diff --git a/Makefile b/Makefile index 0ff54d8..c82c477 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -OPTS=--profile=release +OPTS=--profile=release --ignore-promoted-rules all: @dune build @all $(OPTS) @@ -12,6 +12,9 @@ clean: fmt: @dune build @fmt --display=quiet --auto-promote +lint: + @dune build @lint + WATCH ?= @all watch: @dune build $(WATCH) -w $(OPTS) diff --git a/src/utils/.ocamlformat-ignore b/src/utils/.ocamlformat-ignore new file mode 100644 index 0000000..480159e --- /dev/null +++ b/src/utils/.ocamlformat-ignore @@ -0,0 +1 @@ +bare_encoding.ml* diff --git a/src/utils/Bare_encoding.ml b/src/utils/bare_encoding.ml similarity index 51% rename from src/utils/Bare_encoding.ml rename to src/utils/bare_encoding.ml index 9337513..0eef568 100644 --- a/src/utils/Bare_encoding.ml +++ b/src/utils/bare_encoding.ml @@ -1,5 +1,4 @@ - -module String_map = Map.Make(String) +module String_map = Map.Make (String) module type INPUT = sig val read_byte : unit -> char @@ -8,88 +7,129 @@ module type INPUT = sig val read_i64 : unit -> int64 val read_exact : bytes -> int -> int -> unit end + type input = (module INPUT) -let input_of_bytes ?(off=0) ?len (b:bytes) : input = +let input_of_bytes ?(off = 0) ?len (b : bytes) : input = let off = ref off in - let len = match len with + let len = + match len with | None -> Bytes.length b - !off | Some l -> l in if !off + len > Bytes.length b then invalid_arg "input_of_bytes"; - let[@inline] check_ n = if !off + n > len then invalid_arg "input exhausted" in + let[@inline] check_ n = + if !off + n > len then invalid_arg "input exhausted" + in let module M = struct - let read_byte () = check_ 1; let c = Bytes.get b !off in incr off; c - let read_i16 () = check_ 2; let r = Bytes.get_int16_le b !off in off := !off + 2; r - let read_i32 () = check_ 4; let r = Bytes.get_int32_le b !off in off := !off + 4; r - let read_i64 () = check_ 8; let r = Bytes.get_int64_le b !off in off := !off + 8; r - let read_exact into i len = check_ len; Bytes.blit b !off into i len; off := !off + len + let read_byte () = + check_ 1; + let c = Bytes.get b !off in + incr off; + c + + let read_i16 () = + check_ 2; + let r = Bytes.get_int16_le b !off in + off := !off + 2; + r + + let read_i32 () = + check_ 4; + let r = Bytes.get_int32_le b !off in + off := !off + 4; + r + + let read_i64 () = + check_ 8; + let r = Bytes.get_int64_le b !off in + off := !off + 8; + r + + let read_exact into i len = + check_ len; + Bytes.blit b !off into i len; + off := !off + len end in (module M) module Decode = struct type t = input - let[@inline] of_input (i:input) : t = i + let[@inline] of_input (i : input) : t = i let of_bytes ?off ?len b = of_input (input_of_bytes ?off ?len b) let of_string ?off ?len s = of_bytes ?off ?len (Bytes.unsafe_of_string s) type 'a dec = t -> 'a - let uint (self:t) : int64 = + let uint (self : t) : int64 = let rec loop () = - let c = let (module M) = self in M.read_byte() in + let c = + let (module M) = self in + M.read_byte () + in let c = Char.code c in if c land 0b1000_0000 <> 0 then ( - let rest = loop() in + let rest = loop () in let c = Int64.of_int (c land 0b0111_1111) in Int64.(logor (shift_left rest 7) c) - ) else ( + ) else Int64.of_int c (* done *) - ) in - loop() + loop () - let int (self:t) : int64 = + let int (self : t) : int64 = let open Int64 in let i = uint self in - let sign_bit = logand 0b1L i in (* true if negative *) + let sign_bit = logand 0b1L i in + (* true if negative *) let sign = equal sign_bit 0L in let res = - if sign then ( + if sign then shift_right_logical i 1 - ) else ( + else (* put sign back *) logor (shift_left 1L 63) (shift_right_logical (lognot i) 1) - ) in res - let i8 (self:t) : char = let (module M) = self in M.read_byte() + let i8 (self : t) : char = + let (module M) = self in + M.read_byte () + let u8 = i8 - let i16 (self:t) = let (module M) = self in M.read_i16() + let i16 (self : t) = + let (module M) = self in + M.read_i16 () + let u16 = i16 - let i32 (self:t) = let (module M) = self in M.read_i32() + let i32 (self : t) = + let (module M) = self in + M.read_i32 () + let u32 = i32 - let i64 (self:t) = let (module M) = self in M.read_i64() + let i64 (self : t) = + let (module M) = self in + M.read_i64 () + let u64 = i64 let[@inline] bool self : bool = let c = i8 self in Char.code c <> 0 - let f32 (self:t) : float = + let f32 (self : t) : float = let i = i32 self in Int32.float_of_bits i - let f64 (self:t) : float = + let f64 (self : t) : float = let i = i64 self in Int64.float_of_bits i - let data_of ~size (self:t) : bytes = + let data_of ~size (self : t) : bytes = let b = Bytes.create size in let (module M) = self in M.read_exact b 0 size; @@ -99,15 +139,18 @@ module Decode = struct let size = uint self in if Int64.compare size (Int64.of_int Sys.max_string_length) > 0 then invalid_arg "Decode.data: string too large"; - let size = Int64.to_int size in (* fits, because of previous test *) + let size = Int64.to_int size in + (* fits, because of previous test *) data_of ~size self - let string self : string = - Bytes.unsafe_to_string (data self) + let string self : string = Bytes.unsafe_to_string (data self) let[@inline] optional dec self : _ option = let c = u8 self in - if Char.code c = 0 then None else Some (dec self) + if Char.code c = 0 then + None + else + Some (dec self) end module type OUTPUT = sig @@ -121,7 +164,7 @@ end type output = (module OUTPUT) -let output_of_buffer (buf:Buffer.t) : output = +let output_of_buffer (buf : Buffer.t) : output = let module M = struct let[@inline] write_byte c = Buffer.add_char buf c let[@inline] write_i16 c = Buffer.add_int16_le buf c @@ -135,7 +178,7 @@ let output_of_buffer (buf:Buffer.t) : output = module Encode = struct type t = output - let[@inline] of_output (o:output) : t = o + let[@inline] of_output (o : output) : t = o let[@inline] of_buffer buf : t = of_output @@ output_of_buffer buf type 'a enc = t -> 'a -> unit @@ -143,7 +186,7 @@ module Encode = struct (* no need to check for overflow below *) external unsafe_chr : int -> char = "%identity" - let uint (self:t) (i:int64) : unit = + let uint (self : t) (i : int64) : unit = let module I = Int64 in let i = ref i in let continue = ref true in @@ -157,37 +200,57 @@ module Encode = struct ) else ( (* set bit 8 to [1] *) let lsb = I.to_int (I.logor 0b1000_0000L j) in - let lsb = (unsafe_chr lsb) in + let lsb = unsafe_chr lsb in let (module M) = self in M.write_byte lsb; - i := I.shift_right_logical !i 7; + i := I.shift_right_logical !i 7 ) done - let[@inline] int (self:t) i = + let[@inline] int (self : t) i = let open Int64 in let ui = logxor (shift_left i 1) (shift_right i 63) in uint self ui - let[@inline] i8 (self:t) x = let (module M) = self in M.write_byte x + let[@inline] i8 (self : t) x = + let (module M) = self in + M.write_byte x + let u8 = i8 - let[@inline] i16 (self:t) x = let (module M) = self in M.write_i16 x + + let[@inline] i16 (self : t) x = + let (module M) = self in + M.write_i16 x + let u16 = i16 - let[@inline] i32 (self:t) x = let (module M) = self in M.write_i32 x + + let[@inline] i32 (self : t) x = + let (module M) = self in + M.write_i32 x + let u32 = i32 - let[@inline] i64 (self:t) x = let (module M) = self in M.write_i64 x + + let[@inline] i64 (self : t) x = + let (module M) = self in + M.write_i64 x + let u64 = i64 - let bool self x = i8 self (if x then Char.chr 1 else Char.chr 0) + let bool self x = + i8 self + (if x then + Char.chr 1 + else + Char.chr 0) - let f64 (self:t) x = i64 self (Int64.bits_of_float x) + let f64 (self : t) x = i64 self (Int64.bits_of_float x) - let data_of ~size (self:t) x = + let data_of ~size (self : t) x = if size <> Bytes.length x then failwith "invalid length for Encode.data_of"; let (module M) = self in M.write_exact x 0 size - let data (self:t) x = + let data (self : t) x = uint self (Int64.of_int (Bytes.length x)); let (module M) = self in M.write_exact x 0 (Bytes.length x) @@ -205,6 +268,7 @@ end module Pp = struct type 'a t = Format.formatter -> 'a -> unit type 'a iter = ('a -> unit) -> unit + let unit out () = Format.pp_print_string out "()" let int8 out c = Format.fprintf out "%d" (Char.code c) let int out x = Format.fprintf out "%d" x @@ -214,28 +278,34 @@ module Pp = struct let bool = Format.pp_print_bool let string out x = Format.fprintf out "%S" x let data out x = string out (Bytes.unsafe_to_string x) - let option ppelt out x = match x with + + let option ppelt out x = + match x with | None -> Format.fprintf out "None" | Some x -> Format.fprintf out "(Some %a)" ppelt x + let array ppelt out x = Format.fprintf out "[@["; - Array.iteri (fun i x -> - if i>0 then Format.fprintf out ";@ "; + Array.iteri + (fun i x -> + if i > 0 then Format.fprintf out ";@ "; ppelt out x) x; Format.fprintf out "@]]" + let iter ppelt out xs = Format.fprintf out "[@["; let i = ref 0 in xs (fun x -> - if !i>0 then Format.fprintf out ",@ "; + if !i > 0 then Format.fprintf out ",@ "; incr i; ppelt out x); Format.fprintf out "@]]" - let list ppelt out l = iter ppelt out (fun f->List.iter f l) + + let list ppelt out l = iter ppelt out (fun f -> List.iter f l) end -let to_string (e:'a Encode.enc) (x:'a) = +let to_string (e : 'a Encode.enc) (x : 'a) = let buf = Buffer.create 32 in e (Encode.of_buffer buf) x; Buffer.contents buf @@ -245,81 +315,13 @@ let of_bytes_exn ?off ?len dec b = dec i let of_bytes ?off ?len dec bs = - try Ok (of_bytes_exn ?off ?len dec bs) - with + try Ok (of_bytes_exn ?off ?len dec bs) with | Invalid_argument e | Failure e -> Error e | End_of_file -> Error "end of file" -let of_string_exn ?off ?len dec s = of_bytes_exn ?off ?len dec (Bytes.unsafe_of_string s) -let of_string ?off ?len dec s = of_bytes ?off ?len dec (Bytes.unsafe_of_string s) - - -(*$inject - let to_s f x = - let buf = Buffer.create 32 in - let out = Encode.of_buffer buf in - f out x; - Buffer.contents buf - - let of_s f x = - let i = Decode.of_string x in - f i -*) - -(*$= & ~printer:Int64.to_string - 37L (of_s Decode.uint (to_s Encode.uint 37L)) - 42L (of_s Decode.uint (to_s Encode.uint 42L)) - 0L (of_s Decode.uint (to_s Encode.uint 0L)) - 105542252L (of_s Decode.uint (to_s Encode.uint 105542252L)) - Int64.max_int (of_s Decode.uint (to_s Encode.uint Int64.max_int)) -*) - -(*$= & ~printer:Int64.to_string - 37L (of_s Decode.int (to_s Encode.int 37L)) - 42L (of_s Decode.int (to_s Encode.int 42L)) - 0L (of_s Decode.int (to_s Encode.int 0L)) - 105542252L (of_s Decode.int (to_s Encode.int 105542252L)) - Int64.max_int (of_s Decode.int (to_s Encode.int Int64.max_int)) - Int64.min_int (of_s Decode.int (to_s Encode.int Int64.min_int)) - (-1209433446454112432L) (of_s Decode.int (to_s Encode.int (-1209433446454112432L))) - (-3112855215860398414L) (of_s Decode.int (to_s Encode.int (-3112855215860398414L))) -*) - -(*$= - 1 (let s = to_s Encode.int (-1209433446454112432L) in 0x1 land (Char.code s.[0])) -*) - -(*$Q & ~count:1000 - Q.(int64) (fun s -> \ - s = (of_s Decode.uint (to_s Encode.uint s))) - Q.(small_nat) (fun n -> \ - let n = Int64.of_int n in \ - n = (of_s Decode.uint (to_s Encode.uint n))) -*) - -(*$Q & ~count:1000 - Q.(int64) (fun s -> \ - s = (of_s Decode.int (to_s Encode.int s))) - Q.(small_signed_int) (fun n -> \ - let n = Int64.of_int n in \ - n = (of_s Decode.int (to_s Encode.int n))) -*) - -(*$R - for i=0 to 1_000 do - let i = Int64.of_int i in - assert_equal ~printer:Int64.to_string i (of_s Decode.int (to_s Encode.int i)) - done -*) +let of_string_exn ?off ?len dec s = + of_bytes_exn ?off ?len dec (Bytes.unsafe_of_string s) -(*$R - for i=0 to 1_000 do - let i = Int64.of_int i in - assert_equal ~printer:Int64.to_string i (of_s Decode.uint (to_s Encode.uint i)) - done -*) +let of_string ?off ?len dec s = + of_bytes ?off ?len dec (Bytes.unsafe_of_string s) -(*$Q & ~count:1000 - Q.(string) (fun s -> \ - s = (of_s Decode.string (to_s Encode.string s))) -*) diff --git a/src/utils/Bare_encoding.mli b/src/utils/bare_encoding.mli similarity index 96% rename from src/utils/Bare_encoding.mli rename to src/utils/bare_encoding.mli index 0d80d95..3e7f6a7 100644 --- a/src/utils/Bare_encoding.mli +++ b/src/utils/bare_encoding.mli @@ -1,11 +1,10 @@ - (** BARE runtime library. See {{: https://baremessages.org/} the spec}. *) -module String_map : module type of Map.Make(String) +module String_map : module type of Map.Make (String) -(** {2 Input type} +(** Input type. An input is a source of bytes, used to decode. *) module type INPUT = sig @@ -75,14 +74,11 @@ module Decode : sig val i32 : t -> int32 val i64 : t -> int64 val bool : t -> bool - val f32 : t -> float val f64 : t -> float - val string : t -> string val data : t -> bytes val data_of : size:int -> t -> bytes - val optional : 'a dec -> 'a option dec end @@ -193,6 +189,7 @@ module Pp : sig (** A pretty printer for values of type ['a] *) type 'a iter = ('a -> unit) -> unit + val unit : unit t val int : int t val int8 : char t @@ -214,7 +211,8 @@ val of_bytes_exn : ?off:int -> ?len:int -> 'a Decode.dec -> bytes -> 'a @param off the initial offset in [bs] (default 0) @raise Decode.Error if decoding fails *) -val of_bytes : ?off:int -> ?len:int -> 'a Decode.dec -> bytes -> ('a, string) result +val of_bytes : + ?off:int -> ?len:int -> 'a Decode.dec -> bytes -> ('a, string) result (** Same as {!of_bytes_exn} but doesn't raise. *) val of_string_exn : ?off:int -> ?len:int -> 'a Decode.dec -> string -> 'a @@ -222,9 +220,9 @@ val of_string_exn : ?off:int -> ?len:int -> 'a Decode.dec -> string -> 'a See {of_bytes_exn} for more details. @raise Decode.Error if decoding fails *) -val of_string : ?off:int -> ?len:int -> 'a Decode.dec -> string -> ('a, string) result +val of_string : + ?off:int -> ?len:int -> 'a Decode.dec -> string -> ('a, string) result (** Safe version of {!of_string_exn} *) val to_string : 'a Encode.enc -> 'a -> string (** Encode a value of type ['a] into a string using the given encoder. *) - diff --git a/src/utils/dune b/src/utils/dune index bda1af8..1dc6883 100644 --- a/src/utils/dune +++ b/src/utils/dune @@ -18,9 +18,9 @@ (rule (alias lint) - (targets Bare_encoding.ml Bare_encoding.mli) + (targets bare_encoding.ml bare_encoding.mli) (mode promote) (action (progn - (copy %{lib:bare_encoding:Bare_encoding.ml} Bare_encoding.ml) - (copy %{lib:bare_encoding:Bare_encoding.mli} Bare_encoding.mli)))) + (copy %{lib:bare_encoding:bare_encoding.ml} bare_encoding.ml) + (copy %{lib:bare_encoding:bare_encoding.mli} bare_encoding.mli))))