Tiny_httpd_stream
Byte streams.
Streams are used to represent a series of bytes that can arrive progressively. For example, an uploaded file will be sent as a series of chunks.
These used to live in Tiny_httpd
but are now in their own module.
type t = {
mutable bs : bytes;
The bytes
*)mutable off : int;
mutable len : int;
fill_buf : unit -> unit;
See the current slice of the internal buffer as bytes, i, len
, where the slice is bytes[i] .. [bytes[i+len-1]]
. Can block to refill the buffer if there is currently no content. If len=0
then there is no more data.
consume : int -> unit;
Consume n
bytes from the buffer. This should only be called with n <= len
.
close : unit -> unit;
Close the stream.
*)_rest : hidden;
}
A buffered stream, with a view into the current buffer (or refill if empty), and a function to consume n
bytes.
The point of this type is that it gives the caller access to its internal buffer (bs
, with the slice off,len
). This is convenient for things like line reading where one needs to peek ahead.
Some core invariant for this type of stream are:
off,len
delimits a valid slice in bs
(indices: off, off+1, … off+len-1
)fill_buf()
was just called, then either len=0
which indicates the end of stream; or len>0
and the slice contains some data.To actually move forward in the stream, you can call consume n
to consume n
bytes (where n <= len
). If len
gets to 0
, calling fill_buf()
is required, so it can try to obtain a new slice.
To emulate a classic OCaml reader with a read: bytes -> int -> int -> int
function, the simplest is:
let read (self:t) buf offset max_len : int =
self.fill_buf();
let len = min max_len self.len in
if len > 0 then (
Bytes.blit self.bs self.off buf offset len;
self.consume len;
);
len
val close : t -> unit
Close stream
val empty : t
Stream with 0 bytes inside
val of_input : ?buf_size:int -> Tiny_httpd_io.Input.t -> t
Make a buffered stream from the given channel.
val of_chan : ?buf_size:int -> Stdlib.in_channel -> t
Make a buffered stream from the given channel.
val of_chan_close_noerr : ?buf_size:int -> Stdlib.in_channel -> t
Same as of_chan
but the close
method will never fail.
val of_fd : ?buf_size:int -> Unix.file_descr -> t
Make a buffered stream from the given file descriptor.
val of_fd_close_noerr : ?buf_size:int -> Unix.file_descr -> t
Same as of_fd
but the close
method will never fail.
val of_bytes : ?i:int -> ?len:int -> bytes -> t
A stream that just returns the slice of bytes starting from i
and of length len
.
val of_string : string -> t
val iter : (bytes -> int -> int -> unit) -> t -> unit
Iterate on the chunks of the stream
val to_chan : Stdlib.out_channel -> t -> unit
Write the stream to the channel.
val to_chan' : Tiny_httpd_io.Output.t -> t -> unit
Write to the IO channel.
val to_writer : t -> Tiny_httpd_io.Writer.t
Turn this stream into a writer.
val make :
?bs:bytes ->
?close:(t -> unit) ->
consume:(t -> int -> unit) ->
fill:(t -> unit) ->
unit ->
t
make ~fill ()
creates a byte stream.
val with_file : ?buf_size:int -> string -> (t -> 'a) -> 'a
Open a file with given name, and obtain an input stream on its content. When the function returns, the stream (and file) are closed.
val read_line : ?buf:Tiny_httpd_buf.t -> t -> string
Read a line from the stream.
val read_all : ?buf:Tiny_httpd_buf.t -> t -> string
Read the whole stream into a string.
val read_chunked : ?buf:Tiny_httpd_buf.t -> fail:(string -> exn) -> t -> t
Convert a stream into a stream of byte chunks using the chunked encoding. The size of chunks is not specified.
read_exactly ~size bs
returns a new stream that reads exactly size
bytes from bs
, and then closes.
val output_chunked : ?buf:Tiny_httpd_buf.t -> Stdlib.out_channel -> t -> unit
Write the stream into the channel, using the chunked encoding.
val output_chunked' :
?buf:Tiny_httpd_buf.t ->
Tiny_httpd_io.Output.t ->
t ->
unit
Write the stream into the channel, using the chunked encoding.