1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
|
open Bin_prot
open Typerep_extended.Std
let make_vtag_read_err () =
let str_name = "Reader.unsafe_vtag_read" in
fun _buf ~pos_ref:_ -> Bin_prot.Common.raise_variant_wrong_type str_name
module Computation_impl = struct
type 'a t = 'a Type_class.reader
include Type_generic.Variant_and_record_intf.M(struct type nonrec 'a t = 'a t end)
let int = Type_class.bin_reader_int
let int32 = Type_class.bin_reader_int32
let int64 = Type_class.bin_reader_int64
let nativeint = Type_class.bin_reader_nativeint
let char = Type_class.bin_reader_char
let float = Type_class.bin_reader_float
let string = Type_class.bin_reader_string
let bool = Type_class.bin_reader_bool
let unit = Type_class.bin_reader_unit
let option = Type_class.bin_reader_option
let list = Type_class.bin_reader_list
let array = Type_class.bin_reader_array
let lazy_t = Type_class.bin_reader_lazy
let ref_ = Type_class.bin_reader_ref
(* bin_io does *NOT* support serialization of functions *)
let function_ _ = assert false
let tuple2 ra rb =
(* beware of (expr1, expr2) notation, expr1 has to be executed before expr2
thus, we use there let a = expr1 in let b = expr2 in a, b *)
let read buf ~pos_ref =
let a = ra.Type_class.read buf ~pos_ref in
let b = rb.Type_class.read buf ~pos_ref in
(a,b)
in
let vtag_read = make_vtag_read_err () in
{ Type_class. read ; vtag_read }
let tuple3 ra rb rc =
let read buf ~pos_ref =
let a = ra.Type_class.read buf ~pos_ref in
let b = rb.Type_class.read buf ~pos_ref in
let c = rc.Type_class.read buf ~pos_ref in
(a,b,c)
in
let vtag_read = make_vtag_read_err () in
{ Type_class. read ; vtag_read }
let tuple4 ra rb rc rd =
let read buf ~pos_ref =
let a = ra.Type_class.read buf ~pos_ref in
let b = rb.Type_class.read buf ~pos_ref in
let c = rc.Type_class.read buf ~pos_ref in
let d = rd.Type_class.read buf ~pos_ref in
(a,b,c,d)
in
let vtag_read = make_vtag_read_err () in
{ Type_class. read ; vtag_read }
let tuple5 ra rb rc rd re =
let read buf ~pos_ref =
let a = ra.Type_class.read buf ~pos_ref in
let b = rb.Type_class.read buf ~pos_ref in
let c = rc.Type_class.read buf ~pos_ref in
let d = rd.Type_class.read buf ~pos_ref in
let e = re.Type_class.read buf ~pos_ref in
(a,b,c,d,e)
in
let vtag_read = make_vtag_read_err () in
{ Type_class. read ; vtag_read }
let record record =
let length = Record.length record in
let read buf ~pos_ref =
let current_field_index = ref 0 in
let s = ref "" in
let get field =
let index = Field.index field in
let label = Field.label field in
s := !s ^ (Printf.sprintf "read %S index %d\n" label index);
if index <> !current_field_index then (
s := !s^ (Printf.sprintf "current=%d\n" !current_field_index);
raise (Failure !s)
);
current_field_index := (succ index) mod length;
(Field.traverse field).Type_class.read buf ~pos_ref
in
let t = Record.create record { Record.get } in
if current_field_index.contents <> 0 then assert false;
t
in
let vtag_read = make_vtag_read_err () in
{ Type_class. read ; vtag_read }
let variant variant =
let length = Variant.length variant in
let is_polymorphic = Variant.is_polymorphic variant in
let repr_reader =
if is_polymorphic
then
Bin_prot.Read.bin_read_variant_int
else
if length < 256
then
Bin_prot.Read.bin_read_int_8bit
else
Bin_prot.Read.bin_read_int_16bit
in
let read_with_repr =
let extract_key =
if is_polymorphic
then Tag.ocaml_repr
else Tag.index
in
let tags = Flat_map.Flat_int_map.init length ~f:(fun index ->
match Variant.tag variant index with
| (Variant.Tag tag) as data -> extract_key tag, data)
in
(fun buf ~pos_ref repr ->
match Flat_map.Flat_int_map.find tags repr with
| Some (Variant.Tag tag) -> begin
match Tag.create tag with
| Tag.Const const -> const
| Tag.Args create ->
let value = (Tag.traverse tag).Type_class.read buf ~pos_ref in
create value
end
| None ->
Bin_prot.Common.raise_read_error
(Bin_prot.Common.ReadError.Sum_tag "Binrep.Reader.variant") !pos_ref)
in
let vtag_read buf ~pos_ref vint =
if is_polymorphic
then
read_with_repr buf ~pos_ref vint
else
Bin_prot.Common.raise_variant_wrong_type "Binrep.Reader.variant" !pos_ref
in
let read buf ~pos_ref =
let repr = repr_reader buf ~pos_ref in
read_with_repr buf ~pos_ref repr
in
{ Type_class. read ; vtag_read }
module Named = struct
module Reader_named = Type_generic.Make_named_for_closure(struct
open Bin_prot.Common
type 'a input = buf
type 'a output = pos_ref:pos ref -> 'a
type 'a t = 'a Read.reader
end)
module Vtag_reader_named = Type_generic.Make_named_for_closure(struct
open Bin_prot.Common
type 'a input = buf
type 'a output = pos_ref:pos ref -> (int -> 'a)
type 'a t = (int -> 'a) Read.reader
end)
module Context = struct
type t = {
reader_ctx : Reader_named.Context.t ;
vtag_reader_cxt : Vtag_reader_named.Context.t ;
}
let create () = {
reader_ctx = Reader_named.Context.create () ;
vtag_reader_cxt = Vtag_reader_named.Context.create () ;
}
end
type 'a t = {
reader_named : 'a Reader_named.t;
vtag_reader_named : 'a Vtag_reader_named.t;
}
let init ctx name = let open Context in {
reader_named =
Reader_named.init ctx.reader_ctx name;
vtag_reader_named =
Vtag_reader_named.init ctx.vtag_reader_cxt name;
}
let get_wip_computation t = {
Type_class.
read =
Reader_named.get_wip_computation t.reader_named;
vtag_read =
Vtag_reader_named.get_wip_computation t.vtag_reader_named;
}
let set_final_computation t comp = {
Type_class.
read =
Reader_named.set_final_computation
t.reader_named comp.Type_class.read;
vtag_read =
Vtag_reader_named.set_final_computation
t.vtag_reader_named comp.Type_class.vtag_read;
}
let share _ = true
end
end
include Type_generic.Make(struct
include Computation_impl
let name = "bin_reader"
let required = [
Type_struct.Generic.ident;
Binrep_sizer.ident;
Binrep_writer.ident;
]
end)
|