123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150(*****************************************************************************)(* *)(* MIT License *)(* Copyright (c) 2022 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. *)(* *)(*****************************************************************************)moduleStringMap=structmoduleM=Map.Make(String)includeMletof_listl=of_seq(List.to_seql)lett(inner:'aRepr.t):'atRepr.t=letmoduleM=Repr.Of_map(structincludeMletkey_t=Repr.stringend)inM.tinnerletto_bytesprintermap=fold(funkeyeltstate->Bytes.cat(Bytes.of_stringkey)(Bytes.cat(printerelt)state))mapBytes.emptyletshow(show_inner:'a->string):'at->string=funm->"{\n"^String.concat"\n"(List.map(fun(k,v)->k^": "^show_innerv)(bindingsm))^"\n}"(* Return the union of two maps. The keys of the maps have to be disjoint unless
specifically stated in common_keys. In this case both key's values
are asserted to be equal, with a given equality function.
If no equal function is given the polymorphic euqality is used.*)letunion_disjoint?(common_keys_equal_elt=([],(=)))xy=letcommon_keys,equal_elt=common_keys_equal_eltinunion(funkeyelt_1elt_2->ifnot(List.memkeycommon_keys)thenraise(Invalid_argument(Printf.sprintf"the key %s appears in both union arguments and does not \
belong\n\
\ to common_keys."key))elseifnot(equal_eltelt_1elt_2)thenraise(Invalid_argument(Printf.sprintf"the key %s appears in both union argument with different \
values"key))elseSomeelt_1)xy(* applies union_disjoint on a list of map*)letunion_disjoint_list?(common_keys_equal_elt=([],(=)))map_list=List.fold_left(union_disjoint~common_keys_equal_elt)emptymap_list(* given a list of maps outputs a single map with the union of all keys and
containing lists which consist of the concatenation of the data elements
under the same key (order is preserved) *)letmap_list_to_list_mapmap_list=letjoin_keyxy=Some(x@y)inList.fold_left(funlist_mapm->unionjoinlist_map(map(funx->[x])m))emptymap_listletsub_mapsub_mapmap=letres=filter(funname_->memnamesub_map)mapinifcardinalres<>cardinalsub_mapthenfailwith"sub_map : first argument is not contained in the second.";resmoduleAggregation=struct(* separator between prefixes & name ; must be only one character *)letsep="~"letpadded~ni=letstr=string_of_intiinletlen=String.length(string_of_int(n-1))inString.(make(len-lengthstr)'0')^strletadd_prefix?(n=1)?(i=0)?(shift=0)prefixstr=letout=ifprefix=""thenstrelseprefix^sep^strinifn=1thenoutelsepadded~n(i+shift)^sep^out(* adds prefix to each key of str_map *)letprefix_map?n?i?shiftprefixstr_map=fold(funkvacc->add(add_prefix?n?i?shiftprefixk)vacc)str_mapemptyendendmoduletypeS=sigincludeMap.Swithtypekey=stringandtype'at='aStringMap.tvalt:'aRepr.ty->'atRepr.tyvalof_list:(string*'a)list->'atvalunion_disjoint:?common_keys_equal_elt:stringlist*('a->'a->bool)->'at->'at->'atvalunion_disjoint_list:?common_keys_equal_elt:stringlist*('a->'a->bool)->'atlist->'atvalmap_list_to_list_map:'atlist->'alistt(* [sub_map m1 m2] returns m2 without the keys that do not appear in m1.
Raises failure if some key of m1 is not in m2
*)valsub_map:'at->'bt->'btmoduleAggregation:sigvalsep:stringvaladd_prefix:?n:int->?i:int->?shift:int->string->string->stringvalprefix_map:?n:int->?i:int->?shift:int->string->'at->'atendendinclude(StringMap:S)