Модуль Bytes
module Bytes: sig .. end
Операции с последовательностями байтов.
Последовательность байтов — это изменяемая структура данных, содержащая последовательность байтов фиксированной длины. Доступ к каждому байту для чтения или записи по индексу выполняется за постоянное время.
Для последовательности байтов s длины l мы можем получить доступ к каждому из l байтов s по его индексу в последовательности. Индексация начинается с 0; индекс в s считается допустимым, если он находится в диапазоне [0...l-1] (включительно). Позиция — это точка между двумя байтами либо в начале или конце последовательности. Позиция в s считается допустимой, если она находится в диапазоне [0...l] (включительно). Обратите внимание, что байт с индексом n находится между позициями n и n+1.
Два параметра start и len задают допустимый диапазон в s, если len >= 0 и start, а start+len являются допустимыми позициями в s.
Последовательности байтов можно изменять на месте, например, с помощью описанных ниже функций set и blit. См. также строки (модуль String), которые представляют собой почти такую же структуру данных, но не могут изменяться на месте.
Байты представлены типом OCaml char.
Версию этого модуля с метками можно использовать так, как описано в модуле StdLabels.
- С версии 4.02
val length : bytes -> int
Возвращает длину (количество байтов) аргумента.
val get : bytes -> int -> char
get s n возвращает байт с индексом n в аргументе s.
-
Вызывает исключение
Invalid_argument, еслиnне является допустимым индексом вs.
val set : bytes -> int -> char -> unit
set s n c изменяет s на месте, заменяя байт с индексом n на c.
-
Вызывает исключение
Invalid_argument, еслиnне является допустимым индексом вs.
val create : int -> bytes
create n возвращает новую последовательность байтов длины n. Последовательность не инициализирована и содержит произвольные байты.
-
Вызывает исключение
Invalid_argument, еслиn < 0илиn >Sys.max_string_length.
val make : int -> char -> bytes
make n c возвращает новую последовательность байтов длины n, заполненную байтом c.
-
Вызывает исключение
Invalid_argument, еслиn < 0илиn >Sys.max_string_length.
val init : int -> (int -> char) -> bytes
init n f возвращает новую последовательность байтов длины n, в которой символ i инициализируется результатом f i (в порядке возрастания индексов).
-
Вызывает исключение
Invalid_argument, еслиn < 0илиn >Sys.max_string_length.
val empty : bytes
Последовательность байтов размера 0.
val copy : bytes -> bytes
Возвращает новую последовательность байтов, содержащую те же байты, что и аргумент.
val of_string : string -> bytes
Возвращает новую последовательность байтов, содержащую те же байты, что и заданная строка.
val to_string : bytes -> string
Возвращает новую строку, содержащую те же байты, что и заданная последовательность байтов.
val sub : bytes -> int -> int -> bytes
sub s pos len возвращает новую последовательность байтов длины len, содержащую подпоследовательность s, которая начинается с позиции pos и имеет длину len.
-
Вызывает исключение
Invalid_argument, еслиposиlenне задают допустимый диапазон вs.
val sub_string : bytes -> int -> int -> string
Аналогично Bytes.sub, но возвращает строку вместо последовательности байтов.
val extend : bytes -> int -> int -> bytes
extend s left right возвращает новую последовательность байтов, содержащую байты s, перед которыми добавлено left неинициализированных байтов, а после них — right неинициализированных байтов. Если left или right отрицательно, байты удаляются (вместо добавления) с соответствующей стороны s.
- С версии 4.05 в BytesLabels
-
Вызывает исключение
Invalid_argument, если длина результата отрицательна или превышаетSys.max_string_lengthбайт.
val fill : bytes -> int -> int -> char -> unit
fill s pos len c изменяет s на месте, заменяя len символов на c, начиная с pos.
-
Вызывает исключение
Invalid_argument, еслиposиlenне задают допустимый диапазон вs.
val blit : bytes -> int -> bytes -> int -> int -> unit
blit src src_pos dst dst_pos len копирует len байтов из последовательности байтов src, начиная с индекса src_pos, в последовательность байтов dst, начиная с индекса dst_pos. Функция работает корректно, даже если src и dst — одна и та же последовательность байтов, а интервалы источника и назначения перекрываются.
-
Вызывает исключение
Invalid_argument, еслиsrc_posиlenне задают допустимый диапазон вsrcили еслиdst_posиlenне задают допустимый диапазон вdst.
val blit_string : string -> int -> bytes -> int -> int -> unit
blit_string src src_pos dst dst_pos len копирует len байтов из строки src, начиная с индекса src_pos, в последовательность байтов dst, начиная с индекса dst_pos.
- С версии 4.05 в BytesLabels
-
Вызывает исключение
Invalid_argument, еслиsrc_posиlenне задают допустимый диапазон вsrcили еслиdst_posиlenне задают допустимый диапазон вdst.
val concat : bytes -> bytes list -> bytes
concat sep sl объединяет список последовательностей байтов sl, вставляя между ними разделитель sep, и возвращает результат в виде новой последовательности байтов.
-
Вызывает исключение
Invalid_argument, если результат превышаетSys.max_string_lengthбайт.
val cat : bytes -> bytes -> bytes
cat s1 s2 объединяет s1 и s2 и возвращает результат в виде новой последовательности байтов.
- С версии 4.05 в BytesLabels
-
Вызывает исключение
Invalid_argument, если результат превышаетSys.max_string_lengthбайт.
val iter : (char -> unit) -> bytes -> unit
iter f s последовательно применяет функцию f ко всем байтам s. Это эквивалентно f (get s 0); f (get s 1); ...; f (get s.
(length s - 1)); ()
val iteri : (int -> char -> unit) -> bytes -> unit
Аналогично Bytes.iter, но функция получает индекс байта первым аргументом, а сам байт — вторым.
val map : (char -> char) -> bytes -> bytes
map f s последовательно применяет функцию f ко всем байтам s (в порядке возрастания индексов) и сохраняет полученные байты в новой последовательности, которая возвращается в качестве результата.
val mapi : (int -> char -> char) -> bytes -> bytes
mapi f s вызывает f для каждого символа s и его индекса (в порядке возрастания индексов) и сохраняет полученные байты в новой последовательности, которая возвращается в качестве результата.
val fold_left : ('acc -> char -> 'acc) -> 'acc -> bytes -> 'acc
fold_left f x s вычисляет f (... (f (f x (get s 0)) (get s 1)) ...) (get s (n-1)), где n — длина s.
- С версии 4.13
val fold_right : (char -> 'acc -> 'acc) -> bytes -> 'acc -> 'acc
fold_right f s x вычисляет f (get s 0) (f (get s 1) ( ... (f (get s (n-1)) x) ...)), где n — длина s.
- С версии 4.13
val for_all : (char -> bool) -> bytes -> bool
for_all p s проверяет, удовлетворяют ли все символы в s предикату p.
- С версии 4.13
val exists : (char -> bool) -> bytes -> bool
exists p s проверяет, удовлетворяет ли хотя бы один символ в s предикату p.
- С версии 4.13
val trim : bytes -> bytes
Возвращает копию аргумента без начальных и конечных пробельных символов. К пробельным относятся байты ASCII ' ', '\012', '\n', '\r' и '\t'.
val escaped : bytes -> bytes
Возвращает копию аргумента, в которой специальные символы представлены escape-последовательностями в соответствии с лексическими соглашениями OCaml. Все символы вне печатного диапазона ASCII (32..126), а также обратная косая черта и двойная кавычка экранируются.
-
Вызывает исключение
Invalid_argument, если результат превышаетSys.max_string_lengthбайт.
val index : bytes -> char -> int
index s c возвращает индекс первого вхождения байта c в s.
-
Вызывает исключение
Not_found, еслиcне встречается вs.
val index_opt : bytes -> char -> int option
index_opt s c возвращает индекс первого вхождения байта c в s или None, если c не встречается в s.
- С версии 4.05
val rindex : bytes -> char -> int
rindex s c возвращает индекс последнего вхождения байта c в s.
-
Вызывает исключение
Not_found, еслиcне встречается вs.
val rindex_opt : bytes -> char -> int option
rindex_opt s c возвращает индекс последнего вхождения байта c в s или None, если c не встречается в s.
- С версии 4.05
val index_from : bytes -> int -> char -> int
index_from s i c возвращает индекс первого вхождения байта c в s после позиции i. index s c эквивалентно index_from s 0 c.
-
Вызывает исключение
-
Invalid_argument, еслиiне является допустимой позицией вs. -
Not_found, еслиcне встречается вsпосле позицииi.
-
val index_from_opt : bytes -> int -> char -> int option
index_from_opt s i c возвращает индекс первого вхождения байта c в s после позиции i или None, если c не встречается в s после позиции i. index_opt s c эквивалентно index_from_opt s 0 c.
- С версии 4.05
-
Вызывает исключение
Invalid_argument, еслиiне является допустимой позицией вs.
val rindex_from : bytes -> int -> char -> int
rindex_from s i c возвращает индекс последнего вхождения байта c в s перед позицией i+1. rindex s c эквивалентно rindex_from s (length s - 1) c.
-
Вызывает исключение
-
Invalid_argument, еслиi+1не является допустимой позицией вs. -
Not_found, еслиcне встречается вsперед позициейi+1.
-
val rindex_from_opt : bytes -> int -> char -> int option
rindex_from_opt s i c возвращает индекс последнего вхождения байта c в s перед позицией i+1 или None, если c не встречается в s перед позицией i+1. rindex_opt s c эквивалентно rindex_from s (length s - 1) c.
- С версии 4.05
-
Вызывает исключение
Invalid_argument, еслиi+1не является допустимой позицией вs.
val contains : bytes -> char -> bool
contains s c проверяет, встречается ли байт c в s.
val contains_from : bytes -> int -> char -> bool
contains_from s start c проверяет, встречается ли байт c в s после позиции start. contains s c эквивалентно contains_from.
s 0 c
-
Вызывает исключение
Invalid_argument, еслиstartне является допустимой позицией вs.
val rcontains_from : bytes -> int -> char -> bool
rcontains_from s stop c проверяет, встречается ли байт c в s перед позицией stop+1.
-
Вызывает исключение
Invalid_argument, еслиstop < 0илиstop+1не является допустимой позицией вs.
val uppercase_ascii : bytes -> bytes
Возвращает копию аргумента, в которой все строчные буквы преобразованы в прописные с использованием набора символов US-ASCII.
- С версии 4.03 (4.05 в BytesLabels)
val lowercase_ascii : bytes -> bytes
Возвращает копию аргумента, в которой все прописные буквы преобразованы в строчные с использованием набора символов US-ASCII.
- С версии 4.03 (4.05 в BytesLabels)
val capitalize_ascii : bytes -> bytes
Возвращает копию аргумента, в которой первый символ преобразован в прописную букву с использованием набора символов US-ASCII.
- С версии 4.03 (4.05 в BytesLabels)
val uncapitalize_ascii : bytes -> bytes
Возвращает копию аргумента, в которой первый символ преобразован в строчную букву с использованием набора символов US-ASCII.
- С версии 4.03 (4.05 в BytesLabels)
type t = bytes
Псевдоним типа последовательностей байтов.
val compare : t -> t -> int
val equal : t -> t -> bool
Функция проверки равенства последовательностей байтов.
- С версии 4.03 (4.05 в BytesLabels)
val starts_with : prefix:bytes -> bytes -> bool
starts_with ~prefix s равен true тогда и только тогда, когда s начинается с prefix.
- С версии 4.13
val ends_with : suffix:bytes -> bytes -> bool
ends_with ~suffix s равен true тогда и только тогда, когда s заканчивается на suffix.
- С версии 4.13
Небезопасные преобразования (для опытных пользователей)
В этом разделе описаны небезопасные низкоуровневые функции преобразования между bytes и string. Они не копируют внутренние данные; при неправильном использовании они могут нарушить инвариант неизменяемости строк. Эти функции доступны разработчикам библиотек, обладающим необходимым опытом, но в большинстве случаев следует использовать всегда корректные функции Bytes.to_string и Bytes.of_string.
val unsafe_to_string : bytes -> string
Небезопасно преобразует последовательность байтов в строку.
Чтобы рассуждать об использовании unsafe_to_string, удобно придерживаться дисциплины «владения». Фрагмент кода, работающий с данными, «владеет» ими; существует несколько несовместимых режимов владения, в том числе:
- Исключительное владение: к данным можно обращаться и изменять их
- Совместное владение: у данных несколько владельцев, которые могут только обращаться к ним, но не изменять их.
Исключительное владение линейно: передача данных другому фрагменту кода означает отказ от владения ими (мы больше не можем записывать данные). Исключительный владелец может сделать данные совместно используемыми (отказавшись от права изменять их), но совместно используемые данные уже не могут снова стать объектом исключительного владения.
unsafe_to_string s можно использовать только тогда, когда вызывающий код владеет последовательностью байтов s — исключительным образом или как совместно используемыми неизменяемыми данными. Вызывающий код отказывается от владения s и получает владение возвращаемой строкой.
С этой дисциплиной владения совместимы два варианта использования:
1. Создание строки путем инициализации и изменения последовательности байтов, которая после инициализации больше не изменяется.
let string_init len f : string = let s = Bytes.create len in for i = 0 to len - 1 do Bytes.set s i (f i) done; Bytes.unsafe_to_string s
Эта функция безопасна, поскольку после вызова unsafe_to_string последовательность байтов s больше не будет использоваться или изменяться. Код string_init отказывается от владения s и передает владение полученной строкой вызывающему коду.
Обратите внимание, что функция была бы небезопасной, если бы s передавалась в качестве дополнительного параметра функции f, поскольку таким образом она могла бы сохраниться и быть изменена в будущем: string_init пришлось бы отказаться от владения s, чтобы передать ее в f, и тогда нельзя было бы безопасно вызвать unsafe_to_string.
Мы предоставили функции String.init, String.map и String.mapi, охватывающие большинство случаев создания новых строк. По возможности следует предпочитать их функциям to_string или unsafe_to_string.
2. Временная передача функции владения последовательностью байтов, чтобы она могла работать с эксклюзивно принадлежащей ей строкой и затем вернуть владение, позволяя нам снова изменять последовательность после завершения вызова.
let bytes_length (s : bytes) = String.length (Bytes.unsafe_to_string s)
В этом случае мы не гарантируем, что s не будет изменена после вызова bytes_length s. Функция String.length временно заимствует исключительное владение последовательностью байтов (и видит ее как string), но затем возвращает это владение вызывающему коду, который может считать, что s после вызова по-прежнему является допустимой последовательностью байтов. Обратите внимание: это корректно лишь потому, что мы знаем, что String.length не сохраняет свой аргумент — он может стать доступным через побочный канал, например комбинатор мемоизации.
Вызывающий код не должен изменять s, пока строка заимствована (в это время он временно отказался от владения). Это важно для параллельных программ, а также для функций высшего порядка: если бы String.length возвращала замыкание для последующего вызова, s не следовало бы изменять, пока это замыкание не будет полностью применено и не вернет владение.
val unsafe_of_string : string -> bytes
Небезопасно преобразует совместно используемую строку в последовательность байтов, которую не следует изменять.
Та же дисциплина владения, которая обеспечивает корректность unsafe_to_string, применима и к unsafe_of_string: эту функцию можно использовать, если вы владели значением string, и возвращаемым значением bytes будете владеть в том же режиме.
На практике корректно рассуждать об исключительном владении строковыми значениями чрезвычайно сложно. Всегда следует считать строки совместно используемыми, а не находящимися в исключительном владении.
Например, строковые литералы неявно совместно используются компилятором, поэтому они никогда не находятся в вашем исключительном владении.
let incorrect = Bytes.unsafe_of_string "hello"
let s = Bytes.of_string "hello"
Первое объявление некорректно, поскольку строковый литерал "hello" может совместно использоваться компилятором с другими частями программы, а изменение incorrect является ошибкой. Всегда следует использовать второй вариант, который создает копию и поэтому является корректным.
Также некорректно предполагать исключительное владение строками, которые не являются строковыми литералами, но частично или полностью построены из строковых литералов. Например, изменение unsafe_of_string ("foo" ^ s) может изменить совместно используемую строку "foo" — если предположить представление строк в виде дерева. В более общем случае функции, работающие со строками, предполагают совместное владение и не сохраняют исключительное владение. Поэтому неверно предполагать исключительное владение результатом unsafe_of_string.
Единственный случай, который, по нашему мнению, достаточно безопасен: созданное значение bytes совместно используется и применяется как неизменяемая последовательность байтов. Это может пригодиться при постепенном переносе низкоуровневых программ, работающих с неизменяемыми последовательностями байтов (например, Marshal.from_bytes), которые ранее использовали для этой цели тип string.
val split_on_char : char -> bytes -> bytes list
split_on_char sep s возвращает список всех (возможно, пустых) подпоследовательностей s, разделенных символом sep. Если s пуст, результатом будет список из одного элемента [empty].
Результат функции определяется следующими инвариантами:
- Список не пуст.
- Объединение его элементов с использованием
sepв качестве разделителя дает последовательность байтов, равную исходной (Bytes.concat (Bytes.make 1 sep)).
(Bytes.split_on_char sep s) = s - Ни одна последовательность байтов в результате не содержит символ
sep.
- С версии 4.13
Итераторы
val to_seq : t -> char Seq.t
Выполняет итерацию по строке в порядке возрастания индексов. Изменения строки во время итерации будут отражены в последовательности.
- С версии 4.07
val to_seqi : t -> (int * char) Seq.t
Выполняет итерацию по строке в порядке возрастания индексов, возвращая индексы вместе с символами
- С версии 4.07
val of_seq : char Seq.t -> t
Создает строку из генератора
- С версии 4.07
Кодеки и проверки UTF
UTF-8
val get_utf_8_uchar : t -> int -> Uchar.utf_decode
get_utf_8_uchar b i декодирует символ UTF-8 с индексом i в b.
val set_utf_8_uchar : t -> int -> Uchar.t -> int
set_utf_8_uchar b i u кодирует u в формате UTF-8 по индексу i в b и возвращает количество байтов n, записанных начиная с i. Если n равно 0, места для кодирования u в i было недостаточно, и b осталось нетронутым. В противном случае по адресу i + n можно закодировать новый символ.
val is_valid_utf_8 : t -> bool
is_valid_utf_8 b равно true тогда и только тогда, когда b содержит корректные данные UTF-8.
UTF-16BE
val get_utf_16be_uchar : t -> int -> Uchar.utf_decode
get_utf_16be_uchar b i декодирует символ UTF-16BE с индексом i в b.
val set_utf_16be_uchar : t -> int -> Uchar.t -> int
set_utf_16be_uchar b i u кодирует u в формате UTF-16BE по индексу i в b и возвращает количество байтов n, записанных начиная с i. Если n равно 0, места для кодирования u в i было недостаточно, и b осталось нетронутым. В противном случае по адресу i + n можно закодировать новый символ.
val is_valid_utf_16be : t -> bool
is_valid_utf_16be b равно true тогда и только тогда, когда b содержит корректные данные UTF-16BE.
UTF-16LE
val get_utf_16le_uchar : t -> int -> Uchar.utf_decode
get_utf_16le_uchar b i декодирует символ UTF-16LE с индексом i в b.
val set_utf_16le_uchar : t -> int -> Uchar.t -> int
set_utf_16le_uchar b i u кодирует u в формате UTF-16LE по индексу i в b и возвращает количество байтов n, записанных начиная с i. Если n равно 0, места для кодирования u в i было недостаточно, и b осталось нетронутым. В противном случае по адресу i + n можно закодировать новый символ.
val is_valid_utf_16le : t -> bool
is_valid_utf_16le b равно true тогда и только тогда, когда b содержит корректные данные UTF-16LE.
Двоичное кодирование и декодирование целых чисел
Функции этого раздела выполняют двоичное кодирование и декодирование целых чисел в последовательности байтов и из них.
Все следующие функции вызывают Invalid_argument, если пространство, необходимое по индексу i для декодирования или кодирования целого числа, недоступно.
Кодирование в порядке от младшего к старшему (соответственно, от старшего к младшему) означает, что сначала сохраняются наименее (соответственно, наиболее) значащие байты. Порядок от старшего к младшему также известен как сетевой порядок байтов. Кодирование в нативном порядке байтов выполняется от младшего к старшему или от старшего к младшему в зависимости от Sys.big_endian.
32- и 64-битные целые числа представлены типами int32 и int64, которые можно интерпретировать как числа со знаком или без знака.
8- и 16-битные целые числа представлены типом int, который содержит больше битов, чем двоичное представление. Дополнительные биты обрабатываются следующим образом:
- Функции, декодирующие знаковые (соответственно, беззнаковые) 8- или 16-битные целые числа, представленные значениями
int, расширяют результат знаком (соответственно, нулём). - Функции, кодирующие 8- или 16-битные целые числа, представленные значениями
int, усекают входное значение до его наименее значащих байтов.
val get_uint8 : bytes -> int -> int
get_uint8 b i — это беззнаковое 8-битное целое число из b, начинающееся с байтового индекса i.
- Начиная с версии 4.08
val get_int8 : bytes -> int -> int
get_int8 b i — это знаковое 8-битное целое число из b, начинающееся с байтового индекса i.
- Начиная с версии 4.08
val get_uint16_ne : bytes -> int -> int
get_uint16_ne b i — это беззнаковое 16-битное целое число из b в нативном порядке байтов, начинающееся с байтового индекса i.
- Начиная с версии 4.08
val get_uint16_be : bytes -> int -> int
get_uint16_be b i — это беззнаковое 16-битное целое число из b в порядке от старшего к младшему, начинающееся с байтового индекса i.
- Начиная с версии 4.08
val get_uint16_le : bytes -> int -> int
get_uint16_le b i — это беззнаковое 16-битное целое число из b в порядке от младшего к старшему, начинающееся с байтового индекса i.
- Начиная с версии 4.08
val get_int16_ne : bytes -> int -> int
get_int16_ne b i — это знаковое 16-битное целое число из b в нативном порядке байтов, начинающееся с байтового индекса i.
- Начиная с версии 4.08
val get_int16_be : bytes -> int -> int
get_int16_be b i — это знаковое 16-битное целое число из b в порядке от старшего к младшему, начинающееся с байтового индекса i.
- Начиная с версии 4.08
val get_int16_le : bytes -> int -> int
get_int16_le b i — это знаковое 16-битное целое число из b в порядке от младшего к старшему, начинающееся с байтового индекса i.
- Начиная с версии 4.08
val get_int32_ne : bytes -> int -> int32
get_int32_ne b i — это 32-битное целое число из b в нативном порядке байтов, начинающееся с байтового индекса i.
- Начиная с версии 4.08
val get_int32_be : bytes -> int -> int32
get_int32_be b i — это 32-битное целое число из b в порядке от старшего к младшему, начинающееся с байтового индекса i.
- Начиная с версии 4.08
val get_int32_le : bytes -> int -> int32
get_int32_le b i — это 32-битное целое число из b в порядке от младшего к старшему, начинающееся с байтового индекса i.
- Начиная с версии 4.08
val get_int64_ne : bytes -> int -> int64
get_int64_ne b i — это 64-битное целое число из b в нативном порядке байтов, начинающееся с байтового индекса i.
- Начиная с версии 4.08
val get_int64_be : bytes -> int -> int64
get_int64_be b i — это 64-битное целое число из b в порядке от старшего к младшему, начинающееся с байтового индекса i.
- Начиная с версии 4.08
val get_int64_le : bytes -> int -> int64
get_int64_le b i — это 64-битное целое число из b в порядке от младшего к старшему, начинающееся с байтового индекса i.
- Начиная с версии 4.08
val set_uint8 : bytes -> int -> int -> unit
set_uint8 b i v устанавливает беззнаковое 8-битное целое число в b, начиная с байтового индекса i, в значение v.
- Начиная с версии 4.08
val set_int8 : bytes -> int -> int -> unit
set_int8 b i v устанавливает знаковое 8-битное целое число в b, начиная с байтового индекса i, в значение v.
- Начиная с версии 4.08
val set_uint16_ne : bytes -> int -> int -> unit
set_uint16_ne b i v устанавливает беззнаковое 16-битное целое число в b в нативном порядке байтов, начиная с байтового индекса i, в значение v.
- Начиная с версии 4.08
val set_uint16_be : bytes -> int -> int -> unit
set_uint16_be b i v устанавливает беззнаковое 16-битное целое число в b в порядке от старшего к младшему, начиная с байтового индекса i, в значение v.
- Начиная с версии 4.08
val set_uint16_le : bytes -> int -> int -> unit
set_uint16_le b i v устанавливает беззнаковое 16-битное целое число в b в порядке от младшего к старшему, начиная с байтового индекса i, в значение v.
- Начиная с версии 4.08
val set_int16_ne : bytes -> int -> int -> unit
set_int16_ne b i v устанавливает знаковое 16-битное целое число в b в нативном порядке байтов, начиная с байтового индекса i, в значение v.
- Начиная с версии 4.08
val set_int16_be : bytes -> int -> int -> unit
set_int16_be b i v устанавливает знаковое 16-битное целое число в b в порядке от старшего к младшему, начиная с байтового индекса i, в значение v.
- Начиная с версии 4.08
val set_int16_le : bytes -> int -> int -> unit
set_int16_le b i v устанавливает знаковое 16-битное целое число в b в порядке от младшего к старшему, начиная с байтового индекса i, в значение v.
- Начиная с версии 4.08
val set_int32_ne : bytes -> int -> int32 -> unit
set_int32_ne b i v устанавливает 32-битное целое число в b в нативном порядке байтов, начиная с байтового индекса i, в значение v.
- Начиная с версии 4.08
val set_int32_be : bytes -> int -> int32 -> unit
set_int32_be b i v устанавливает 32-битное целое число в b в порядке от старшего к младшему, начиная с байтового индекса i, в значение v.
- Начиная с версии 4.08
val set_int32_le : bytes -> int -> int32 -> unit
set_int32_le b i v устанавливает 32-битное целое число в b в порядке от младшего к старшему, начиная с байтового индекса i, в значение v.
- Начиная с версии 4.08
val set_int64_ne : bytes -> int -> int64 -> unit
set_int64_ne b i v устанавливает 64-битное целое число в b в нативном порядке байтов, начиная с байтового индекса i, в значение v.
- Начиная с версии 4.08
val set_int64_be : bytes -> int -> int64 -> unit
set_int64_be b i v устанавливает 64-битное целое число в b в порядке от старшего к младшему, начиная с байтового индекса i, в значение v.
- Начиная с версии 4.08
val set_int64_le : bytes -> int -> int64 -> unit
set_int64_le b i v устанавливает 64-битное целое число в b в порядке от младшего к старшему, начиная с байтового индекса i, в значение v.
- Начиная с версии 4.08
Последовательности байтов и безопасность при параллельном выполнении
При параллельном доступе к последовательностям байтов из нескольких доменов следует соблюдать осторожность: обращение к последовательности байтов никогда не приведёт к аварийному завершению программы, но несинхронизированный доступ может дать неожиданные результаты (не соответствующие последовательной согласованности).
Атомарность
Любая операция с последовательностью байтов, обращающаяся более чем к одному байту, не является атомарной. Сюда входят итерация и сканирование.
Например, рассмотрим следующую программу:
let size = 100_000_000 let b = Bytes.make size ' ' let update b f () = Bytes.iteri (fun i x -> Bytes.set b i (Char.chr (f (Char.code x)))) b let d1 = Domain.spawn (update b (fun x -> x + 1)) let d2 = Domain.spawn (update b (fun x -> 2 * x + 1)) let () = Domain.join d1; Domain.join d2
последовательность байтов b может содержать недетерминированную смесь значений '!', 'A', 'B' и 'C'.
После выполнения этого кода каждый байт последовательности b будет равен '!', 'A', 'B' или 'C'. Если требуется атомарность, пользователь должен реализовать собственную синхронизацию (например, используя Mutex.t).
Состояния гонки данных
Если два домена обращаются только к непересекающимся частям последовательности байтов, наблюдаемое поведение эквивалентно некоторому последовательному чередованию операций из этих двух доменов.
Состояние гонки данных возникает, когда два домена без синхронизации обращаются к одному и тому же байту и хотя бы одно из обращений является записью. При отсутствии состояний гонки данных наблюдаемое поведение эквивалентно некоторому последовательному чередованию операций из разных доменов.
По возможности следует избегать состояний гонки данных, используя синхронизацию для упорядочивания обращений к элементам последовательности.
Действительно, при наличии состояний гонки данных программы не аварийно завершаются, но наблюдаемое поведение может быть неэквивалентно никакому последовательному чередованию операций из разных доменов. Тем не менее даже при наличии состояний гонки данных операция чтения вернёт значение одной из предшествующих записей в эту ячейку.
Доступы разного размера
Ещё один тонкий момент: если состояние гонки данных включает записи и чтения разного размера в одну и ту же область, порядок, в котором домены наблюдают эти записи и чтения, не определён. Например, следующий код последовательно записывает 32-битное целое число и char по одному и тому же индексу
let b = Bytes.make 10 '\000' let d1 = Domain.spawn (fun () -> Bytes.set_int32_ne b 0 100; b.[0] <- 'd' )
В этой ситуации домен, наблюдающий запись значения 'd' в b.0, не обязательно также увидит запись в индексы 1, 2 или 3.
© 1995-2026 INRIA.
https://ocaml.org/manual/5.5/api/Bytes.html