Module Bytes.Writer

Byte stream writers.

Byte streams are sequences of byte slices. A byte stream writer is given access to these slices in order but only slice by slice in its slice iteration function: slices only remain valid for reading until the function returns.


type t

The type for byte stream writers.

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

make write is a writer from the function write which iterates over the slices of a byte stream. The contract between the writer and write is as follows:

  • The slice values given to write are valid for reading only until the write function returns.
  • The writer guarantees that after write was called with Slice.eod, write is dereferenced by the writer and will never be called again.

pos defaults to 0 and slice_length to Slice.default_length.

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

ignore () is make (fun _ -> ()), a writer that ignores the writes that are pushed on it.

val pos : t -> Stream.pos

pos w is the stream postion of the next byte to write. Alternatively it can be seen as the number of bytes written on w, see written_length.

val slice_length : t -> Slice.length

slice_length w is a hint on the maximal length of slices that w would like to receive (if any).

val written_length : t -> int

written_length w is an alternative name for pos.

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

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


Note. All these functions raise Invalid_argument if a slice other than Slice.eod is written after a Slice.eod was written.

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

write w s writes the slice s on w. s must remain valid for reading until the function returns.

The function raises Invalid_argument is s is written after a Slice.eod and s is not Slice.eod.

val write_eod : t -> unit

write_eod w is write w Slice.eod. Only Slice.eod can be written on w aftewards.

val write_bytes : t -> bytes -> unit

write_bytes w b writes the bytes b on w in slice_length slices. The bytes of b must not change until the function returns.

val write_string : t -> string -> unit

write_string is like write_bytes but writes a string.

val write_reader : eod:bool -> t -> Reader.t -> unit

write_reader w r writes the slices of r on w. Slice.eod is only written if eod is true. Note that the slices are written as given by r and may not respect w's desired slice_length.

val write_in_channel : eod:bool -> t -> Stdlib.In_channel.t -> unit

write_in_channel w ic sets ic to binary mode and writes slices to w until the end of file is reached at which point Slice.eod is written iff eod is true. The maximal length of written slices are w's slice_length.


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

The type for byte stream writer filters.

Given a writer w, a filter f returns a filtering writer f ~eod w, that transforms the writes made on it in some way and then writes them to w. The following conventions should be followed for the filtering writer:

  • Once the filter writer receives Slice.eod, it must stop and, if applicable, report an error if there was leftover data that it couldn't write. It must only write Slice.eod on w if eod is true. Otherwise it should leave w as is so that it can be used again to perform other non-filtered writes
  • If pos is unspecified it should default to w's position only if the writes are in the same position space as w. Otherwise it should be 0 (e.g. on compression filters).
  • If slice_length is unspecified it should default to w's value or a value that makes more sense for the filter's needs.
  • The filtering writer should write slices on w that respects its slice_length desires.
  • If your filter is in a module M, then its name should be M.{decode,encode}_writes or an other meaningful verb like M.{decompress,compress}_writes, M.{encrypt,decrypt}_writes, etc.
val limit : ?action:(t -> int -> unit) -> int -> filter

limit n w is a writer that writes at most n bytes on w. Any leftover in the slice that exceeds the n bytes is lost. After n bytes have been written on w the action action is invoked once and the filtering writer accepts only Slice.eod afterwards. As per filter semantics Slice.eod is only written on w if eod is true. The default action raises Stream.Limit error.

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:

let b = Buffer.create (String.length s) in
let w = List.fold_left (fun w f -> f ~eod:true w) (of_buffer w) fs in
write_string w s; write_eod w; Buffer.contents b


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

tap f w is a writer that invokes f with the slice before writing it on w.


val of_out_channel : ?pos:Stream.pos -> ?slice_length:Slice.length -> ?flush_slices:bool -> Stdlib.Out_channel.t -> t

of_out_channel oc sets oc to binary mode and writes slices to oc. If flush_slices is true (defaults to false), oc is flushed after each slice except Slice.eod. pos defaults to Out_channel.pos. The hinted slice_length defaults to Slice.io_buffer_size. Can raise Sys_error.

val of_buffer : ?pos:Stream.pos -> ?slice_length:Slice.length -> Stdlib.Buffer.t -> t

of_buffer b writes slices to b.

slice_length is not that important but we default it to Slice.io_buffer_size, so that channel and fd readers that may ajust their own buffers on writers adjust nicely for themselves.

Formatting and inspecting

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

pp formats w's properties for inspection.