Модуль BytesLabels
module BytesLabels: 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 -> f:(int -> char) -> bytes
init n f возвращает новую последовательность байтов длины n, в которой символ i инициализируется результатом f i (в порядке возрастания индексов).
-
Вызывает исключение
Invalid_argument, еслиn < 0илиn >Sys.max_string_length.
val empty : bytes
Последовательность байтов нулевого размера.
val copy : bytes -> bytes
Возвращает новую последовательность байтов, содержащую те же байты, что и аргумент.
val of_string : string -> bytes
Возвращает новую последовательность байтов, содержащую те же байты, что и заданная строка.
val to_string : bytes -> string
Возвращает новую строку, содержащую те же байты, что и заданная последовательность байтов.
val sub : bytes -> pos:int -> len:int -> bytes
sub s ~pos ~len возвращает новую последовательность байтов длины len, содержащую подпоследовательность s, которая начинается с позиции pos и имеет длину len.
-
Вызывает исключение
Invalid_argument, еслиposиlenне задают допустимый диапазон вs.
val sub_string : bytes -> pos:int -> len:int -> string
То же, что и BytesLabels.sub, но возвращает строку вместо последовательности байтов.
val extend : bytes -> left:int -> right:int -> bytes
extend s ~left ~right возвращает новую последовательность байтов, содержащую байты s, перед которыми добавлено left неинициализированных байтов, а после — right неинициализированных байтов. Если left или right отрицательно, байты удаляются (вместо добавления) с соответствующей стороны s.
- Начиная с 4.05 в BytesLabels
-
Вызывает исключение
Invalid_argument, если длина результата отрицательна или превышаетSys.max_string_lengthбайтов.
val fill : bytes -> pos:int -> len:int -> char -> unit
fill s ~pos ~len c изменяет s на месте, заменяя len символов на c, начиная с pos.
-
Вызывает исключение
Invalid_argument, еслиposиlenне задают допустимый диапазон вs.
val blit : src:bytes -> src_pos:int -> dst:bytes -> dst_pos:int -> len: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 : src:string -> src_pos:int -> dst:bytes -> dst_pos:int -> len: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 : sep: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 : f:(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 : f:(int -> char -> unit) -> bytes -> unit
То же, что и BytesLabels.iter, но функция получает индекс байта в качестве первого аргумента, а сам байт — в качестве второго.
val map : f:(char -> char) -> bytes -> bytes
map ~f s последовательно применяет функцию f ко всем байтам s (в порядке возрастания индексов) и сохраняет полученные байты в новой последовательности, которую возвращает в качестве результата.
val mapi : f:(int -> char -> char) -> bytes -> bytes
mapi ~f s вызывает f для каждого символа s и его индекса (в порядке возрастания индексов), а полученные байты сохраняет в новой последовательности, которую возвращает в качестве результата.
val fold_left : f:('acc -> char -> 'acc) -> init:'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 : f:(char -> 'acc -> 'acc) -> bytes -> init:'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 : f:(char -> bool) -> bytes -> bool
for_all p s проверяет, удовлетворяют ли все символы в s предикату p.
- Начиная с 4.13
val exists : f:(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.05
val lowercase_ascii : bytes -> bytes
Возвращает копию аргумента, в которой все прописные буквы преобразованы в строчные с использованием набора символов US-ASCII.
- Начиная с 4.05
val capitalize_ascii : bytes -> bytes
Возвращает копию аргумента, в которой первый символ преобразован в прописную букву с использованием набора символов US-ASCII.
- Начиная с 4.05
val uncapitalize_ascii : bytes -> bytes
Возвращает копию аргумента, в которой первый символ преобразован в строчную букву с использованием набора символов US-ASCII.
- Начиная с 4.05
type t = bytes
Псевдоним типа последовательностей байтов.
val compare : t -> t -> int
val equal : t -> t -> bool
Функция проверки равенства последовательностей байтов.
- Начиная с 4.05
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. Они не копируют внутренние данные; при неправильном использовании они могут нарушить инвариант неизменяемости строк. Эти функции доступны опытным авторам библиотек, но в большинстве случаев следует использовать всегда корректные функции BytesLabels.to_string и BytesLabels.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
Эта функция безопасна, поскольку к последовательности байтов s больше никогда не будут обращаться и её не будут изменять после вызова unsafe_to_string. Код 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" — если предположить, что строки представлены в виде, подобном rope. В общем случае функции, работающие со строками, предполагают совместное владение и не сохраняют единоличное владение. Поэтому предполагать единоличное владение результатом unsafe_of_string некорректно.
Единственный случай, в котором мы с достаточной уверенностью можем считать это безопасным, — если созданное значение bytes используется совместно как неизменяемая последовательность байтов. Это может быть полезно для постепенной миграции низкоуровневых программ, работающих с неизменяемыми последовательностями байтов (например, Marshal.from_bytes) и ранее использовавших для этой цели тип string.
val split_on_char : sep: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 записывает значение v как беззнаковое 8-битное целое число в b, начиная с байтовой позиции i.
- Начиная с версии 4.08
val set_int8 : bytes -> int -> int -> unit
set_int8 b i v записывает значение v как знаковое 8-битное целое число в b, начиная с байтовой позиции i.
- Начиная с версии 4.08
val set_uint16_ne : bytes -> int -> int -> unit
set_uint16_ne b i v записывает значение v как беззнаковое 16-битное целое число в порядке байтов платформы в b, начиная с байтовой позиции i.
- Начиная с версии 4.08
val set_uint16_be : bytes -> int -> int -> unit
set_uint16_be b i v записывает значение v как беззнаковое 16-битное целое число с порядком байтов от старшего к младшему в b, начиная с байтовой позиции i.
- Начиная с версии 4.08
val set_uint16_le : bytes -> int -> int -> unit
set_uint16_le b i v записывает значение v как беззнаковое 16-битное целое число с порядком байтов от младшего к старшему в b, начиная с байтовой позиции i.
- Начиная с версии 4.08
val set_int16_ne : bytes -> int -> int -> unit
set_int16_ne b i v записывает значение v как знаковое 16-битное целое число в порядке байтов платформы в b, начиная с байтовой позиции i.
- Начиная с версии 4.08
val set_int16_be : bytes -> int -> int -> unit
set_int16_be b i v записывает значение v как знаковое 16-битное целое число с порядком байтов от старшего к младшему в b, начиная с байтовой позиции i.
- Начиная с версии 4.08
val set_int16_le : bytes -> int -> int -> unit
set_int16_le b i v записывает значение v как знаковое 16-битное целое число с порядком байтов от младшего к старшему в b, начиная с байтовой позиции i.
- Начиная с версии 4.08
val set_int32_ne : bytes -> int -> int32 -> unit
set_int32_ne b i v записывает значение v как 32-битное целое число в порядке байтов платформы в b, начиная с байтовой позиции i.
- Начиная с версии 4.08
val set_int32_be : bytes -> int -> int32 -> unit
set_int32_be b i v записывает значение v как 32-битное целое число с порядком байтов от старшего к младшему в b, начиная с байтовой позиции i.
- Начиная с версии 4.08
val set_int32_le : bytes -> int -> int32 -> unit
set_int32_le b i v записывает значение v как 32-битное целое число с порядком байтов от младшего к старшему в b, начиная с байтовой позиции i.
- Начиная с версии 4.08
val set_int64_ne : bytes -> int -> int64 -> unit
set_int64_ne b i v записывает значение v как 64-битное целое число в порядке байтов платформы в b, начиная с байтовой позиции i.
- Начиная с версии 4.08
val set_int64_be : bytes -> int -> int64 -> unit
set_int64_be b i v записывает значение v как 64-битное целое число с порядком байтов от старшего к младшему в b, начиная с байтовой позиции i.
- Начиная с версии 4.08
val set_int64_le : bytes -> int -> int64 -> unit
set_int64_le b i v записывает значение v как 64-битное целое число с порядком байтов от младшего к старшему в b, начиная с байтовой позиции i.
- Начиная с версии 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/BytesLabels.html