Работа с байтами
Видео-иллюстрация из серии OCaml Tips
Смотреть на [YouTube](https://youtu.be/Wk58dQ1IMZI).Стандартные средства (стандартная библиотека OCaml'а) предлагает достаточно богатые возможности по работе с бинарными данными благодаря соответствующим функциям из модулей Bytes и String.
Строки и байты
На данный момент в OCaml представлено два типа для представления последовательности байт фиксированной длины: тип bytes и тип string. Исторически изначально строки были изменяемыми и тип байтов отсутствовал, так как строки не обязательно должны содержать текстовую информации, но с LTS четвертой версии они стали неизменяемыми. Поэтому потребовался некий другой интерфейс для мутаций строк –– так инструментом и стал тип bytes и одноименный модуль, почти полностью повторявший модуль строк.
Тут стоит ясно понимать, что строки и байты в OCaml это одна и та же сущность и все это в рантайми исторически называется строками. Это можно легко доказать следующим кодом.
let string_value = "Hello!" in
let bytes_value = Bytes.of_string string_value in
assert (Obj.(tag (repr string_value) = string_tag));
assert (Obj.(tag (repr bytes_value) = string_tag))Также необходимо понимать, что имея одно представление с двумя интерфейсами, непременно между ними будут преобразования, а при преобразовании между двумя интерфейсами их абстракции должны быть гарантированны.
На практике это сводится к тому, что преобразования между bytes и string всегда сопровождаются копированием!
(* bytes.ml *)
let to_string b = unsafe_to_string (copy b)
let of_string s = copy (unsafe_of_string s)Если вы хотите избавиться от лишних аллокаций, то вам придется взять на себя ответственность за выполнение гарантий абстракций. Подробнее читайте в секции zero-cost преобразования.
Функции кодирования и декодирования
См. https://ocaml.org/manual/api/Bytes.html#1_Binaryencodingdecodingofintegers
Пример использования данных функций:
let load_address addr =
let command = Bytes.create 4 in
Bytes.set_uint8 command 0 Message.cmnd_stk_load_address;
Bytes.set_uint16_le command 1 addr;
Bytes.set_uint8 command 3 Message.sync_crc_eop;
command