123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114open!ImportexceptionInvalid_sizeofstring(** The exception raised when trying to encode a key or a value of size other
than encoded_size *)moduletypeKey=sigtypet[@@derivingrepr](** The type for keys. *)valequal:t->t->bool(** The equality function for keys. *)valhash:t->int(** Note: Unevenly distributed hash functions may result in performance drops. *)valhash_size:int(** The number of bits necessary to encode the maximum output value of
{!hash}. `Hashtbl.hash` uses 30 bits.
Overestimating the [hash_size] will result in performance drops;
underestimation will result in undefined behavior. *)valencode:t->string(** [encode] is an encoding function. The resultant encoded values must have
size {!encoded_size}. *)valencoded_size:int(** [encoded_size] is the size of the result of {!encode}, expressed in number
of bytes. *)valdecode:string->int->t(** [decode s off] is the decoded form of the encoded value at the offset
[off] of string [s]. Must satisfy [decode (encode t) 0 = t]. *)endmoduletypeValue=sigtypet[@@derivingrepr]valencode:t->stringvalencoded_size:intvaldecode:string->int->tendmoduleEntry=structmoduletypeS=sigtypekeytypevaluetypet=private{key:key;key_hash:int;value:value}[@@derivingrepr]valv:key->value->tvalencoded_size:intvalencoded_sizeL:int63valdecode:string->int->tvaldecode_key:string->int->key*intvaldecode_value:string->int->valuevalencode:t->(string->unit)->unitvalencode':key->value->(string->unit)->unitvalcompare:t->t->int(* Compare entries by their key hash. *)endmoduleMake(K:Key)(V:Value):Swithtypekey:=K.tandtypevalue:=V.t=structtypet={key:K.t;key_hash:int;value:V.t}[@@derivingrepr]letvkeyvalue={key;key_hash=K.hashkey;value}letencoded_size=K.encoded_size+V.encoded_sizeletencoded_sizeL=Int63.of_intencoded_sizeletdecodestringoff=letkey=K.decodestringoffinletvalue=V.decodestring(off+K.encoded_size)in{key;key_hash=K.hashkey;value}letdecode_keystringoff=letkey=K.decodestringoffin(key,K.hashkey)letdecode_valuestringoff=V.decodestring(off+K.encoded_size)letencode'keyvaluef=letencoded_key=K.encodekeyinletencoded_value=V.encodevalueinifString.lengthencoded_key<>K.encoded_sizethenraise(Invalid_sizeencoded_key);ifString.lengthencoded_value<>V.encoded_sizethenraise(Invalid_sizeencoded_value);f(encoded_key^encoded_value)letencode{key;value;_}f=encode'keyvaluefletcompareab=Int.comparea.key_hashb.key_hashendendmoduleString_fixed(L:sigvallength:intend):sigtypet=stringincludeKeywithtypet:=stringincludeValuewithtypet:=stringend=structtypet=string[@@derivingrepr]lethash=Hashtbl.hashlethash_size=30letencodes=sletdecodesoff=String.subsoffL.lengthletencoded_size=L.lengthletequal=String.equalend