package bytesrw

  1. Overview
  2. Docs

Byte stream readers.

Byte streams are sequences of non-empty byte slices ended by a single Slice.eod slice. A byte stream reader provides read access to these slices in order, on demand, but only slice by slice: the slice you get is valid for reading only until the next slice is read from the reader.

See the quick start and read about stream readers in the tutorial.

Readers

type t

The type for byte stream readers.

val make : ?pos:Stream.pos -> ?slice_length:Slice.length -> (unit -> Slice.t) -> t

make read is a reader from the function read which enumerates the slices of a byte stream. The contract between the reader and read is as follows:

  • The slice returned by a call to read must remain valid for reading until the next call to read.
  • The reader guarantees to dereference read and never call it again as soon as Slice.eod is returned by read.

pos defaults to 0 and slice_length to Slice.default_length.

val empty : ?pos:Stream.pos -> ?slice_length:Slice.length -> unit -> t

empty () is make (Fun.const Slice.eod), an empty byte stream.

val pos : t -> Stream.pos

pos r is the stream position of the next byte to read. Alternatively it can be seen as the number of bytes returned by calls to read (not including push back replays), see read_length.

Warning. Due to push backs negative values can be returned.

val read_length : t -> int

read_length r is an alternative name for pos.

Warning. Due to push backs negative values can be returned.

val slice_length : t -> Slice.length

slice_length r is a hint on the maximal length of slices that r returns.

val error : 'e Stream.format_error -> t -> ?pos:Stream.pos -> 'e -> 'a

error fmt r e raises a Stream.Error e of format fmt for r. pos is the position reported for the error, it defaults to r's pos. If the value is negative it is added to the latter, e.g. using the negated length of the last slice would report an error at the first byte of the last slice.

Reading

val read : t -> Slice.t

read r reads the next slice from r. The slice is only valid for reading until the next call to read on r. Once Slice.eod is returned, Slice.eod is always returned.

val push_back : t -> Slice.t -> unit

push_back r s pushes the slice s back on r. If s is Slice.eod this has no effect. Otherwise the stream position is rewinded by Slice.length s and the next read on r returns s.

Note. If r is the result of a call to tap the tap function won't see the push backs. Good for your checksums.

Warning. This should not be used as a general lookahead mecanism by stream readers. Codecs should devise their own buffering structures. But it is useful for stream content sniffing and breaking streams into substreams at precise positions.

Warning. Currently it is possible to push back beyond the beginning of a stream. It is unclear whether this feature will be kept in the future. Please get in touch if you use that feature.

val sniff : int -> t -> string

sniff n r sniffs at most n bytes from r. These bytes will still be returned by read calls. Less than n bytes are returned if the end of stream is reached before or if n <= 0.

Warning. This uses push_back and should not be used as a general lookahead mecanism by stream readers.

val skip : int -> t -> unit

skip n r is skips at most n bytes from r. See also discard.

val discard : t -> unit

discard r reads and discards slices until Slice.eod is returned. See also skip.

Filters

Read more about filters in the tutorial.

type filter = ?pos:Stream.pos -> ?slice_length:Slice.length -> t -> t

The type for byte stream reader filters.

Given a reader r, a filter f returns a filtering reader f r, that reads the stream of r and transforms it in some way. The following conventions should be followed for the resulting filtering reader:

  • If pos is unspecified, it should default to r's position only if the reads on the filtering reader are always in the same position space as r (see e.g. sub or limit). Otherwise it should be 0 (e.g. on decompression filters) or anything else that makes sense for the filter.
  • If slice_length is unspecified, it should default to r's slice_length or what makes more sense for the filter's reads.
  • If the filter reader does not read all of r's bytes, it must, after having returned Slice.eod, leave r at the position of the leftover data so that r can be used again to perform non-filtered reads. This can be done by using push_back on r with the leftover data.
  • If your filter is in a module M, then its name should be M.{decode,encode}_reads or another meaningful verb like M.{decompress,compress}_reads, M.{encrypt,decrypt}_reads, etc.
val sub : int -> filter

sub n r is a reader reading at most n bytes from r before returning Slice.eod. sub satisfies all the filter conventions and is not affected by push backs: reading back a push back on the sub stream does not count towards n. See also limit.

val limit : ?action:(t -> int -> unit) -> int -> filter

limit n r is like sub except it invokes action once with the filter reader before returning Slice.eod. The default action raises Stream.Limit error. See an example.

val filter_string : filter list -> string -> string

filter_string fs s is a convenience function that applies the filters fs, from left to right to the string s it is equivalent to:

to_string (List.fold_left (fun r f -> f r) (of_string s) fs)

See an example.

val reslice : filter

reslice ?pos ?slice_length r has the data of r but ensures that all slices are of length slice_length (defaults to slice_length r) except perhaps the last one.

Appending

val append : ?pos:Stream.pos -> ?slice_length:Slice.length -> t -> t -> t

append r0 r1 reads from r0 and then from r1. pos defaults to 0 and slice_length defaults to the maximal length of r0 and r1.

Taps

val tap : (Slice.t -> unit) -> t -> t

tap f r invokes f with the slice read by r before returning them with read. Note that push_backs are not tapped, so this can be used reliably for checksumming the reads of r. See also Slice.tracer and an example.

Predicates and comparisons

val equal : t -> t -> bool

equal r0 r1 asserts that the bytes of r0 are equal to those of r1 in bounded space. This may not fully consume the readers.

val compare : t -> t -> int

equal r0 r1 sorts the bytes of r0 and r1 in lexicographic order in bounded space. This may not fully consume the readers.

Converting

val of_bytes : ?pos:Stream.pos -> ?slice_length:Slice.length -> bytes -> t

of_bytes s reads the bytes of b with slices of maximal length slice_length which defaults to Bytes.length s. pos defaults to 0.

val of_string : ?pos:Stream.pos -> ?slice_length:Slice.length -> string -> t

of_string b is like of_bytes but reads the bytes of s.

val of_in_channel : ?pos:Stream.pos -> ?slice_length:Slice.length -> In_channel.t -> t

of_in_channel ic, sets ic in binary mode and reads the bytes of ic with slices of maximal length slice_length which defaults to Slice.io_buffer_size. pos default to In_channel.pos. This function and the resulting reader may raise Sys_error.

val of_slice : ?pos:Stream.pos -> ?slice_length:Slice.length -> Slice.t -> t

of_slice s reads r with slice of maximal length slice_length which default to Slice.length s. pos defaults to 0.

val of_slice_seq : ?pos:Stream.pos -> ?slice_length:Slice.length -> Slice.t Seq.t -> t

of_slice_seq seq reads the slices produced by seq. pos defaults to 0 and slice_length defaults to None.

val to_string : t -> string

to_string r reads r until Slice.eod into a string s.

val to_slice_seq : t -> Slice.t Seq.t

to_slice_seq r reads r until Slice.eod into a sequence. The latter is not enumerated.

Warning. A slice returned by the sequence is only valid for reading until the next slice is requested from the sequence.

val add_to_buffer : Buffer.t -> t -> unit

add_to_buffer b r reads r and adds its slices to b until Slice.eod.

val output_to_out_channel : ?flush_slices:bool -> Out_channel.t -> t -> unit

output_to_out_channel oc r, sets oc in binary mode, reads r and outputs the slices on oc until Slice.eod. If flush_slices is true, oc is flushed after each slice except Slice.eod. May raise Sys_error.

Formatting

val pp : Format.formatter -> t -> unit

pp formats a readers's properties for inspection. It does not consume any input.

OCaml

Innovation. Community. Security.