This type is a compiler witness that 'rw and 'seek do not affect layout; it enables wider use of unboxed GADTs.
type (-'data_perm_read_write, +'seek_permission) t = private t_repr
The first type parameter controls whether the iobuf can be written to. The second type parameter controls whether the window and limits can be changed.
Perms module for information on how the first type parameter is used.
seek access, a function's type uses
_ rather than
no_seek as the type argument to
_ allows the function to be directly applied to either permission. Using a specific permission would require code to use coercion
There is no
t_of_sexp. One should use
@sexp.opaque as desired.
type ('rw, 'seek) iobuf := ( 'rw, 'seek ) t
type ('rw, 'seek) t_with_shallow_sexp = ( 'rw, 'seek ) t
t_with_shallow_sexp has a
sexp_of that shows the windows and limits of the underlying bigstring, but no data. We do this rather than deriving sexp_of on
t because it is much more likely to be noise than useful information, and so callers should probably not display the iobuf at all.
Window.Hexdump submodule that renders the contents of
Limits.Hexdump submodule that renders the contents of
Hexdump submodule that renders the contents of
t's window and limits using indices relative to the limits.
module Hexdump : sig ... end
module Debug : sig ... end
Debug.Hexdump submodule that renders the contents of
t's window, limits, and underlying bigstring using indices relative to the bigstring.
val create : len:int -> ( _, _ ) t
create ~len creates a new iobuf, backed by a bigstring of length
len, with the limits and window set to the entire bigstring.
of_bigstring bigstring ~pos ~len returns an iobuf backed by
bigstring, with the window and limits specified starting at
pos and of length
immutable to prevent aliasing
val of_string : string -> ( _, _ ) t
of_string s returns a new iobuf whose contents are
sub_shared t ~pos ~len returns a new iobuf with limits and window set to the subrange of
t's window specified by
sub_shared preserves data permissions, but allows arbitrary seek permissions on the resulting iobuf.
copy t returns a new iobuf whose contents are the same as those in the window of
clone t returns a new iobuf that is a deep-copy of
t including an exact copy of the underlying buffer and bounds. This means data outside the window is copied as well.
transfer ~src ~dst makes the window of
dst into a copy of the window of
transfer will raise if
Iobuf.length dst <
It is a utility function defined as
reset dst; blito ~src ~dst; flip_lo dst.
set_bounds_and_buffer ~src ~dst copies bounds metadata (i.e., limits and window) and shallowly copies the buffer (data pointer) from
dst. It does not access data, but does allow access through
dst. This makes
dst an alias of
set_bounds_and_buffer creates an alias, we disallow immutable
[> write]. Otherwise, one of
dst could be
read and the other
immutable :> read, which would allow you to write the
immutable alias's data through the
set_bounds_and_buffer is typically used with a frame iobuf that need only be allocated once. This frame can be updated repeatedly and handed to users, without further allocation. Allocation-sensitive applications need this.
val set_bounds_and_buffer_sub : pos:int -> len:int -> src:( [> Core.write ] as 'data, _ ) t -> dst:( 'data, seek ) t -> unit
set_bounds_and_buffer_sub ~pos ~len ~src ~dst is a more efficient version of
set_bounds_and_buffer ~src:(Iobuf.sub_shared ~pos ~len src) ~dst.
set_bounds_and_buffer ~src ~dst is not the same as
~src ~len:(Iobuf.length src) because the limits are narrowed in the latter case.
~pos are mandatory for performance reasons, in concert with
@@inline. If they were optional, allocation would be necessary when passing a non-default, non-constant value, which is an important use case.
One may wonder why you'd want to call
no_seek, given that a cast is already possible, e.g.,
t : (_, seek) t :> (_, no_seek) t. It turns out that if you want to define some
f : (_, _) t -> unit of your own that can be conveniently applied to
seek iobufs without the user having to cast
seek up, you need this
read_only is more of a historical convenience now that
read_write is a polymorphic variant, as one can now explicitly specify the general type for an argument with something like
t : (_ perms, _) t :> (read, _) t.
val capacity : ( _, _ ) t -> int
capacity t returns the size of
t's limits subrange. The capacity of an iobuf can be reduced via
val length : ( _, _ ) t -> int
length t returns the size of
val length_lo : ( _, _ ) t -> int
length_lo t returns the length that
t's window would have after calling
flip_lo, without actually changing the window. This is the number of bytes between the lower limit and the start of the window.
When you're writing to the window, you can think of this as the number of bytes already written. When reading from the window, this can mean the number of bytes already consumed.
This is equivalent to:
Iobuf.Expert.(lo t - lo_min t)
val length_hi : ( _, _ ) t -> int
length_hi t returns the length that
t's window would have after calling
flip_hi, without actually changing the window. This is the number of bytes between the end of the window and the upper limit of the buffer.
This is equivalent to:
Iobuf.Expert.(hi_max t - hi t)
val is_empty : ( _, _ ) t -> bool
is_empty t is
length t = 0.
narrow_lo t sets
t's lower limit to the beginning of the current window.
narrow_hi t sets
t's upper limit to the end of the current window.
memcmp a b first compares the length of
b's windows and then compares the bytes in the windows for equivalence.
One can call
Lo_bound.window t to get a snapshot of the lower bound of the window, and then later restore that snapshot with
Lo_bound.restore. This is useful for speculatively parsing, and then rewinding when there isn't enough data to finish.
Using a snapshot with a different iobuf, even a sub iobuf of the snapshotted one, has unspecified results. An exception may be raised, or a silent error may occur. However, the safety guarantees of the iobuf will not be violated, i.e., the attempt will not enlarge the limits of the subject iobuf.
module type Bound = sig ... end
advance t amount advances the lower bound of the window by
amount. It is an error to advance past the upper bound of the window or the lower limit.
unsafe_advance is like
advance but with no bounds checking, so incorrect usage can easily cause segfaults.
resize t sets the length of
t's window, provided it does not exceed limits.
unsafe_resize is like
resize but with no bounds checking, so incorrect usage can easily cause segfaults.
flip_lo t sets the window to range from the lower limit to the lower bound of the old window. This is typically called after a series of
Fills, to reposition the window in preparation to
Consume the newly written data.
The bounded version narrows the effective limit. This can preserve some data near the limit, such as a hypothetical packet header (in the case of
bounded_flip_lo) or unfilled suffix of a buffer (in
compact t copies data from the window to the lower limit of the iobuf and sets the window to range from the end of the copied data to the upper limit. This is typically called after a series of
Consumes to save unread data and prepare for the next series of
flip_hi t sets the window to range from the the upper bound of the current window to the upper limit. This operation is dual to
flip_lo and is typically called when the data in the current (narrowed) window has been processed and the window needs to be positioned over the remaining data in the buffer. For example:
(* ... determine initial_data_len ... *) Iobuf.resize buf ~len:initial_data_len; (* ... and process initial data ... *) Iobuf.flip_hi buf;
Now the window of
buf ranges over the remainder of the data.
protect_window_and_bounds t ~f calls
f t with
t's bounds set to its current window, and restores
t's window, bounds, and buffer afterward.
val protect_window_and_bounds_1 : ( 'rw, no_seek ) t -> 'a -> f:( ( 'rw, seek ) t -> 'a -> 'b ) -> 'b
protect_window_and_bounds_1 t x ~f is a more efficient version of
protect_window_and_bounds t ~f:(fun t -> f t x).
val protect_window_and_bounds_2 : ( 'rw, no_seek ) t -> 'a -> 'b -> f:( ( 'rw, seek ) t -> 'a -> 'b -> 'c ) -> 'c
protect_window_and_bounds_2 t x y ~f is a more efficient version of
protect_window_and_bounds t ~f:(fun t -> f t x y).
val protect_window_and_bounds_3 : ( 'rw, no_seek ) t -> 'a -> 'b -> 'c -> f:( ( 'rw, seek ) t -> 'a -> 'b -> 'c -> 'd ) -> 'd
protect_window_and_bounds_3 t x y z ~f is a more efficient version of
protect_window_and_bounds t ~f:(fun t -> f t x y z).
"consume" and "fill" functions access data at the lower bound of the window and advance the lower bound of the window. "peek" and "poke" functions access data but do not advance the window.
to_string t returns the bytes in
t as a string. It does not alter the window.
val to_string_hum : ?max_lines:int -> ( _, _ ) t -> string
t's windows and limits.
to_bytes t returns the bytes in
t as a bytes. It does not alter the window.
module Consume : sig ... end
Consume.string t ~len reads
len characters (all, by default) from
t into a new string and advances the lower bound of the window accordingly.
module Fill : sig ... end
Fill.bin_prot X.bin_write_t t x writes
t in bin-prot form, advancing past the bytes written.
module Peek : sig ... end
Poke functions access a value at
pos from the lower bound of the window and do not advance.
module Poke : sig ... end
Poke.bin_prot X.bin_write_t t x writes
x to the beginning of
t in binary form without advancing. You can use
X.bin_size_t to tell how long it was.
X.bin_write_t is only allowed to write that portion of the buffer you have access to.
module Unsafe : sig ... end
Unsafe has submodules that are like their corresponding module, except with no range checks. Hence, mistaken uses can cause segfaults. Be careful!
The number of bytes in the length prefix of
val fill_bin_prot : ( [> Core.write ], seek ) t -> 'a Bin_prot.Type_class.writer -> 'a -> unit Core.Or_error.t
fill_bin_prot writes a bin-prot value to the lower bound of the window, prefixed by its length, and advances by the amount written.
fill_bin_prot returns an error if the window is too small to write the value.
consume_bin_prot t reader reads a bin-prot value from the lower bound of the window, which should have been written using
fill_bin_prot, and advances the window by the amount read.
consume_bin_prot returns an error if there is not a complete message in the window and in that case the window is left unchanged.
Don't use these without a good reason, as they are incompatible with similar functions in
Writer. They use a 4-byte length rather than an 8-byte length.
module Blit : sig ... end
Blit copies between iobufs and advances neither
module Blit_consume : sig ... end
Blit_consume copies between iobufs and advances
src but does not advance
module Blit_fill : sig ... end
Blit_fill copies between iobufs and advances
dst but does not advance
module Blit_consume_and_fill : sig ... end
Blit_consume_and_fill copies between iobufs and advances both
memset t ~pos ~len c fills
c within the range
[pos, pos + len).
Create a new iobuf whose contents are the appended contents of the passed array.
module Expert : sig ... end
Expert module is for building efficient out-of-module
module type Accessors_common = sig ... end
('d, 'w) Iobuf.t accessor function manipulating
'a, either writing it to the iobuf or reading it from the iobuf.
module type Accessors_read = sig ... end
module type Accessors_write = sig ... end
module type Consuming_blit = sig ... end