Something went wrong. Try again.
An experimental library which implements a subset of the apache arrow format in ocaml.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101(* See buffer.mli for the contract and the alignment invariant. *)
type bytes_ba = (int, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
type bigarray = bytes_ba
(* [data] is a view into a larger allocation, positioned so its first byte is 64-byte aligned (for buffers from [create]). [read_only] is set on [sub] views, which share storage and must not be mutated through this handle. *)type t = { data : bytes_ba; len : int; read_only : bool }
let alignment = 64
(* The raw address of a Bigarray's first byte; see buffer_stubs.c. *)external address_of : bytes_ba -> nativeint = "arrow_buffer_address"
(* Padding (0 .. alignment-1) to add to [addr] to reach the next multiple of [alignment]. *)let padding_to_align addr = let m = Nativeint.to_int (Nativeint.rem addr (Nativeint.of_int alignment)) in if m = 0 then 0 else alignment - m
let create ~len = if len < 0 then invalid_arg "Arrow.Buffer.create: negative length"; (* Over-allocate by a full alignment so any starting address can be shifted up to a 64-byte boundary with [len] bytes still in range. *) let raw = Bigarray.Array1.create Bigarray.int8_unsigned Bigarray.c_layout (len + alignment) in let pad = padding_to_align (address_of raw) in let data = Bigarray.Array1.sub raw pad len in Bigarray.Array1.fill data 0; { data; len; read_only = false }
let of_bigarray ?(read_only = false) data = { data; len = Bigarray.Array1.dim data; read_only }
let length t = t.lenlet base_address t = address_of t.data
let is_aligned t = Nativeint.equal (Nativeint.rem (base_address t) (Nativeint.of_int alignment)) 0n
let get t i = Bigarray.Array1.get t.data i
let set t i v = if t.read_only then invalid_arg "Arrow.Buffer.set: read-only view"; Bigarray.Array1.set t.data i v
(* Bounds check shared by every blit; raising up front avoids a partial copy. *)let check_blit ~name ~src_len ~src_pos ~dst_len ~dst_pos ~len = if len < 0 || src_pos < 0 || dst_pos < 0 || src_pos + len > src_len || dst_pos + len > dst_len then invalid_arg name
let blit_from_bytes ~src ~src_pos t ~dst_pos ~len = if t.read_only then invalid_arg "Arrow.Buffer.blit_from_bytes: read-only view"; check_blit ~name:"Arrow.Buffer.blit_from_bytes" ~src_len:(Bytes.length src) ~src_pos ~dst_len:t.len ~dst_pos ~len; for i = 0 to len - 1 do Bigarray.Array1.unsafe_set t.data (dst_pos + i) (Char.code (Bytes.unsafe_get src (src_pos + i))) done
let blit_from_string ~src ~src_pos t ~dst_pos ~len = if t.read_only then invalid_arg "Arrow.Buffer.blit_from_string: read-only view"; check_blit ~name:"Arrow.Buffer.blit_from_string" ~src_len:(String.length src) ~src_pos ~dst_len:t.len ~dst_pos ~len; for i = 0 to len - 1 do Bigarray.Array1.unsafe_set t.data (dst_pos + i) (Char.code (String.unsafe_get src (src_pos + i))) done
let blit_to_bytes t ~src_pos ~dst ~dst_pos ~len = check_blit ~name:"Arrow.Buffer.blit_to_bytes" ~src_len:t.len ~src_pos ~dst_len:(Bytes.length dst) ~dst_pos ~len; for i = 0 to len - 1 do Bytes.unsafe_set dst (dst_pos + i) (Char.unsafe_chr (Bigarray.Array1.unsafe_get t.data (src_pos + i))) done
let blit ~src ~src_pos ~dst ~dst_pos ~len = if dst.read_only then invalid_arg "Arrow.Buffer.blit: read-only view"; check_blit ~name:"Arrow.Buffer.blit" ~src_len:src.len ~src_pos ~dst_len:dst.len ~dst_pos ~len; (* One memcpy (memmove semantics when the ranges overlap). *) Bigarray.Array1.blit (Bigarray.Array1.sub src.data src_pos len) (Bigarray.Array1.sub dst.data dst_pos len)
let sub t ~pos ~len = if pos < 0 || len < 0 || pos + len > t.len then invalid_arg "Arrow.Buffer.sub"; { data = Bigarray.Array1.sub t.data pos len; len; read_only = true }