Data_encoding: stylistic changes in printer of binary schema
This commit is contained in:
parent
030630ec0f
commit
5baa090a1e
@ -28,7 +28,7 @@ end = struct
|
|||||||
open Binary_schema
|
open Binary_schema
|
||||||
type ele = Ref of string | Root of description
|
type ele = Ref of string | Root of description
|
||||||
type t = (string, ele) Hashtbl.t
|
type t = (string, ele) Hashtbl.t
|
||||||
let add t x = Hashtbl.replace t x.name (Root x)
|
let add t x = Hashtbl.replace t x.title (Root x)
|
||||||
let rec find tbl key =
|
let rec find tbl key =
|
||||||
match Hashtbl.find tbl key with
|
match Hashtbl.find tbl key with
|
||||||
| Ref s -> find tbl s
|
| Ref s -> find tbl s
|
||||||
@ -37,9 +37,9 @@ end = struct
|
|||||||
let union tbl ~new_cannonical ~existing =
|
let union tbl ~new_cannonical ~existing =
|
||||||
add tbl new_cannonical ;
|
add tbl new_cannonical ;
|
||||||
let root = find tbl existing in
|
let root = find tbl existing in
|
||||||
if root.name = new_cannonical.name
|
if root.title = new_cannonical.title
|
||||||
then ()
|
then ()
|
||||||
else Hashtbl.replace tbl root.name (Ref new_cannonical.name)
|
else Hashtbl.replace tbl root.title (Ref new_cannonical.title)
|
||||||
|
|
||||||
let empty () = Hashtbl.create 128
|
let empty () = Hashtbl.create 128
|
||||||
|
|
||||||
@ -49,15 +49,15 @@ end = struct
|
|||||||
(Hashtbl.iter (fun k v ->
|
(Hashtbl.iter (fun k v ->
|
||||||
Format.fprintf ppf "'%s' ---> %a@,"
|
Format.fprintf ppf "'%s' ---> %a@,"
|
||||||
k (fun ppf -> function
|
k (fun ppf -> function
|
||||||
| Root { name } -> Format.fprintf ppf "Root '%s'" name
|
| Root { title } -> Format.fprintf ppf "Root '%s'" title
|
||||||
| Ref s -> Format.fprintf ppf "Ref '%s'" s) v))) tbl
|
| Ref s -> Format.fprintf ppf "Ref '%s'" s) v))) tbl
|
||||||
end
|
end
|
||||||
|
|
||||||
let fixup_references uf =
|
let fixup_references uf =
|
||||||
let open Binary_schema in
|
let open Binary_schema in
|
||||||
let rec fixup_layout = function
|
let rec fixup_layout = function
|
||||||
| Ref s -> Ref (UF.find uf s).name
|
| Ref s -> Ref (UF.find uf s).title
|
||||||
| Enum (i, name) -> Enum (i, (UF.find uf name).name)
|
| Enum (i, name) -> Enum (i, (UF.find uf name).title)
|
||||||
| Seq layout -> Seq (fixup_layout layout)
|
| Seq layout -> Seq (fixup_layout layout)
|
||||||
| (Zero_width
|
| (Zero_width
|
||||||
| Int _
|
| Int _
|
||||||
@ -97,7 +97,7 @@ let z_encoding =
|
|||||||
Binary_schema.Obj { fields = [ Named_field ("Z.t", `Dynamic, Bytes) ] }
|
Binary_schema.Obj { fields = [ Named_field ("Z.t", `Dynamic, Bytes) ] }
|
||||||
|
|
||||||
let add_z_reference uf { descriptions } =
|
let add_z_reference uf { descriptions } =
|
||||||
UF.add uf { name = z_reference_name ;
|
UF.add uf { title = z_reference_name ;
|
||||||
description = Some z_reference_description } ;
|
description = Some z_reference_description } ;
|
||||||
{ descriptions = (z_reference_name, z_encoding) :: descriptions }
|
{ descriptions = (z_reference_name, z_encoding) :: descriptions }
|
||||||
|
|
||||||
@ -114,16 +114,54 @@ let n_encoding =
|
|||||||
Binary_schema.Obj { fields = [ Named_field ("N.t", `Dynamic, Bytes) ] }
|
Binary_schema.Obj { fields = [ Named_field ("N.t", `Dynamic, Bytes) ] }
|
||||||
|
|
||||||
let add_n_reference uf { descriptions } =
|
let add_n_reference uf { descriptions } =
|
||||||
UF.add uf { name = n_reference_name ;
|
UF.add uf { title = n_reference_name ;
|
||||||
description = Some n_reference_description } ;
|
description = Some n_reference_description } ;
|
||||||
{ descriptions = (n_reference_name, n_encoding) :: descriptions }
|
{ descriptions = (n_reference_name, n_encoding) :: descriptions }
|
||||||
|
|
||||||
|
let dedup_canonicalize uf =
|
||||||
|
let tbl : (Binary_schema.toplevel_encoding, Binary_schema.description) Hashtbl.t = Hashtbl.create 100 in
|
||||||
|
let rec help prev_len acc = function
|
||||||
|
| [] ->
|
||||||
|
let fixedup =
|
||||||
|
List.map
|
||||||
|
(fun (desc, layout) -> (desc, fixup_references uf layout))
|
||||||
|
acc in
|
||||||
|
if List.length fixedup = prev_len
|
||||||
|
then
|
||||||
|
List.map
|
||||||
|
(fun (name, layout) ->
|
||||||
|
(UF.find uf name, layout))
|
||||||
|
fixedup
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Hashtbl.clear tbl ;
|
||||||
|
help (List.length fixedup) [] fixedup
|
||||||
|
end
|
||||||
|
| (name, layout) :: tl ->
|
||||||
|
match Hashtbl.find_opt tbl layout with
|
||||||
|
| None ->
|
||||||
|
let desc = UF.find uf name in
|
||||||
|
begin
|
||||||
|
Hashtbl.add tbl layout desc ;
|
||||||
|
help prev_len ((desc.title, layout) :: acc) tl
|
||||||
|
end
|
||||||
|
| Some original_desc ->
|
||||||
|
begin
|
||||||
|
UF.union uf
|
||||||
|
~new_cannonical:original_desc
|
||||||
|
~existing:name ;
|
||||||
|
help prev_len acc tl
|
||||||
|
end
|
||||||
|
in
|
||||||
|
help 0 []
|
||||||
|
|
||||||
|
|
||||||
type pdesc = P : 'x Encoding.desc -> pdesc
|
type pdesc = P : 'x Encoding.desc -> pdesc
|
||||||
let describe (type x) ?toplevel_name (encoding : x Encoding.t) =
|
let describe (type x) (encoding : x Encoding.t) =
|
||||||
let open Encoding in
|
let open Encoding in
|
||||||
let uf = UF.empty () in
|
let uf = UF.empty () in
|
||||||
let uf_add_name name =
|
let uf_add_name title =
|
||||||
UF.add uf { name ; description = None } in
|
UF.add uf { title ; description = None } in
|
||||||
let add_reference name description { descriptions } =
|
let add_reference name description { descriptions } =
|
||||||
{ descriptions = (name, description) :: descriptions } in
|
{ descriptions = (name, description) :: descriptions } in
|
||||||
let new_reference =
|
let new_reference =
|
||||||
@ -203,10 +241,10 @@ let describe (type x) ?toplevel_name (encoding : x Encoding.t) =
|
|||||||
tag_size = size ;
|
tag_size = size ;
|
||||||
cases }) references in
|
cases }) references in
|
||||||
(name, references)
|
(name, references)
|
||||||
and describe : type b. ?description:string -> name:string ->
|
and describe : type b. ?description:string -> title:string ->
|
||||||
recursives -> references -> b desc -> string * references =
|
string -> recursives -> references -> b desc -> string * references =
|
||||||
fun ?description ~name recursives references encoding ->
|
fun ?description ~title name recursives references encoding ->
|
||||||
let new_cannonical = { Binary_schema.name ; description } in
|
let new_cannonical = { Binary_schema.title ; description } in
|
||||||
UF.add uf new_cannonical ;
|
UF.add uf new_cannonical ;
|
||||||
let layout, references = layout None recursives references encoding in
|
let layout, references = layout None recursives references encoding in
|
||||||
begin
|
begin
|
||||||
@ -291,13 +329,14 @@ let describe (type x) ?toplevel_name (encoding : x Encoding.t) =
|
|||||||
| Union { kind ; tag_size ; cases } ->
|
| Union { kind ; tag_size ; cases } ->
|
||||||
let name, references = union recursives references kind tag_size cases in
|
let name, references = union recursives references kind tag_size cases in
|
||||||
([ Anonymous_field (kind, Ref name) ], references)
|
([ Anonymous_field (kind, Ref name) ], references)
|
||||||
| (Mu { kind ; name ; title = _ ; description ; fix } as encoding) ->
|
| (Mu { kind ; name ; title ; description ; fix } as encoding) ->
|
||||||
let kind = (kind :> Kind.t) in
|
let kind = (kind :> Kind.t) in
|
||||||
|
let title = Option.unopt ~default:name title in
|
||||||
if List.mem name recursives
|
if List.mem name recursives
|
||||||
then ([ Anonymous_field (kind, Ref name) ], references)
|
then ([ Anonymous_field (kind, Ref name) ], references)
|
||||||
else
|
else
|
||||||
let { encoding } = fix { encoding ; json_encoding = None } in
|
let { encoding } = fix { encoding ; json_encoding = None } in
|
||||||
let (name, references) = describe ~name ?description (name :: recursives) references encoding in
|
let (name, references) = describe ~title ?description name (name :: recursives) references encoding in
|
||||||
([ Anonymous_field (kind, Ref name) ], references)
|
([ Anonymous_field (kind, Ref name) ], references)
|
||||||
| Bool as encoding ->
|
| Bool as encoding ->
|
||||||
let layout, references =
|
let layout, references =
|
||||||
@ -423,12 +462,13 @@ let describe (type x) ?toplevel_name (encoding : x Encoding.t) =
|
|||||||
(* FIXMe ref_name ?? *)
|
(* FIXMe ref_name ?? *)
|
||||||
let name, references = union recursives references kind tag_size cases in
|
let name, references = union recursives references kind tag_size cases in
|
||||||
(Ref name, references)
|
(Ref name, references)
|
||||||
| Mu { name ; description ; fix } as encoding ->
|
| Mu { name ; title ; description ; fix } as encoding ->
|
||||||
|
let title = Option.unopt ~default:name title in
|
||||||
if List.mem name recursives
|
if List.mem name recursives
|
||||||
then (Ref name, references)
|
then (Ref name, references)
|
||||||
else
|
else
|
||||||
let { encoding } = fix { encoding ; json_encoding = None } in
|
let { encoding } = fix { encoding ; json_encoding = None } in
|
||||||
let (name, references) = describe ~name ?description (name :: recursives) references encoding in
|
let (name, references) = describe name ~title ?description (name :: recursives) references encoding in
|
||||||
(Ref name, references)
|
(Ref name, references)
|
||||||
| Conv { encoding } ->
|
| Conv { encoding } ->
|
||||||
layout ref_name recursives references encoding.encoding
|
layout ref_name recursives references encoding.encoding
|
||||||
@ -439,51 +479,16 @@ let describe (type x) ?toplevel_name (encoding : x Encoding.t) =
|
|||||||
| (Dynamic_size _) as encoding ->
|
| (Dynamic_size _) as encoding ->
|
||||||
let name = may_new_reference ref_name in
|
let name = may_new_reference ref_name in
|
||||||
let fields, references = fields None recursives references encoding in
|
let fields, references = fields None recursives references encoding in
|
||||||
UF.add uf { name ; description = None } ;
|
UF.add uf { title = name ; description = None } ;
|
||||||
(Ref name, add_reference name (obj fields) references)
|
(Ref name, add_reference name (obj fields) references)
|
||||||
| Check_size { encoding } ->
|
| Check_size { encoding } ->
|
||||||
layout ref_name recursives references encoding.encoding
|
layout ref_name recursives references encoding.encoding
|
||||||
| Delayed func ->
|
| Delayed func ->
|
||||||
layout ref_name recursives references (func ()).encoding in
|
layout ref_name recursives references (func ()).encoding in
|
||||||
let toplevel_name = Option.unopt ~default:"Toplevel encoding" toplevel_name in
|
let fields, references =
|
||||||
uf_add_name toplevel_name ;
|
fields None [] { descriptions = [] } encoding.encoding in
|
||||||
let fields, references = fields None [] { descriptions = [] } encoding.encoding in
|
uf_add_name "" ;
|
||||||
let rev_references = (toplevel_name, obj fields) :: references.descriptions in
|
let _, toplevel = List.hd (dedup_canonicalize uf ["", obj fields]) in
|
||||||
let dedup_canonicalize =
|
|
||||||
let tbl : (Binary_schema.toplevel_encoding, Binary_schema.description) Hashtbl.t = Hashtbl.create 100 in
|
|
||||||
let rec help prev_len acc = function
|
|
||||||
| [] ->
|
|
||||||
let fixedup =
|
|
||||||
List.map
|
|
||||||
(fun (desc, layout) -> (desc, fixup_references uf layout))
|
|
||||||
acc in
|
|
||||||
if List.length fixedup = prev_len
|
|
||||||
then
|
|
||||||
List.map
|
|
||||||
(fun (name, layout) ->
|
|
||||||
(UF.find uf name, layout))
|
|
||||||
fixedup
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
Hashtbl.clear tbl ;
|
|
||||||
help (List.length fixedup) [] fixedup
|
|
||||||
end
|
|
||||||
| (name, layout) :: tl ->
|
|
||||||
match Hashtbl.find_opt tbl layout with
|
|
||||||
| None ->
|
|
||||||
let desc = UF.find uf name in
|
|
||||||
begin
|
|
||||||
Hashtbl.add tbl layout desc ;
|
|
||||||
help prev_len ((desc.name, layout) :: acc) tl
|
|
||||||
end
|
|
||||||
| Some original_desc ->
|
|
||||||
begin
|
|
||||||
UF.union uf
|
|
||||||
~new_cannonical:original_desc
|
|
||||||
~existing:name ;
|
|
||||||
help prev_len acc tl
|
|
||||||
end
|
|
||||||
in help 0 [] in
|
|
||||||
let filtered =
|
let filtered =
|
||||||
List.filter
|
List.filter
|
||||||
(fun (name, encoding) ->
|
(fun (name, encoding) ->
|
||||||
@ -492,10 +497,9 @@ let describe (type x) ?toplevel_name (encoding : x Encoding.t) =
|
|||||||
UF.union uf ~new_cannonical:(UF.find uf name) ~existing:reference ;
|
UF.union uf ~new_cannonical:(UF.find uf name) ~existing:reference ;
|
||||||
false
|
false
|
||||||
| _ -> true)
|
| _ -> true)
|
||||||
rev_references in
|
references.descriptions in
|
||||||
let filtered = dedup_canonicalize filtered in
|
let fields = List.rev (dedup_canonicalize uf filtered) in
|
||||||
let is_top = (fun (Binary_schema.{ name }, _) -> name = toplevel_name) in
|
{ Binary_schema.toplevel ; fields }
|
||||||
let description, toplevel = List.find is_top filtered in
|
|
||||||
let fields = List.filter (fun d -> not (is_top d)) filtered in
|
|
||||||
{ Binary_schema.description ; toplevel ; fields }
|
|
||||||
|
|
||||||
|
@ -7,4 +7,4 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
val describe : ?toplevel_name:string -> 'a Encoding.t -> Binary_schema.t
|
val describe: 'a Encoding.t -> Binary_schema.t
|
||||||
|
@ -41,85 +41,86 @@ and toplevel_encoding =
|
|||||||
cases : (int * string) list }
|
cases : (int * string) list }
|
||||||
|
|
||||||
and description =
|
and description =
|
||||||
{ name : string ;
|
{ title : string ;
|
||||||
description : string option }
|
description : string option }
|
||||||
|
|
||||||
|
|
||||||
type t = {
|
type t = {
|
||||||
description: description ;
|
|
||||||
toplevel: toplevel_encoding ;
|
toplevel: toplevel_encoding ;
|
||||||
fields: (description * toplevel_encoding) list ;
|
fields: (description * toplevel_encoding) list ;
|
||||||
}
|
}
|
||||||
|
|
||||||
module Printer = struct
|
module Printer_ast = struct
|
||||||
|
|
||||||
type table =
|
type table =
|
||||||
{ title : string ;
|
{ headers : string list ;
|
||||||
description : string option ;
|
|
||||||
headers : string list ;
|
|
||||||
body : string list list }
|
body : string list list }
|
||||||
|
|
||||||
type print_structure =
|
type t =
|
||||||
| Table of table
|
| Table of table
|
||||||
| Union of string * string option * Binary_size.tag_size * table list
|
| Union of Binary_size.tag_size * (description * table) list
|
||||||
|
|
||||||
let pp_kind ppf = function
|
let pp_size ppf = function
|
||||||
| `Fixed size -> Format.fprintf ppf "%d byte%s" size (if size = 1 then "" else "s")
|
| `Fixed size ->
|
||||||
| `Variable -> Format.fprintf ppf "Variable size"
|
Format.fprintf ppf "%d byte%s" size (if size = 1 then "" else "s")
|
||||||
| `Dynamic -> Format.fprintf ppf "Determined from data"
|
| `Variable ->
|
||||||
|
Format.fprintf ppf "Variable"
|
||||||
|
| `Dynamic ->
|
||||||
|
Format.fprintf ppf "Determined from data"
|
||||||
|
|
||||||
let pp_int ppf (int : integer_extended) =
|
let pp_int ppf (int : integer_extended) =
|
||||||
Format.fprintf ppf "%s"
|
Format.fprintf ppf "%s"
|
||||||
begin
|
begin
|
||||||
match int with
|
match int with
|
||||||
| `Int16 -> "16 bit Signed Integer"
|
| `Int16 -> "signed 16-bit integer"
|
||||||
| `Int31 -> "32 bit Signed Integer in the range [2^30, 2^30-1]"
|
| `Int31 -> "signed 31-bit integer"
|
||||||
| `Uint30 -> "32 bit Signed Integer in the range [0, 2^30-1]"
|
| `Uint30 -> "unsigned 30-bit integer"
|
||||||
| `Int32 -> "32 bit Signed Integer"
|
| `Int32 -> "signed 32-bit integer"
|
||||||
| `Int64 -> "64 bit Signed Integer"
|
| `Int64 -> "signed 64-bit integer"
|
||||||
| `Int8 -> "8 bit Signed Integer"
|
| `Int8 -> "signed 8-bit integer"
|
||||||
| `Uint16 -> "16 bit Unsigned Integer"
|
| `Uint16 -> "unsigned 16-bit integer"
|
||||||
| `Uint8 -> "8 bit Unsigned Integer"
|
| `Uint8 -> "unsigned 8-bit integer"
|
||||||
end
|
end
|
||||||
|
|
||||||
let rec pp_layout ppf = function
|
let rec pp_layout ppf = function
|
||||||
| Zero_width ->
|
| Zero_width ->
|
||||||
Format.fprintf ppf "Zero width data, not actually present in the encoding"
|
Format.fprintf ppf "placeholder (not actually present in the encoding)"
|
||||||
| Int integer ->
|
| Int integer ->
|
||||||
Format.fprintf ppf "%a" pp_int integer
|
Format.fprintf ppf "%a" pp_int integer
|
||||||
| Bool ->
|
| Bool ->
|
||||||
Format.fprintf ppf "8 bit unsigned integer: 0 for false and 255 for true"
|
Format.fprintf ppf "boolean (0 for false, 255 for true)"
|
||||||
| RangedInt (minimum, maximum) ->
|
| RangedInt (minimum, maximum) when minimum <= 0 ->
|
||||||
Format.fprintf ppf "%a in the range %d to %d"
|
Format.fprintf ppf "%a in the range %d to %d"
|
||||||
pp_int ((Binary_size.range_to_size ~minimum ~maximum) :> integer_extended) minimum maximum
|
pp_int ((Binary_size.range_to_size ~minimum ~maximum) :> integer_extended)
|
||||||
|
minimum maximum
|
||||||
|
| RangedInt (minimum, maximum) (* when minimum > 0 *) ->
|
||||||
|
Format.fprintf ppf "%a in the range %d to %d (shifted by %d)"
|
||||||
|
pp_int ((Binary_size.range_to_size ~minimum ~maximum) :> integer_extended)
|
||||||
|
minimum maximum minimum
|
||||||
| RangedFloat (minimum, maximum) ->
|
| RangedFloat (minimum, maximum) ->
|
||||||
Format.fprintf ppf
|
Format.fprintf ppf
|
||||||
"Double precision (8 bytes) floating point number in the range %f to %f"
|
"double-precision floating-point number, in the range %f to %f"
|
||||||
minimum maximum
|
minimum maximum
|
||||||
| Float ->
|
| Float ->
|
||||||
Format.fprintf ppf "Double precision (8 bytes) floating point number"
|
Format.fprintf ppf "double-precision floating-point number"
|
||||||
| Bytes ->
|
| Bytes ->
|
||||||
Format.fprintf ppf "Bytes"
|
Format.fprintf ppf "bytes"
|
||||||
| String ->
|
| String ->
|
||||||
Format.fprintf ppf "String"
|
Format.fprintf ppf "bytes"
|
||||||
| Ref reference ->
|
| Ref reference ->
|
||||||
Format.fprintf ppf "$%s" reference
|
Format.fprintf ppf "$%s" reference
|
||||||
| Enum (size, reference) ->
|
| Enum (size, reference) ->
|
||||||
Format.fprintf ppf "%a encoding an enumeration (see %s)"
|
Format.fprintf ppf "%a encoding an enumeration (see %s)"
|
||||||
pp_int (size :> integer_extended)
|
pp_int (size :> integer_extended)
|
||||||
reference
|
reference
|
||||||
| Seq (Ref reference) -> Format.fprintf ppf "Sequence of %s" reference
|
| Seq (Ref reference) -> Format.fprintf ppf "sequence of $%s" reference
|
||||||
| Seq data -> Format.fprintf ppf "Sequence of %a" pp_layout data
|
| Seq data -> Format.fprintf ppf "sequence of %a" pp_layout data
|
||||||
|
|
||||||
|
|
||||||
let binary_table_headers = [ "Name" ; "Size" ; "Contents" ]
|
|
||||||
let enum_headers = [ "Case number" ; "Encoded string" ]
|
|
||||||
|
|
||||||
let pp_tag_size ppf tag =
|
let pp_tag_size ppf tag =
|
||||||
Format.fprintf ppf "%s" @@
|
Format.fprintf ppf "%s" @@
|
||||||
match tag with
|
match tag with
|
||||||
| `Uint8 -> "8 bit"
|
| `Uint8 -> "8-bit"
|
||||||
| `Uint16 -> "16 bit"
|
| `Uint16 -> "16-bit"
|
||||||
|
|
||||||
let field_descr () =
|
let field_descr () =
|
||||||
let reference = ref 0 in
|
let reference = ref 0 in
|
||||||
@ -130,41 +131,46 @@ module Printer = struct
|
|||||||
string_of_int value in
|
string_of_int value in
|
||||||
function
|
function
|
||||||
| Named_field (name, kind, desc) ->
|
| Named_field (name, kind, desc) ->
|
||||||
[ name ; Format.asprintf "%a" pp_kind kind ; string_of_layout desc ]
|
[ name ; Format.asprintf "%a" pp_size kind ; string_of_layout desc ]
|
||||||
| Dynamic_size_field (Some name, 1, size) ->
|
| Dynamic_size_field (Some name, 1, size) ->
|
||||||
[ Format.asprintf "# bytes in field \"%s\"" name ;
|
[ Format.asprintf "# bytes in field \"%s\"" name ;
|
||||||
Format.asprintf "%a"
|
Format.asprintf "%a"
|
||||||
pp_kind (`Fixed (Binary_size.integer_to_size size)) ;
|
pp_size (`Fixed (Binary_size.integer_to_size size)) ;
|
||||||
string_of_layout (Int (size :> integer_extended)) ]
|
string_of_layout (Int (size :> integer_extended)) ]
|
||||||
| Dynamic_size_field (None, 1, size) ->
|
| Dynamic_size_field (None, 1, size) ->
|
||||||
[ Format.asprintf "# bytes in next field" ;
|
[ Format.asprintf "# bytes in next field" ;
|
||||||
Format.asprintf "%a"
|
Format.asprintf "%a"
|
||||||
pp_kind (`Fixed (Binary_size.integer_to_size size)) ;
|
pp_size (`Fixed (Binary_size.integer_to_size size)) ;
|
||||||
string_of_layout (Int (size :> integer_extended)) ]
|
string_of_layout (Int (size :> integer_extended)) ]
|
||||||
| Dynamic_size_field (_, i, size) ->
|
| Dynamic_size_field (_, i, size) ->
|
||||||
[ Format.asprintf "# bytes in next %d fields" i ;
|
[ Format.asprintf "# bytes in next %d fields" i ;
|
||||||
Format.asprintf "%a"
|
Format.asprintf "%a"
|
||||||
pp_kind (`Fixed (Binary_size.integer_to_size size)) ;
|
pp_size (`Fixed (Binary_size.integer_to_size size)) ;
|
||||||
string_of_layout (Int (size :> integer_extended)) ]
|
string_of_layout (Int (size :> integer_extended)) ]
|
||||||
| Anonymous_field (kind, desc) ->
|
| Anonymous_field (kind, desc) ->
|
||||||
[ "Unnamed field " ^ anon_num () ;
|
[ "Unnamed field " ^ anon_num () ;
|
||||||
Format.asprintf "%a" pp_kind kind ;
|
Format.asprintf "%a" pp_size kind ;
|
||||||
string_of_layout desc ]
|
string_of_layout desc ]
|
||||||
| Optional_field name ->
|
| Optional_field name ->
|
||||||
[ Format.asprintf "? presence of field \"%s\"" name ;
|
[ Format.asprintf "? presence of field \"%s\"" name ;
|
||||||
Format.asprintf "%a" pp_kind (`Fixed 1) ;
|
Format.asprintf "%a" pp_size (`Fixed 1) ;
|
||||||
string_of_layout Bool ]
|
string_of_layout Bool ]
|
||||||
|
|
||||||
let toplevel ({ name ; description }, encoding) =
|
let binary_table_headers = [ "Name" ; "Size" ; "Contents" ]
|
||||||
|
let enum_headers = [ "Case number" ; "Encoded string" ]
|
||||||
|
|
||||||
|
let toplevel (descr, encoding) =
|
||||||
match encoding with
|
match encoding with
|
||||||
| Obj { fields } ->
|
| Obj { fields } ->
|
||||||
Table { title = Format.asprintf "%s" name ;
|
descr,
|
||||||
description ;
|
Table { headers = binary_table_headers ;
|
||||||
headers = binary_table_headers ;
|
|
||||||
body = List.map (field_descr ()) fields }
|
body = List.map (field_descr ()) fields }
|
||||||
| Cases { kind ; tag_size ; cases } ->
|
| Cases { kind ; tag_size ; cases } ->
|
||||||
Union (Format.asprintf "%s (%a, %a tag)" name pp_kind kind pp_tag_size tag_size,
|
{ title =
|
||||||
description, tag_size,
|
Format.asprintf "%s (%a, %a tag)"
|
||||||
|
descr.title pp_size kind pp_tag_size tag_size ;
|
||||||
|
description = descr.description},
|
||||||
|
Union (tag_size,
|
||||||
List.map
|
List.map
|
||||||
(fun (tag, name, fields) ->
|
(fun (tag, name, fields) ->
|
||||||
{ title =
|
{ title =
|
||||||
@ -173,19 +179,22 @@ module Printer = struct
|
|||||||
| Some name -> Format.asprintf "%s (tag %d)" name tag
|
| Some name -> Format.asprintf "%s (tag %d)" name tag
|
||||||
| None -> Format.asprintf "Tag %d" tag
|
| None -> Format.asprintf "Tag %d" tag
|
||||||
end;
|
end;
|
||||||
description = None ;
|
description = None },
|
||||||
headers = binary_table_headers ;
|
{ headers = binary_table_headers ;
|
||||||
body = List.map (field_descr ()) fields })
|
body = List.map (field_descr ()) fields })
|
||||||
cases)
|
cases)
|
||||||
| Int_enum { size ; cases } ->
|
| Int_enum { size ; cases } ->
|
||||||
|
{ title =
|
||||||
|
Format.asprintf "%s (Enumeration: %a):"
|
||||||
|
descr.title pp_int (size :> integer_extended) ;
|
||||||
|
description = descr.description },
|
||||||
Table
|
Table
|
||||||
{ title = Format.asprintf "Enum %s (%a):" name pp_int (size :> integer_extended) ;
|
{ headers = enum_headers ;
|
||||||
description = None;
|
|
||||||
headers = enum_headers ;
|
|
||||||
body = List.map (fun (num, str) -> [ string_of_int num ; str ]) cases }
|
body = List.map (fun (num, str) -> [ string_of_int num ; str ]) cases }
|
||||||
|
|
||||||
let to_print_ast encodings =
|
end
|
||||||
List.map toplevel encodings
|
|
||||||
|
module Printer = struct
|
||||||
|
|
||||||
let rec pad char ppf = function
|
let rec pad char ppf = function
|
||||||
| 0 -> ()
|
| 0 -> ()
|
||||||
@ -199,9 +208,9 @@ module Printer = struct
|
|||||||
if level = 2 then '=' else
|
if level = 2 then '=' else
|
||||||
'`' in
|
'`' in
|
||||||
let sub = String.map (fun _ -> char) title in
|
let sub = String.map (fun _ -> char) title in
|
||||||
Format.fprintf ppf "@[<v 0>%s@ %s@ @ @]" title sub
|
Format.fprintf ppf "%s@ %s@\n@\n" title sub
|
||||||
|
|
||||||
let pp_table ppf (level, { title ; description ; headers ; body }) =
|
let pp_table ppf { Printer_ast.headers ; body } =
|
||||||
let max_widths =
|
let max_widths =
|
||||||
List.fold_left (List.map2 (fun len str -> max (String.length str) len))
|
List.fold_left (List.map2 (fun len str -> max (String.length str) len))
|
||||||
(List.map String.length headers)
|
(List.map String.length headers)
|
||||||
@ -218,46 +227,52 @@ module Printer = struct
|
|||||||
List.iter2
|
List.iter2
|
||||||
(fun width _str -> Format.fprintf ppf "%a+" (pad c) (width + 2))
|
(fun width _str -> Format.fprintf ppf "%a+" (pad c) (width + 2))
|
||||||
max_widths) in
|
max_widths) in
|
||||||
let pp_option_nl ppf =
|
Format.fprintf ppf "%a@\n%a@\n%a@\n%a@\n@\n"
|
||||||
Option.iter ~f:(Format.fprintf ppf "%s@,@,") in
|
|
||||||
Format.fprintf ppf "@[<v 0>%a@,@,%a%a@,%a@,%a@,%a@,@]"
|
|
||||||
(pp_title level) title
|
|
||||||
pp_option_nl description
|
|
||||||
(pp_line '-') headers
|
(pp_line '-') headers
|
||||||
(pp_row ' ') headers
|
(pp_row ' ') headers
|
||||||
(pp_line '=') headers
|
(pp_line '=') headers
|
||||||
(Format.pp_print_list
|
(Format.pp_print_list
|
||||||
~pp_sep:(fun ppf () -> Format.fprintf ppf "@,")
|
~pp_sep:(fun ppf () -> Format.fprintf ppf "@\n")
|
||||||
(fun ppf s ->
|
(fun ppf s ->
|
||||||
Format.fprintf ppf "%a@,%a"
|
Format.fprintf ppf "%a@\n%a"
|
||||||
(pp_row ' ') s
|
(pp_row ' ') s
|
||||||
(pp_line '-') s))
|
(pp_line '-') s))
|
||||||
body
|
body
|
||||||
|
|
||||||
let pp_print_structure ?(initial_level=0) ppf = function
|
let pp_option_nl ppf =
|
||||||
| Table table -> pp_table ppf (1 + initial_level, table)
|
Option.iter ~f:(Format.fprintf ppf "%s@\n@\n")
|
||||||
| Union (name, description, _tag_size, tables) ->
|
|
||||||
Format.fprintf ppf "@[<v 0>%a@,@,%a@,%a@]"
|
|
||||||
(pp_title (initial_level + 1)) name
|
|
||||||
(fun ppf -> function
|
|
||||||
| None -> ()
|
|
||||||
| Some description ->
|
|
||||||
Format.fprintf ppf "@,%s" description)
|
|
||||||
description
|
|
||||||
(fun ppf -> Format.pp_print_list
|
|
||||||
~pp_sep:(fun ppf () -> Format.fprintf ppf "@,")
|
|
||||||
pp_table
|
|
||||||
ppf)
|
|
||||||
(List.map (fun x -> (initial_level + 2, x)) tables)
|
|
||||||
|
|
||||||
let pp ppf { description ; toplevel = t; fields } =
|
let pp_toplevel ppf = function
|
||||||
let s = toplevel (description, t) in
|
| Printer_ast.Table table -> pp_table ppf table
|
||||||
Format.fprintf ppf "%a@,%a"
|
| Union (_tag_size, tables) ->
|
||||||
(pp_print_structure ~initial_level:0) s
|
Format.fprintf ppf
|
||||||
|
"%a"
|
||||||
|
(fun ppf ->
|
||||||
|
Format.pp_print_list
|
||||||
|
~pp_sep:(fun ppf () -> Format.fprintf ppf "@\n")
|
||||||
|
(fun ppf (descr, table) ->
|
||||||
|
Format.fprintf ppf
|
||||||
|
"%a%a%a"
|
||||||
|
(pp_title 2) descr.title
|
||||||
|
pp_option_nl descr.description
|
||||||
|
pp_table table)
|
||||||
|
ppf)
|
||||||
|
tables
|
||||||
|
|
||||||
|
let pp ppf { toplevel; fields } =
|
||||||
|
let _, toplevel =
|
||||||
|
Printer_ast.toplevel ({ title = "" ; description = None}, toplevel) in
|
||||||
|
Format.fprintf ppf "%a@\n%a"
|
||||||
|
pp_toplevel toplevel
|
||||||
(Format.pp_print_list
|
(Format.pp_print_list
|
||||||
~pp_sep:(fun ppf () -> Format.fprintf ppf "@,")
|
~pp_sep:(fun ppf () -> Format.fprintf ppf "@\n")
|
||||||
(pp_print_structure ~initial_level:0))
|
(fun ppf (descr, toplevel) ->
|
||||||
(to_print_ast fields)
|
Format.fprintf ppf
|
||||||
|
"%a%a%a"
|
||||||
|
(pp_title 1) descr.title
|
||||||
|
pp_option_nl descr.description
|
||||||
|
pp_toplevel toplevel))
|
||||||
|
(List.map Printer_ast.toplevel fields)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -265,10 +280,10 @@ module Encoding = struct
|
|||||||
|
|
||||||
let description_encoding =
|
let description_encoding =
|
||||||
conv
|
conv
|
||||||
(fun { name ; description } -> (name, description))
|
(fun { title ; description } -> (title, description))
|
||||||
(fun (name, description) -> { name ; description })
|
(fun (title, description) -> { title ; description })
|
||||||
(obj2
|
(obj2
|
||||||
(req "name" string)
|
(req "title" string)
|
||||||
(opt "description" string))
|
(opt "description" string))
|
||||||
|
|
||||||
|
|
||||||
@ -514,12 +529,9 @@ module Encoding = struct
|
|||||||
|
|
||||||
let encoding =
|
let encoding =
|
||||||
conv
|
conv
|
||||||
(fun { description ; toplevel ; fields } ->
|
(fun { toplevel ; fields } -> (toplevel, fields))
|
||||||
(description, toplevel, fields))
|
(fun (toplevel, fields) -> { toplevel ; fields }) @@
|
||||||
(fun (description, toplevel, fields) ->
|
obj2
|
||||||
{ description ; toplevel ; fields }) @@
|
|
||||||
obj3
|
|
||||||
(req "description" description_encoding)
|
|
||||||
(req "toplevel" binary_description_encoding)
|
(req "toplevel" binary_description_encoding)
|
||||||
(req "fields"
|
(req "fields"
|
||||||
(list
|
(list
|
||||||
|
@ -41,18 +41,13 @@ and toplevel_encoding =
|
|||||||
cases : (int * string) list }
|
cases : (int * string) list }
|
||||||
|
|
||||||
and description =
|
and description =
|
||||||
{ name : string ;
|
{ title : string ;
|
||||||
description : string option }
|
description : string option }
|
||||||
|
|
||||||
type t = {
|
type t = {
|
||||||
description: description ;
|
|
||||||
toplevel: toplevel_encoding ;
|
toplevel: toplevel_encoding ;
|
||||||
fields: (description * toplevel_encoding) list ;
|
fields: (description * toplevel_encoding) list ;
|
||||||
}
|
}
|
||||||
|
|
||||||
module Printer : sig
|
|
||||||
val pp_layout : Format.formatter -> layout -> unit
|
|
||||||
end
|
|
||||||
|
|
||||||
val pp: Format.formatter -> t -> unit
|
val pp: Format.formatter -> t -> unit
|
||||||
val encoding: t Encoding.t
|
val encoding: t Encoding.t
|
||||||
|
@ -679,7 +679,7 @@ module Binary: sig
|
|||||||
it raises [Write_error] instead of return [None] in case of error. *)
|
it raises [Write_error] instead of return [None] in case of error. *)
|
||||||
val to_bytes_exn : 'a Encoding.t -> 'a -> MBytes.t
|
val to_bytes_exn : 'a Encoding.t -> 'a -> MBytes.t
|
||||||
|
|
||||||
val describe : ?toplevel_name:string -> 'a Encoding.t -> Binary_schema.t
|
val describe : 'a Encoding.t -> Binary_schema.t
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user