Bytesrw adapter for Eio
ocaml
codec
1(*---------------------------------------------------------------------------
2 Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
3 SPDX-License-Identifier: ISC
4 ---------------------------------------------------------------------------*)
5
6(** Bytesrw adapters for Eio
7
8 This module provides adapters to create {!Bytesrw.Bytes.Reader.t} and
9 {!Bytesrw.Bytes.Writer.t} from Eio flows, mirroring the API of
10 {!Bytesrw_unix} for Eio's effect-based I/O. *)
11
12open Bytesrw
13
14(** Create a [Bytes.Reader.t] from an Eio source flow.
15
16 Reads directly from the flow without intermediate buffering.
17
18 @param slice_length Maximum bytes per slice (default: 65536, which is {!Bytes.Slice.unix_io_buffer_size}) *)
19let bytes_reader_of_flow
20 ?(slice_length = Bytes.Slice.unix_io_buffer_size)
21 (flow : _ Eio.Flow.source)
22 : Bytes.Reader.t =
23 let buf_size = Bytes.Slice.check_length slice_length in
24 let read () =
25 let cstruct = Cstruct.create buf_size in
26 match Eio.Flow.single_read flow cstruct with
27 | 0 -> Bytes.Slice.eod
28 | count ->
29 let data_cs = Cstruct.sub cstruct 0 count in
30 let buf = Cstruct.to_bytes data_cs in
31 Bytes.Slice.make buf ~first:0 ~length:count
32 | exception End_of_file -> Bytes.Slice.eod
33 in
34 Bytes.Reader.make ~slice_length read
35
36(** Create a [Bytes.Writer.t] from an Eio sink flow.
37
38 Writes directly to the flow without intermediate buffering.
39
40 @param slice_length Suggested slice length for upstream (default: 65536, which is {!Bytes.Slice.unix_io_buffer_size}) *)
41let bytes_writer_of_flow
42 ?(slice_length = Bytes.Slice.unix_io_buffer_size)
43 (flow : _ Eio.Flow.sink)
44 : Bytes.Writer.t =
45 let rec write slice =
46 if Bytes.Slice.is_eod slice then ()
47 else begin
48 let bytes = Bytes.Slice.bytes slice in
49 let first = Bytes.Slice.first slice in
50 let length = Bytes.Slice.length slice in
51 let cstruct = Cstruct.of_bytes ~off:first ~len:length bytes in
52 match Eio.Flow.single_write flow [cstruct] with
53 | count when count = length -> ()
54 | count -> write (Option.get (Bytes.Slice.drop count slice))
55 end
56 in
57 Bytes.Writer.make ~slice_length write