Module Mavryk_p2p.P2p_buffer_reader

This module takes care of reading data from a readable into a buffer.

Its purpose is to take care - via those abstract types - of the tedious tracking of byte positions and lengths when copying data around, as well as ensuring invariants for safety of call sites, e.g. "do not read too much" or "wait if no data is readable right now".

type readable

A data source. Reading functions read data from it.

type buffer

A data destination. Reading functions copy data into it.

mk_readable ~read_buffer ~read_queue creates a readable that uses read_buffer to store data and read_queue to notify asynchronously that data was written.

val mk_buffer : ?pos:int -> ?length_to_copy:int -> bytes -> buffer Mavryk_base.TzPervasives.tzresult

mk_buffer ?pos ?length_to_copy bytes creates a buffer for copying length_to_copy bytes into bytes starting at position pos.

  • pos defaults to 0.
  • length_to_copy defaults to Bytes.length bytes - pos.

If you neither specify pos nor length_to_copy, prefer using mk_buffer_safe which cannot fail.

If invalid values are passed, fails with Invalid_read_request.

val mk_buffer_safe : bytes -> buffer

mk_buffer_safe bytes creates a buffer that uses the entirety of bytes.

Simpler equivalent to mk_buffer ?pos:None ?length_to_copy:None bytes as the result is not wrapped in a result.

val read : ?canceler:Lwt_canceler.t -> readable -> buffer -> int Mavryk_base.TzPervasives.tzresult Lwt.t

read readable buffer reads the next segment of data from readable and copies it into buffer, returning the number of read bytes.

  • If readable does not currently contain any data, it waits for a segment then reads it.
  • If readable already contains data, it reads immediately.

Note: Even if buffer size is 0, this function still waits for data in readable before returning.

Invariants:

  • The returned number of bytes is lower than or equal to the current value of buffer.length_to_copy.
  • If the next readable segment is smaller than the current value of buffer.length_to_copy then only this segment is copied into buffer (i.e. after read, buffer.length_to_copy may or may not be 0)
  • If the next readable segment is bigger than the current value of buffer.length_to_copy then the unused data of that segment is kept for the next read (i.e. readable does not lose data).
val read_full : ?canceler:Lwt_canceler.t -> readable -> buffer -> unit Mavryk_base.TzPervasives.tzresult Lwt.t

read_full readable buffer reads from readable and copies into buffer until buffer is full.

  • If readable does not currently contain enough data to fill buffer, it waits for additional segments and reads them.
  • If readable already contains data, it reads immediately.

Invariants:

  • buffer.length_to_copy after read_full is guaranteed to be 0 (i.e. it is useless to read into buffer afterwards).
  • If the last read segment of readable is bigger than the remaining length of buffer then the unused data of that segment is kept for the next read (i.e. readable does not lose data).