diff --git a/bencode.ml b/bencode.ml index bbc9e750..5fe856fd 100644 --- a/bencode.ml +++ b/bencode.ml @@ -305,6 +305,8 @@ let parse dec s i len = (* state machine *) parse_rec dec +let parse_resume d = parse_rec d + let reset dec = dec.l <- 0; dec.c <- 0; diff --git a/bencode.mli b/bencode.mli index 4ac860d9..0bd47a80 100644 --- a/bencode.mli +++ b/bencode.mli @@ -90,6 +90,10 @@ val parse : decoder -> string -> int -> int -> parse_result It can return an error, a value or just [ParsePartial] if more input is needed *) +val parse_resume : decoder -> parse_result + (** Resume where the previous call to {!parse} stopped (may have + returned a value while some input is not processed) *) + val reset : decoder -> unit (** Reset the decoder to its pristine state, ready to parse something different. Before that, {! rest} and {! rest_size} can be used diff --git a/bij.ml b/bij.ml index 34310e6b..0147e072 100644 --- a/bij.ml +++ b/bij.ml @@ -201,8 +201,43 @@ module TrBencode = struct let b = B.of_string s in decode ~bij b - (* TODO *) - let read ~bij ic = failwith "read: not implemented" + let read ~bij ic = + let d = B.mk_decoder () in + let buf = String.create 256 in + let rec read_chunk() = + let n = input ic buf 0 (String.length buf) in + if n = 0 + then raise (DecodingError "unexpected EOF") + else match B.parse d buf 0 n with + | B.ParsePartial -> read_chunk() + | B.ParseError s -> raise (DecodingError s) + | B.ParseOk b -> decode ~bij b + in + read_chunk() - let write ~bij x oc = failwith "write: not implemented" + let read_stream ~bij ic = + let d = B.mk_decoder () in + let buf = String.create 256 in + let rec try_parse n = match B.parse d buf 0 n with + | B.ParsePartial -> read_chunk() + | B.ParseError s -> raise (DecodingError s) + | B.ParseOk b -> Some (decode ~bij b) + and read_chunk() = + let n = input ic buf 0 (String.length buf) in + if n = 0 + then match B.parse_resume d with + | B.ParsePartial -> None + | B.ParseError s -> raise (DecodingError s) + | B.ParseOk b -> Some (decode ~bij b) + else try_parse n + in + Stream.from (fun _ -> read_chunk()) + + let write ~bij oc x = + let b = encode ~bij x in + B.to_chan oc b; + flush oc + + let write_stream ~bij oc str = + Stream.iter (fun x -> write ~bij oc x) str end diff --git a/bij.mli b/bij.mli index 6cc8ee83..55144947 100644 --- a/bij.mli +++ b/bij.mli @@ -89,7 +89,12 @@ module TrBencode : sig val of_string : bij:'a t -> string -> 'a val read : bij:'a t -> in_channel -> 'a + (** Read a single value from the channel *) - val write : bij:'a t -> 'a t -> out_channel -> unit + val read_stream : bij:'a t -> in_channel -> 'a Stream.t + + val write : bij:'a t -> out_channel -> 'a -> unit + + val write_stream : bij:'a t -> out_channel -> 'a Stream.t -> unit end