12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879type'at=Staticofint|Dynamicof'a|Unknowntype'asize='atletmap:typeab.(a->b)->at->bt=funf->function|Unknown->Unknown|Staticn->Staticn|Dynamica->Dynamic(fa)moduleSyntax=structlet(let+)xf=mapfxend(** A type wrapper for positional offsets into buffers (as opposed to e.g.
lengths of values in those buffers). *)typeoffset=Offsetofint[@@unboxed]moduleOffset=structtypet=offsetlet(+>):t->int->t=fun(Offsetn)m->Offset(n+m)let(<+):int->t->t=funn(Offsetm)->Offset(n+m)endmoduleSizer=structtype'at={of_value:('a->int)size;of_encoding:(string->Offset.t->Offset.t)size;}(** An ['a t] is a value that represents the size information known about a
particular codec for type ['a].
- [of_value]: given a value to encode, return the size of its encoding.
- [of_encoding]: given a buffer [buf] and an offset [off], return the
_offset_ immediately _after_ the encoding starting at [buf.\[off\]]
NOTE: not the length of the encoding itself, to enable chains of such
sizers to call each other in tail-position.
Invariant: [∀ n. (of_value = Static n) ⟺ (of_encoding = Static n)]. *)let(<+>):typea.at->at->at=letadd_of_value(a:_size)(b:_size):_size=match(a,b)with|Unknown,_|_,Unknown->Unknown|Statica,Staticb->Static(a+b)|Static0,other|other,Static0->other|Staticn,Dynamicf|Dynamicf,Staticn->Dynamic(funa->n+fa)|Dynamicf,Dynamicg->Dynamic(funa->fa+ga)inletadd_of_encoding(a:_size)(b:_size):_size=match(a,b)with|Unknown,_|_,Unknown->Unknown|Statica,Staticb->Static(a+b)|Static0,other|other,Static0->other|Dynamicf,Dynamicg->Dynamic(funbufoff->gbuf(fbufoff))(* NOTE: in these cases we could be slightly more efficient by storing a
vector of sizing functions inside [Dynamic], which would allow constant
folding for static segments of dynamically-sized types. *)|Staticn,Dynamicf->Dynamic(funbufoff->fbufOffset.(off+>n))|Dynamicf,Staticn->Dynamic(funbufoff->Offset.(fbufoff+>n))infunab->{of_value=add_of_valuea.of_valueb.of_value;of_encoding=add_of_encodinga.of_encodingb.of_encoding;}letstaticn={of_value=Staticn;of_encoding=Staticn}letdynamic~of_value~of_encoding={of_value=Dynamicof_value;of_encoding=Dynamicof_encoding}letusingft=letof_value=map(funsize_ofx->size_of(fx))t.of_valuein{twithof_value}letunknown={of_value=Unknown;of_encoding=Unknown}end