mirror of
https://github.com/ocaml-multicore/eio.git
synced 2025-10-30 00:04:12 -04:00
Add Buf_read.parse_exn
This commit is contained in:
parent
b9a608562d
commit
3b4abcc79c
@ -278,6 +278,11 @@ let parse ?initial_size ~max_size p flow =
|
||||
let buf = of_flow flow ?initial_size ~max_size in
|
||||
format_errors (p <* end_of_input) buf
|
||||
|
||||
let parse_exn ?initial_size ~max_size p flow =
|
||||
match parse ?initial_size ~max_size p flow with
|
||||
| Ok x -> x
|
||||
| Error (`Msg m) -> failwith m
|
||||
|
||||
[@@inline never]
|
||||
let bad_offset ~expected actual =
|
||||
Fmt.invalid_arg "Sequence is stale (expected to be used at offset %d, but stream is now at %d)"
|
||||
|
||||
@ -628,6 +628,13 @@ module Buf_read : sig
|
||||
|
||||
@param initial_size see {!of_flow}. *)
|
||||
|
||||
val parse_exn : ?initial_size:int -> max_size:int -> 'a parser -> #Flow.source -> 'a
|
||||
(** [parse_exn] wraps {!parse}, but raises [Failure msg] if that returns [Error (`Msg msg)].
|
||||
|
||||
Catching exceptions with [parse] and then raising them might seem pointless,
|
||||
but this has the effect of turning e.g. an [End_of_file] exception into a [Failure]
|
||||
with a more user-friendly message. *)
|
||||
|
||||
val of_flow : ?initial_size:int -> max_size:int -> #Flow.source -> t
|
||||
(** [of_flow ~max_size flow] is a buffered reader backed by [flow].
|
||||
|
||||
|
||||
@ -51,6 +51,11 @@ let test ?(max_size=10) input p =
|
||||
next := input;
|
||||
let i = R.of_flow mock_flow ~max_size in
|
||||
p i
|
||||
|
||||
let parse_exn p flow ~max_size =
|
||||
match R.parse_exn p flow ~max_size with
|
||||
| x -> traceln "Ok: %S" x
|
||||
| exception Failure msg -> traceln "Failure: %s" msg
|
||||
```
|
||||
|
||||
|
||||
@ -511,3 +516,51 @@ Invalid_argument
|
||||
"Sequence is stale (expected to be used at offset 4, but stream is now at 8)".
|
||||
```
|
||||
|
||||
## Convenience wrapper
|
||||
|
||||
`parse` turns parser errors into friendly messages:
|
||||
|
||||
```ocaml
|
||||
# R.(parse (string "FROM:" *> take_all)) (Eio.Flow.string_source "FROM:A") ~max_size:5;;
|
||||
- : (string, [> `Msg of string ]) result = Ok "A"
|
||||
|
||||
# R.(parse (string "FROM:" *> take_all)) (Eio.Flow.string_source "TO:B") ~max_size:5;;
|
||||
- : (string, [> `Msg of string ]) result =
|
||||
Error (`Msg "Expected \"FROM:\" but got \"TO:B\" (at offset 0)")
|
||||
|
||||
# R.(parse (string "FROM:" *> take_all)) (Eio.Flow.string_source "FROM:ABCDE") ~max_size:5;;
|
||||
- : (string, [> `Msg of string ]) result =
|
||||
Error (`Msg "Buffer size limit exceeded when reading at offset 5")
|
||||
|
||||
# R.(parse (string "END")) (Eio.Flow.string_source "ENDING") ~max_size:5;;
|
||||
- : (unit, [> `Msg of string ]) result =
|
||||
Error (`Msg "Unexpected data after parsing (at offset 3)")
|
||||
|
||||
# R.(parse (string "END")) (Eio.Flow.string_source "E") ~max_size:5;;
|
||||
- : (unit, [> `Msg of string ]) result =
|
||||
Error (`Msg "Unexpected end-of-file at offset 1")
|
||||
```
|
||||
|
||||
`parse_exn` is similar, but raises (we then catch it and print it nicely):
|
||||
|
||||
```ocaml
|
||||
# parse_exn R.(string "FROM:" *> take_all) (Eio.Flow.string_source "FROM:A") ~max_size:5;;
|
||||
+Ok: "A"
|
||||
- : unit = ()
|
||||
|
||||
# parse_exn R.(string "FROM:" *> take_all) (Eio.Flow.string_source "TO:B") ~max_size:5;;
|
||||
+Failure: Expected "FROM:" but got "TO:B" (at offset 0)
|
||||
- : unit = ()
|
||||
|
||||
# parse_exn R.(string "FROM:" *> take_all) (Eio.Flow.string_source "FROM:ABCDE") ~max_size:5;;
|
||||
+Failure: Buffer size limit exceeded when reading at offset 5
|
||||
- : unit = ()
|
||||
|
||||
# parse_exn R.(take 3) (Eio.Flow.string_source "ENDING") ~max_size:5;;
|
||||
+Failure: Unexpected data after parsing (at offset 3)
|
||||
- : unit = ()
|
||||
|
||||
# parse_exn R.(take 3) (Eio.Flow.string_source "E") ~max_size:5;;
|
||||
+Failure: Unexpected end-of-file at offset 1
|
||||
- : unit = ()
|
||||
```
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user