123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2022 Trili Tech <contact@trili.tech> *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining a *)(* copy of this software and associated documentation files (the "Software"),*)(* to deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)(* and/or sell copies of the Software, and to permit persons to whom the *)(* Software is furnished to do so, subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be included *)(* in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)(* DEALINGS IN THE SOFTWARE. *)(* *)(*****************************************************************************)exceptionBoundsexceptionSizeOverflowmoduletypeKeyS=sigincludeMap.OrderedTypevalunsigned_compare:t->t->intvalzero:tvaladd:t->t->tvalsub:t->t->tvalpred:t->tvalsucc:t->tvalto_string:t->stringendmoduletypeS=sigtypekeytype'aproducer=key->'aLwt.tmoduleMap:Lazy_map.Swithtypekey=keytype'atvalpp:(Format.formatter->'a->unit)->Format.formatter->'at->unitvalto_string:('a->string)->'at->stringvalstring_of_key:key->stringvalnum_elements:'at->keyvalcreate:?first_key:key->?values:'aMap.Map.t->?produce_value:'aproducer->?origin:Tezos_tree_encoding.wrapped_tree->key->'atvalorigin:'at->Tezos_tree_encoding.wrapped_treeoptionvalempty:unit->'atvalsingleton:'a->'atvalof_list:'alist->'atvalget:key->'at->'aLwt.tvalset:key->'a->'at->'atvalcons:'a->'at->'atvalsplit:'at->key->'at*'atvalgrow:?default:(unit->'a)->key->'at->'atvaldrop:'at->'atvalpop:'at->('a*'at)Lwt.tvalprepend_list:'alist->'at->'atvalappend:'a->'at->'at*keyvalconcat:'at->'at->'atLwt.tvalunsafe_concat:'at->'at->'atvalto_list:'at->'alistLwt.tvalloaded_bindings:'at->(key*'aoption)listvalfirst_key:'at->keyvalencoding:keyTezos_tree_encoding.t->'aTezos_tree_encoding.t->'atTezos_tree_encoding.tendmoduleZZ:KeySwithtypet=Z.t=structincludeZ(** Note that, in fixed sized integers we need to use a specialized `unsigned`
version of compare. This is because, internally, some keys can be
represented by negative integers (using wraparound). For example after a
while the value of num_elements will surpass max_int and so it will
become negative Nevertheless we still want this to represent large
unsigned integers (up until 2*max_int). In the case of Z this is not an
issue as there is no wraparound.*)letunsigned_compare=Z.compareendmoduleMake_no_enc(Key:KeyS)=structmoduleMap=Lazy_map.Make(Key)typekey=Key.ttype'aproducer=key->'aLwt.ttype'at={first:key;num_elements:key;values:'aMap.t}letpppp_valuefmtmap=Format.fprintffmt"@[<hv 2>{ first = %s;@ num_elements = %s;@ values = %a }@]"(Key.to_stringmap.first)(Key.to_stringmap.num_elements)(Map.pppp_value)map.valuesletto_stringshow_valuemap=letpp_valuefmtvalue=Format.pp_print_stringfmt(show_valuevalue)inFormat.asprintf"%a"(pppp_value)mapletstring_of_key=Key.to_stringletnum_elementsmap=map.num_elementsletcreate?(first_key=Key.zero)?values?produce_value?originnum_elements=letvalues=Map.create?values?produce_value?origin()in{first=first_key;num_elements;values}letorigin{values;_}=Map.originvaluesletempty()=createKey.zeroletof_listvalues=letfold(map,len)value=(Map.Map.addlenvaluemap,Key.succlen)inletvalues,num_elements=List.fold_leftfold(Map.Map.empty,Key.zero)valuesincreate~valuesnum_elementsletinvalid_keykeymap=Key.unsigned_comparekeymap.num_elements>=0letgetkeymap=ifinvalid_keykeymapthenraiseBounds;letkey=Key.addmap.firstkeyinMap.getkeymap.valuesletsetkeyvaluemap=ifinvalid_keykeymapthenraiseBounds;letkey=Key.addmap.firstkeyin{mapwithvalues=Map.setkeyvaluemap.values}letsingletonvalue=createKey.(succzero)|>setKey.zerovalueletoverflowk1k2=Key.unsigned_comparek1(Key.addk1k2)>0letconsvaluemap=ifoverflowmap.num_elements(Key.succKey.zero)thenraiseSizeOverflowelseletfirst=Key.predmap.firstinletvalues=Map.setfirstvaluemap.valuesinletnum_elements=Key.succmap.num_elementsin{first;values;num_elements}letsplitvecat=ifKey.(unsigned_compareatzero<0||unsigned_compare(num_elementsvec)at<0)thenraiseBoundselse({first=vec.first;num_elements=at;values=Map.dupvec.values},{first=Key.(addvec.firstat);num_elements=Key.(subvec.num_elementsat);values=Map.dupvec.values;})letappend_opteltmap=ifoverflowmap.num_elements(Key.succKey.zero)thenraiseSizeOverflowelseletnum_elements=map.num_elementsinletmap={mapwithnum_elements=Key.succnum_elements}inletmap=matcheltwithSomeelt->setnum_elementseltmap|None->mapin(map,num_elements)(* This version of drop simply doesn't check for bounds, but is used in
functions actually checking the bounds, to prevent doing it twice. *)letunsafe_dropmap=letvalues=Map.removemap.firstmap.valuesin{first=Key.succmap.first;num_elements=Key.predmap.num_elements;values;}letdropmap=ifKey.(unsigned_comparezeromap.num_elements<0)thenunsafe_dropmapelseraiseBoundsletpopmap=letopenLwt.SyntaxinifKey.(unsigned_comparezeromap.num_elements<0)thenlet+x=getKey.zeromapin(x,unsafe_dropmap)elseraiseBoundsletappendeltmap=append_opt(Someelt)mapletprepend_listeses0=letes=List.revesinletrecauxv=functionx::rst->aux(consxv)rst|[]->vinauxes0esletrecgrow?defaultdeltamap=ifoverflowmap.num_elementsdeltathenraiseSizeOverflowelseifKey.(delta<=zero)thenmapelseletmap,_=append_opt(Option.map(funf->f())default)mapingrow?defaultKey.(preddelta)mapletto_listmap=letopenLwt.Syntaxinletrecunrollaccindex=ifKey.unsigned_compareindexKey.zero>0thenlet*prefix=getindexmapin(unroll[@ocaml.tailcall])(prefix::acc)(Key.predindex)elselet*prefix=getKey.zeromapinLwt.return(prefix::acc)in(* The empty vector is not correctly taken into account otherwise, since
`pred zero` = `-1`, which is an invalid key according to
{!invalid_key}. *)ifmap.num_elements=Key.zerothenLwt.return[]else(unroll[@ocaml.tailcall])[](Key.predmap.num_elements)letconcatlhsrhs=letopenLwt.Syntaxinifoverflowlhs.num_elementsrhs.num_elementsthenraiseSizeOverflowelselet*lhs=to_listlhsinlet+rhs=to_listrhsinof_list(lhs@rhs)letloaded_bindingsm=Map.loaded_bindingsm.valuesletunsafe_concatlhsrhs=letlhs=loaded_bindingslhs|>List.mapsndinletrhs=loaded_bindingsrhs|>List.mapsndinof_list(List.filter_mapFun.id(lhs@rhs))letfirst_keyvector=vector.firstendmoduleMake(Key:KeyS):Swithtypekey=Key.t=structmoduleNo_enc=Make_no_enc(Key)moduleEncoding=Tezos_tree_encoding.Lazy_vector_encoding.Make(No_enc)includeNo_encletencoding=Encoding.lazy_vectorendmoduleInt=structincludeIntletunsigned_comparenm=compare(n-min_int)(m-min_int)endmoduleIntVector=Make(Int)moduleInt32Vector=Make(Int32)moduleInt64Vector=Make(Int64)moduleZVector=Make(ZZ)moduleMutable=structmoduletypeImmutableS=SmoduletypeS=sigtypekeymoduleVector:Swithtypekey=keytype'atvalnum_elements:'at->keyvalof_immutable:'aVector.t->'atvalcreate:?values:'aVector.Map.Map.t->?produce_value:'aVector.producer->?origin:Tezos_tree_encoding.wrapped_tree->key->'atvalorigin:'at->Tezos_tree_encoding.wrapped_treeoptionvalget:key->'at->'aLwt.tvalset:key->'a->'at->unitvalgrow:?default:(unit->'a)->key->'at->unitvalappend:'a->'at->keyvalcons:'a->'at->unitvaldrop:'at->unitvalpop:'at->'aLwt.tvalreset:'at->unitvalsnapshot:'at->'aVector.tendmoduleMake(Vector:ImmutableS):Swithtypekey=Vector.keyandmoduleVector=Vector=structmoduleVector=Vectortypekey=Vector.keytype'at='aVector.trefletnum_elementsmap_ref=Vector.num_elements!map_refletof_immutable=refletcreate?values?produce_value?originnum_elements=of_immutable(Vector.create?values?produce_value?originnum_elements)letoriginvector=Vector.origin!vectorletgetkeymap_ref=Vector.getkey!map_refletsetkeyvaluemap_ref=map_ref:=Vector.setkeyvalue!map_refletgrow?defaultdeltamap_ref=map_ref:=Vector.grow?defaultdelta!map_refletappendeltmap_ref=letnew_map,i=Vector.appendelt!map_refinmap_ref:=new_map;iletconsamap_ref=map_ref:=Vector.consa!map_refletdropmap_ref=map_ref:=Vector.drop!map_refletpopmap_ref=letopenLwt.Syntaxinlet+v,map=Vector.pop!map_refinmap_ref:=map;vletresetmap_ref=map_ref:=Vector.empty()letsnapshotmap_ref=!map_refendmoduleIntVector=Make(IntVector)moduleInt32Vector=Make(Int32Vector)moduleInt64Vector=Make(Int64Vector)moduleZVector=Make(ZVector)end