123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018-2021 Tarides <contact@tarides.com> *)(* Copyright (c) 2021 Nomadic Labs, <contact@nomadic-labs.com> *)(* *)(* 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. *)(* *)(*****************************************************************************)openTezos_context_encoding.ContextmoduletypeDB=Irmin.Swithtypekey=Path.tandtypecontents=Contents.tandtypebranch=Branch.tandtypehash=Hash.tandtypestep=Path.stepandtypemetadata=Metadata.tandtypeKey.step=Path.stepmoduleMake_tree(Store:DB)=structincludeStore.Treeletpp=Irmin.Type.ppStore.tree_tletempty_=Store.Tree.emptyletequal=Irmin.Type.(unstage(equalStore.tree_t))letis_emptyt=equalStore.Tree.emptytlethasht=Hash.to_context_hash(Store.Tree.hasht)letaddtkv=Store.Tree.addtkvletkindt=matchStore.Tree.destructtwith`Contents_->`Value|`Node_->`Treeletto_valuet=matchStore.Tree.destructtwith|`Contents(c,_)->Store.Tree.Contents.force_exnc>|=Option.some|`Node_->Lwt.return_noneletof_value_v=Store.Tree.addStore.Tree.empty[]vletfold?depthtk~(order:[`Sorted|`Undefined])~init~f=find_treetk>>=function|None->Lwt.returninit|Somet->letorder=(order:>[`RandomofRandom.State.t|`Sorted|`Undefined])inStore.Tree.fold?depth~force:`True~cache:false~uniq:`False~order~tree:(funktacc->matchkindtwith|`Value->ifk=[]thenLwt.returnaccelsefktacc|`Tree->fktacc)tinittyperaw=[`Valueofbytes|`TreeofrawTzString.Map.t]typeconcrete=Store.Tree.concreteletrecraw_of_concrete:typea.(raw->a)->concrete->a=funk->function|`Treel->raw_of_node(funl->k(`Tree(TzString.Map.of_seql)))l|`Contents(v,_)->k(`Valuev)andraw_of_node:typea.((string*raw)Seq.t->a)->(string*concrete)list->a=funk->function|[]->kSeq.empty|(n,v)::t->raw_of_concrete(funv->raw_of_node(funt->k(fun()->Seq.Cons((n,v),t)))t)vletto_rawt=Store.Tree.to_concretet>|=raw_of_concrete(funt->t)letrecconcrete_of_raw:typea.(concrete->a)->raw->a=funk->function|`Treel->concrete_of_node(funl->k(`Treel))(TzString.Map.to_seql)|`Valuev->k(`Contents(v,()))andconcrete_of_node:typea.((string*concrete)list->a)->(string*raw)Seq.t->a=funkseq->matchseq()with|Nil->k[]|Cons((n,v),t)->concrete_of_raw(funv->concrete_of_node(funt->k((n,v)::t))t)vletof_raw=concrete_of_rawStore.Tree.of_concreteletraw_encoding:rawData_encoding.t=letopenData_encodinginmu"Tree.raw"(funencoding->letmap_encoding=convTzString.Map.bindings(funbindings->TzString.Map.of_seq(List.to_seqbindings))(list(tup2stringencoding))inunion[case~title:"tree"(Tag0)map_encoding(function`Treet->Somet|`Value_->None)(funt->`Treet);case~title:"value"(Tag1)bytes(function`Valuev->Somev|`Tree_->None)(funv->`Valuev);])typerepo=Store.repoletmake_repo=letprng_state=lazy(Random.State.make_self_init())in(* [irmin-pack] stores implicitly share instances according to a string
argument (for persistent stores, this is the store's file path). To avoid
having hidden global state, we generate a unique string each time. *)letrandom_store_name()=letprng_state=Lazy.forceprng_stateinString.init64(fun_->Char.chr(Random.State.intprng_state256))infun()->Store.Repo.v@@Irmin_pack.config@@random_store_name()letshallowrepokinded_hash=Store.Tree.shallowrepo(matchkinded_hashwith|`Nodehash->`Node(Hash.of_context_hashhash)|`Contentshash->`Contents(Hash.of_context_hashhash,()))letlisttree?offset?lengthkey=Store.Tree.list~cache:truetree?offset?lengthkeyexceptionContext_dangling_hashofstringletfind_treetreekey=Lwt.catch(fun()->Store.Tree.find_treetreekey)(function|Dangling_hash{context;hash}->letstr=Fmt.str"%s encountered dangling hash %a"context(Irmin.Type.ppHash.t)hashinraise(Context_dangling_hashstr)|exn->raiseexn)letadd_treetreekeyvalue=Lwt.catch(fun()->Store.Tree.add_treetreekeyvalue)(function|Dangling_hash{context;hash}->letstr=Fmt.str"%s encountered dangling hash %a"context(Irmin.Type.ppHash.t)hashinraise(Context_dangling_hashstr)|exn->raiseexn)endtypeerror+=Unsupported_context_hash_versionofContext_hash.Version.tlet()=register_error_kind`Permanent~id:"context_hash.unsupported_version"~title:"Unsupported context hash version"~description:"Unsupported context hash version."~pp:(funppfversion->Format.fprintfppf"@[Context hash version %a is not supported.@,\
You might need to update the shell.@]"Context_hash.Version.ppversion)Data_encoding.(obj1(req"version"Context_hash.Version.encoding))(function|Unsupported_context_hash_versionversion->Someversion|_->None)(funversion->Unsupported_context_hash_versionversion)