Bytesrw adapter for Eio
ocaml codec
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 85 lines 3.3 kB view raw
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 19 Maximum bytes per slice (default: 65536, which is 20 {!Bytes.Slice.unix_io_buffer_size}) *) 21let bytes_reader_of_flow ?(slice_length = Bytes.Slice.unix_io_buffer_size) 22 (flow : _ Eio.Flow.source) : 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.Reader.t] from an Eio file at [offset]. 37 38 Uses pread for random-access reading without loading the whole file. 39 40 @param slice_length Maximum bytes per slice (default: 65536). 41 @param length Number of bytes to read (default: to end of file). *) 42let pread_reader ?(slice_length = Bytes.Slice.unix_io_buffer_size) ?length 43 ~offset (file : _ Eio.File.ro) : Bytes.Reader.t = 44 let stat = Eio.File.stat file in 45 let file_length = Optint.Int63.to_int stat.size in 46 let total = match length with Some n -> n | None -> file_length - offset in 47 let pos = ref 0 in 48 let buf_size = Bytes.Slice.check_length slice_length in 49 let buf = Bytes.create buf_size in 50 let read () = 51 if !pos >= total then Bytes.Slice.eod 52 else 53 let len = min buf_size (total - !pos) in 54 let cs = Cstruct.create len in 55 Eio.File.pread_exact file 56 ~file_offset:(Optint.Int63.of_int (offset + !pos)) 57 [ cs ]; 58 Cstruct.blit_to_bytes cs 0 buf 0 len; 59 pos := !pos + len; 60 Bytes.Slice.make buf ~first:0 ~length:len 61 in 62 Bytes.Reader.make ~slice_length read 63 64(** Create a [Bytes.Writer.t] from an Eio sink flow. 65 66 Writes directly to the flow without intermediate buffering. 67 68 @param slice_length 69 Suggested slice length for upstream (default: 65536, which is 70 {!Bytes.Slice.unix_io_buffer_size}) *) 71let bytes_writer_of_flow ?(slice_length = Bytes.Slice.unix_io_buffer_size) 72 (flow : _ Eio.Flow.sink) : Bytes.Writer.t = 73 let rec write slice = 74 if Bytes.Slice.is_eod slice then () 75 else begin 76 let bytes = Bytes.Slice.bytes slice in 77 let first = Bytes.Slice.first slice in 78 let length = Bytes.Slice.length slice in 79 let cstruct = Cstruct.of_bytes ~off:first ~len:length bytes in 80 match Eio.Flow.single_write flow [ cstruct ] with 81 | count when count = length -> () 82 | count -> write (Option.get (Bytes.Slice.drop count slice)) 83 end 84 in 85 Bytes.Writer.make ~slice_length write