12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808(*****************************************************************************)(* *)(* Open Source 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. *)(* *)(*****************************************************************************)(* ---- Constants ----------------------------------------------------------- *)letmax_uint8=Binary_size.max_int`Uint8letmax_uint16=Binary_size.max_int`Uint16letmax_uint8_l=Int32.of_intmax_uint8letmax_uint16_l=Int32.of_intmax_uint16letmax_uint8_L=Int64.of_intmax_uint8letmax_uint16_L=Int64.of_intmax_uint16letmax_uint32=Int32.(to_intmax_int)letmax_uint32_L=0xFFFF_FFFFL(* ---- Tags ---------------------------------------------------------------- *)(* Ultimately compact-tags are translated to encoding-tag of which uint8 and
uint16 are supported. Thus, we can always encode those tags in int. *)typetag=intletjoin_tagstags=lettag_value,tag_len=List.fold_left(fun(res,ofs)(tag_value,tag_len)->(reslor(tag_valuelslofs),ofs+tag_len))(0,0)tagsiniftag_len>16thenraise@@Invalid_argument"join_tags: total tag_len shouldn't be over 16";tag_value(* ---- Encoding helpers ---------------------------------------------------- *)(** [conv_partial f g encoding] is the counterpart of
[conv_with_guard]. It allows to define an encoding which is able
to encode only a subset of the input type.
@raise Write_error on any attempt to encode data in the unsupported
subset of the input type. *)letconv_partialfgencoding=Encoding.conv(funx->matchfxwith|Somex->x|None->raiseBinary_error_types.(Write_errorNo_case_matched))gencoding(* ---- Compact encoding definition ----------------------------------------- *)moduletypeS=sigtypeinputtypelayoutvallayouts:layoutlistvaltag_len:intvaltag:layout->tagvaltitle:layout->stringoptionvalpartial_encoding:layout->inputEncoding.tvalclassify:input->layoutvaljson_encoding:inputEncoding.tendtype'at=(moduleSwithtypeinput='a)lettag_bit_count:typea.at->int=fun(moduleC:Swithtypeinput=a)->C.tag_lenletmake:typea.?tag_size:[`Uint0|`Uint8|`Uint16]->at->aEncoding.t=fun?(tag_size=`Uint0)(moduleC:Swithtypeinput=a)->lettag_len_limit=matchtag_sizewith`Uint0->0|`Uint8->8|`Uint16->16inifC.tag_len>tag_len_limitthenraise@@Invalid_argument"Compact_encoding.make: tags do not fit";lettaglayout=letcandidate=C.taglayoutinifcandidate>=1lslC.tag_lenthenraise@@Invalid_argument"Compact_encoding.make.tag: tags do not fit";candidateinmatchtag_sizewith|`Uint0->((* INVARIANT: when [tag_len = 0] then either:
- it's void and [layouts = []], or
- [layouts] has a single element and [partial_encoding] is total *)matchC.layoutswith|[]->C.json_encoding|[single_layout]->C.partial_encodingsingle_layout|_->raise@@Invalid_argument"Data_encoding.Compact.make: 0-tag encoding has more than one \
layout")|(`Uint8|`Uint16)astag_size->Encoding.raw_splitted~json:(Json.convertC.json_encoding)~binary:(Encoding.matching~tag_size(funx->letlayout=C.classifyxinEncoding.matched~tag_size(C.taglayout)(C.partial_encodinglayout)x)@@List.map(funlayout->lettag=taglayoutinlettitle=matchC.titlelayoutwith|None->Format.sprintf"case_%d"tag|Somes->sin(* Note: the projection function is never used. This is
because [matching] uses the list of cases for decoding
only, not encoding. *)Encoding.case~title(Encoding.Tagtag)(C.partial_encodinglayout)(funx->Somex)(funx->x))C.layouts)letsplitted:typea.json:aEncoding.t->compact:at->at=fun~json~compact:(moduleC:Swithtypeinput=a)->(modulestructincludeCletjson_encoding=jsonend)(* ---- Combinators --------------------------------------------------------- *)moduleList_syntax=structlet(let*)lf=List.concat_mapflletreturnx=[x]endtypevoid=|letrefute=function(_:void)->.letvoid:voidt=(modulestructtypeinput=voidtypelayout=voidlettag_len=0letlayouts=[]lettitle=refuteletclassify=refuteletpartial_encoding=refutelettag=refuteletjson_encoding=Encoding.conv_with_guardrefute(fun_->Error"void has no inhabitant")Encoding.unitend)type('a,'b,'layout)case_open={title:string;description:stringoption;proj:'a->'boption;inj:'b->'a;compact:(moduleSwithtypeinput='bandtypelayout='layout);}type('a,'b,'layout)case_layout_open={tag:int;(* The tag which identifies this specific case out of the others *)title:string;proj:'a->'boption;inj:'b->'a;compact:(moduleSwithtypeinput='bandtypelayout='layout);layout:'layout;}type'acase=Case:('a,'b,'layout)case_open->'acase[@@unboxed]letcase:typeab.title:string->?description:string->bt->(a->boption)->(b->a)->acase=fun~title?descriptioncompactprojinj->let(moduleC:Swithtypeinput=b)=compactinCase{title;description;proj;inj;compact=(moduleC)}type'acase_layout=|Case_layout:('a,'b,'layout)case_layout_open->'acase_layout[@@unboxed]letcase_to_layout_open:typeablayoutc.tag->(a,b,layout)case_open->((a,b,layout)case_layout_open->c)->clist=funtag{proj;inj;compact;title;_}f->let(moduleC:Swithtypeinput=bandtypelayout=layout)=compactinList.map(funlayout->f{tag;proj;inj;compact;layout;title})C.layoutsletcase_to_layout:typea.tag->acase->acase_layoutlist=funtag(Casecase)->case_to_layout_opentagcase(funx->Case_layoutx)letcases_to_layouts:typea.acaselist->acase_layoutlist=funcases->List.mapi(funi->case_to_layouti)cases|>List.concatletclassify_with_case_open:typeablayout.tag->(a,b,layout)case_open->a->(a,b,layout)case_layout_openoption=funtag{compact;proj;inj;title;_}input->let(moduleC:Swithtypeinput=bandtypelayout=layout)=compactinmatchprojinputwith|Someinput'->letlayout=C.classifyinput'inSome{proj;inj;tag;layout;title;compact}|None->Noneletclassify_with_case:typea.tag->acase->a->acase_layoutoption=funtag(Casecase)input->matchclassify_with_case_opentagcaseinputwith|Somelayout->Some(Case_layoutlayout)|None->Noneletclassify_with_cases_exn:typea.(int*acase)list->a->acase_layout=funicasesinput->letrecclassify_aux=function|[]->raise(Invalid_argument"classify_exn")|(tag,case)::rst->(matchclassify_with_casetagcaseinputwith|Somelayout->layout|None->classify_auxrst)inclassify_auxicaseslettag_with_case_layout_open:typeablayout.int->(a,b,layout)case_layout_open->tag=funinner_tag_len{tag;compact;layout;_}->let(moduleC:Swithtypeinput=bandtypelayout=layout)=compactin(taglslinner_tag_len)lorC.taglayoutlettag_with_case_layout:typea.int->acase_layout->tag=funinner_tag_len(Case_layoutcase)->tag_with_case_layout_openinner_tag_lencaselettitle_with_case_layout_open:typeablayout.(a,b,layout)case_layout_open->string=fun{title;_}->titlelettitle_with_case_layout:typea.acase_layout->string=fun(Case_layoutcase)->title_with_case_layout_opencaselettag_len_of_case_open:typeablayout.(a,b,layout)case_open->int=fun{compact;_}->let(moduleC:Swithtypeinput=bandtypelayout=layout)=compactinC.tag_lenlettag_len_of_case:typea.acase->int=fun(Casecase)->tag_len_of_case_opencaseletpartial_encoding_of_case_layout_open:typeablayout.(a,b,layout)case_layout_open->aEncoding.t=fun{proj;inj;compact;layout;_}->let(moduleC:Swithtypeinput=bandtypelayout=layout)=compactin(* TODO: introduce a [def] combinator. Problem: needs an [id]. *)conv_partialprojinj@@C.partial_encodinglayoutletpartial_encoding_of_case_layout:typea.acase_layout->aEncoding.t=fun(Case_layoutlayout)->partial_encoding_of_case_layout_openlayoutletcase_to_json_data_encoding_case_open:typeablayout.(a,b,layout)case_open->aEncoding.case=fun{title;description;proj;inj;compact}->let(moduleC:Swithtypeinput=bandtypelayout=layout)=compactinEncoding.case~title?descriptionEncoding.Json_onlyC.json_encodingprojinjletcase_to_json_data_encoding_case:typea.acase->aEncoding.case=fun(Caselayout)->case_to_json_data_encoding_case_openlayoutletvoid_case:typea.title:string->acase=fun~title->case~title~description:"This case is void. No data is accepted."void(fun_->None)refuteletis_void_case:typea.acase->bool=fun(Case{compact;_})->Obj.reprcompact==Obj.reprvoidletunion_bitstitlemin=function|Somechoicewhenmin<=choice->choice|None->min|Some_->raise(Invalid_argument(Format.sprintf"union: not enough %s bits"title))letunion:typea.?union_tag_bits:int->?cases_tag_bits:int->acaselist->at=fun?union_tag_bits?cases_tag_bitscases->ifcases=[]thenraise@@Invalid_argument"Data_encoding.Compact.union: empty list of cases.";(modulestructtypeinput=a(* [union_tag_len] is the number of bits introduced by [union] to
distinguish between cases, while [inner_tag] is the greatest
number of bits used by the cases themselves. *)letunion_tag_len,cases_tag_len=letmin_union,min_cases=matchcaseswith|[]->assertfalse|case::rst->List.fold_left(fun(bound,size,acc_extra,acc_len)case->letsize=1+sizeinletacc_len=maxacc_len(tag_len_of_casecase)inifbound<sizethen(2*bound,size,acc_extra+1,acc_len)else(bound,size,acc_extra,acc_len))(1,1,0,tag_len_of_casecase)rst|>fun(_,_,extra,len)->(extra,len)in(union_bits"tag"min_unionunion_tag_bits,union_bits"inner"min_casescases_tag_bits)lettag_len=letr=union_tag_len+cases_tag_leninifr>=16thenraise@@Invalid_argument"Compact_encoding.union: tags do not fit";rtypelayout=acase_layoutletlayouts=cases_to_layoutscasesletclassify=letcleaned_cases=letrecauxaccidx=function|[]->List.revacc|case::cases->ifis_void_casecasethenauxacc(idx+1)caseselseaux((idx,case)::acc)(idx+1)casesinaux[]0casesinclassify_with_cases_exncleaned_casesletpartial_encoding=partial_encoding_of_case_layoutlettaglayout=tag_with_case_layoutcases_tag_lenlayoutlettitlelayout=Some(title_with_case_layoutlayout)letjson_encoding:inputEncoding.t=Encoding.union@@List.mapcase_to_json_data_encoding_casecasesend)letpayload:typea.aEncoding.t->at=funencoding:(moduleSwithtypeinput=a)->(modulestructtypeinput=atypelayout=unitletlayouts=[()]lettag_len=0lettag()=0lettitle()=Noneletclassify(_:input)=()letpartial_encoding()=encodingletjson_encoding=encodingend)letunit=payloadEncoding.unitletnull=payloadEncoding.nullletconv:typeab.?json:aEncoding.t->(a->b)->(b->a)->bt->at=fun?jsonfg(moduleB:Swithtypeinput=b)->(modulestructtypeinput=atypelayout=B.layoutletlayouts=B.layoutslettag_len=B.tag_lenlettag=B.taglettitle=B.titleletclassifyb=B.classify(fb)letpartial_encodingl=Encoding.convfg(B.partial_encodingl)letjson_encoding=matchjsonwith|None->Encoding.convfgB.json_encoding|Someencoding->encodingend)letoptioncompact=union~union_tag_bits:1[case~title:"none"null(functionNone->Some()|_->None)(fun()->None);case~title:"some"compact(funx->x)(funx->Somex);]lettup1:typea.at->at=fun(moduleA:Swithtypeinput=a):(moduleSwithtypeinput=a)->(modulestructtypeinput=A.inputtypelayout=A.layoutlettag_len=A.tag_lenletlayouts=A.layoutsletclassifya=A.classifyaletpartial_encodingla=Encoding.tup1(A.partial_encodingla)lettaga=A.tagalettitle=A.titleletjson_encoding=Encoding.tup1A.json_encodingend)lettup2:typeab.at->bt->(a*b)t=fun(moduleA:Swithtypeinput=a)(moduleB:Swithtypeinput=b):(moduleSwithtypeinput=a*b)->(modulestructtypeinput=A.input*B.inputtypelayout=A.layout*B.layoutlettag_len=letr=A.tag_len+B.tag_leninifr>=16thenraise@@Invalid_argument"Compact_encoding.tup2: tags do not fit";rletlayouts=letopenList_syntaxinlet*a=A.layoutsinlet*b=B.layoutsinreturn(a,b)letclassify(a,b)=(A.classifya,B.classifyb)letpartial_encoding(la,lb)=Encoding.tup2(A.partial_encodingla)(B.partial_encodinglb)lettag(a,b)=join_tags[(A.taga,A.tag_len);(B.tagb,B.tag_len)]lettitle_=Noneletjson_encoding=Encoding.tup2A.json_encodingB.json_encodingend)lettup3:typeabc.at->bt->ct->(a*b*c)t=fun(moduleA:Swithtypeinput=a)(moduleB:Swithtypeinput=b)(moduleC:Swithtypeinput=c):(moduleSwithtypeinput=a*b*c)->(modulestructtypeinput=A.input*B.input*C.inputtypelayout=A.layout*B.layout*C.layoutlettag_len=letr=A.tag_len+B.tag_len+C.tag_leninifr>=16thenraise@@Invalid_argument"Compact_encoding.tup3: tags do not fit";rletlayouts=letopenList_syntaxinlet*a=A.layoutsinlet*b=B.layoutsinlet*c=C.layoutsinreturn(a,b,c)letclassify(a,b,c)=(A.classifya,B.classifyb,C.classifyc)letpartial_encoding(la,lb,lc)=Encoding.tup3(A.partial_encodingla)(B.partial_encodinglb)(C.partial_encodinglc)lettag(a,b,c)=join_tags[(A.taga,A.tag_len);(B.tagb,B.tag_len);(C.tagc,C.tag_len)]lettitle_=Noneletjson_encoding=Encoding.tup3A.json_encodingB.json_encodingC.json_encodingend)lettup4:typeabcd.at->bt->ct->dt->(a*b*c*d)t=fun(moduleA:Swithtypeinput=a)(moduleB:Swithtypeinput=b)(moduleC:Swithtypeinput=c)(moduleD:Swithtypeinput=d):(moduleSwithtypeinput=a*b*c*d)->(modulestructtypeinput=A.input*B.input*C.input*D.inputtypelayout=A.layout*B.layout*C.layout*D.layoutlettag_len=letr=A.tag_len+B.tag_len+C.tag_len+D.tag_leninifr>=16thenraise@@Invalid_argument"Compact_encoding.tup4: tags do not fit";rletlayouts=letopenList_syntaxinlet*a=A.layoutsinlet*b=B.layoutsinlet*c=C.layoutsinlet*d=D.layoutsinreturn(a,b,c,d)letclassify(a,b,c,d)=(A.classifya,B.classifyb,C.classifyc,D.classifyd)letpartial_encoding(la,lb,lc,ld)=Encoding.tup4(A.partial_encodingla)(B.partial_encodinglb)(C.partial_encodinglc)(D.partial_encodingld)lettag(a,b,c,d)=join_tags[(A.taga,A.tag_len);(B.tagb,B.tag_len);(C.tagc,C.tag_len);(D.tagd,D.tag_len);]lettitle_=Noneletjson_encoding=Encoding.tup4A.json_encodingB.json_encodingC.json_encodingD.json_encodingend)lettup5:typeabcde.at->bt->ct->dt->et->(a*b*c*d*e)t=fun(moduleA:Swithtypeinput=a)(moduleB:Swithtypeinput=b)(moduleC:Swithtypeinput=c)(moduleD:Swithtypeinput=d)(moduleE:Swithtypeinput=e):(moduleSwithtypeinput=a*b*c*d*e)->(modulestructtypeinput=A.input*B.input*C.input*D.input*E.inputtypelayout=A.layout*B.layout*C.layout*D.layout*E.layoutlettag_len=letr=A.tag_len+B.tag_len+C.tag_len+D.tag_len+E.tag_leninifr>=16thenraise@@Invalid_argument"Compact_encoding.tup5: tags do not fit";rletlayouts=letopenList_syntaxinlet*a=A.layoutsinlet*b=B.layoutsinlet*c=C.layoutsinlet*d=D.layoutsinlet*e=E.layoutsinreturn(a,b,c,d,e)letclassify(a,b,c,d,e)=(A.classifya,B.classifyb,C.classifyc,D.classifyd,E.classifye)letpartial_encoding(la,lb,lc,ld,le)=Encoding.tup5(A.partial_encodingla)(B.partial_encodinglb)(C.partial_encodinglc)(D.partial_encodingld)(E.partial_encodingle)lettag(a,b,c,d,e)=join_tags[(A.taga,A.tag_len);(B.tagb,B.tag_len);(C.tagc,C.tag_len);(D.tagd,D.tag_len);(E.tage,E.tag_len);]lettitle_=Noneletjson_encoding=Encoding.tup5A.json_encodingB.json_encodingC.json_encodingD.json_encodingE.json_encodingend)lettup6:typeabcdef.at->bt->ct->dt->et->ft->(a*b*c*d*e*f)t=fun(moduleA:Swithtypeinput=a)(moduleB:Swithtypeinput=b)(moduleC:Swithtypeinput=c)(moduleD:Swithtypeinput=d)(moduleE:Swithtypeinput=e)(moduleF:Swithtypeinput=f):(moduleSwithtypeinput=a*b*c*d*e*f)->(modulestructtypeinput=A.input*B.input*C.input*D.input*E.input*F.inputtypelayout=A.layout*B.layout*C.layout*D.layout*E.layout*F.layoutlettag_len=letr=A.tag_len+B.tag_len+C.tag_len+D.tag_len+E.tag_len+F.tag_leninifr>=16thenraise@@Invalid_argument"Compact_encoding.tup6: tags do not fit";rletlayouts=letopenList_syntaxinlet*a=A.layoutsinlet*b=B.layoutsinlet*c=C.layoutsinlet*d=D.layoutsinlet*e=E.layoutsinlet*f=F.layoutsinreturn(a,b,c,d,e,f)letclassify(a,b,c,d,e,f)=(A.classifya,B.classifyb,C.classifyc,D.classifyd,E.classifye,F.classifyf)letpartial_encoding(la,lb,lc,ld,le,lf)=Encoding.tup6(A.partial_encodingla)(B.partial_encodinglb)(C.partial_encodinglc)(D.partial_encodingld)(E.partial_encodingle)(F.partial_encodinglf)lettag(a,b,c,d,e,f)=join_tags[(A.taga,A.tag_len);(B.tagb,B.tag_len);(C.tagc,C.tag_len);(D.tagd,D.tag_len);(E.tage,E.tag_len);(F.tagf,F.tag_len);]lettitle_=Noneletjson_encoding=Encoding.tup6A.json_encodingB.json_encodingC.json_encodingD.json_encodingE.json_encodingF.json_encodingend)lettup7:typeabcdefg.at->bt->ct->dt->et->ft->gt->(a*b*c*d*e*f*g)t=fun(moduleA:Swithtypeinput=a)(moduleB:Swithtypeinput=b)(moduleC:Swithtypeinput=c)(moduleD:Swithtypeinput=d)(moduleE:Swithtypeinput=e)(moduleF:Swithtypeinput=f)(moduleG:Swithtypeinput=g):(moduleSwithtypeinput=a*b*c*d*e*f*g)->(modulestructtypeinput=A.input*B.input*C.input*D.input*E.input*F.input*G.inputtypelayout=A.layout*B.layout*C.layout*D.layout*E.layout*F.layout*G.layoutlettag_len=letr=A.tag_len+B.tag_len+C.tag_len+D.tag_len+E.tag_len+F.tag_len+G.tag_leninifr>=16thenraise@@Invalid_argument"Compact_encoding.tup7: tags do not fit";rletlayouts=letopenList_syntaxinlet*a=A.layoutsinlet*b=B.layoutsinlet*c=C.layoutsinlet*d=D.layoutsinlet*e=E.layoutsinlet*f=F.layoutsinlet*g=G.layoutsinreturn(a,b,c,d,e,f,g)letclassify(a,b,c,d,e,f,g)=(A.classifya,B.classifyb,C.classifyc,D.classifyd,E.classifye,F.classifyf,G.classifyg)letpartial_encoding(la,lb,lc,ld,le,lf,lg)=Encoding.tup7(A.partial_encodingla)(B.partial_encodinglb)(C.partial_encodinglc)(D.partial_encodingld)(E.partial_encodingle)(F.partial_encodinglf)(G.partial_encodinglg)lettag(a,b,c,d,e,f,g)=join_tags[(A.taga,A.tag_len);(B.tagb,B.tag_len);(C.tagc,C.tag_len);(D.tagd,D.tag_len);(E.tage,E.tag_len);(F.tagf,F.tag_len);(G.tagg,G.tag_len);]lettitle_=Noneletjson_encoding=Encoding.tup7A.json_encodingB.json_encodingC.json_encodingD.json_encodingE.json_encodingF.json_encodingG.json_encodingend)lettup8:typeabcdefgh.at->bt->ct->dt->et->ft->gt->ht->(a*b*c*d*e*f*g*h)t=fun(moduleA:Swithtypeinput=a)(moduleB:Swithtypeinput=b)(moduleC:Swithtypeinput=c)(moduleD:Swithtypeinput=d)(moduleE:Swithtypeinput=e)(moduleF:Swithtypeinput=f)(moduleG:Swithtypeinput=g)(moduleH:Swithtypeinput=h):(moduleSwithtypeinput=a*b*c*d*e*f*g*h)->(modulestructtypeinput=A.input*B.input*C.input*D.input*E.input*F.input*G.input*H.inputtypelayout=A.layout*B.layout*C.layout*D.layout*E.layout*F.layout*G.layout*H.layoutlettag_len=letr=A.tag_len+B.tag_len+C.tag_len+D.tag_len+E.tag_len+F.tag_len+G.tag_len+H.tag_leninifr>=16thenraise@@Invalid_argument"Compact_encoding.tup8: tags do not fit";rletlayouts=letopenList_syntaxinlet*a=A.layoutsinlet*b=B.layoutsinlet*c=C.layoutsinlet*d=D.layoutsinlet*e=E.layoutsinlet*f=F.layoutsinlet*g=G.layoutsinlet*h=H.layoutsinreturn(a,b,c,d,e,f,g,h)letclassify(a,b,c,d,e,f,g,h)=(A.classifya,B.classifyb,C.classifyc,D.classifyd,E.classifye,F.classifyf,G.classifyg,H.classifyh)letpartial_encoding(la,lb,lc,ld,le,lf,lg,lh)=Encoding.tup8(A.partial_encodingla)(B.partial_encodinglb)(C.partial_encodinglc)(D.partial_encodingld)(E.partial_encodingle)(F.partial_encodinglf)(G.partial_encodinglg)(H.partial_encodinglh)lettag(a,b,c,d,e,f,g,h)=join_tags[(A.taga,A.tag_len);(B.tagb,B.tag_len);(C.tagc,C.tag_len);(D.tagd,D.tag_len);(E.tage,E.tag_len);(F.tagf,F.tag_len);(G.tagg,G.tag_len);(H.tagh,H.tag_len);]lettitle_=Noneletjson_encoding=Encoding.tup8A.json_encodingB.json_encodingC.json_encodingD.json_encodingE.json_encodingF.json_encodingG.json_encodingH.json_encodingend)lettup9:typeabcdefghi.at->bt->ct->dt->et->ft->gt->ht->it->(a*b*c*d*e*f*g*h*i)t=fun(moduleA:Swithtypeinput=a)(moduleB:Swithtypeinput=b)(moduleC:Swithtypeinput=c)(moduleD:Swithtypeinput=d)(moduleE:Swithtypeinput=e)(moduleF:Swithtypeinput=f)(moduleG:Swithtypeinput=g)(moduleH:Swithtypeinput=h)(moduleI:Swithtypeinput=i):(moduleSwithtypeinput=a*b*c*d*e*f*g*h*i)->(modulestructtypeinput=A.input*B.input*C.input*D.input*E.input*F.input*G.input*H.input*I.inputtypelayout=A.layout*B.layout*C.layout*D.layout*E.layout*F.layout*G.layout*H.layout*I.layoutlettag_len=letr=A.tag_len+B.tag_len+C.tag_len+D.tag_len+E.tag_len+F.tag_len+G.tag_len+H.tag_len+I.tag_leninifr>=16thenraise@@Invalid_argument"Compact_encoding.tup9: tags do not fit";rletlayouts=letopenList_syntaxinlet*a=A.layoutsinlet*b=B.layoutsinlet*c=C.layoutsinlet*d=D.layoutsinlet*e=E.layoutsinlet*f=F.layoutsinlet*g=G.layoutsinlet*h=H.layoutsinlet*i=I.layoutsinreturn(a,b,c,d,e,f,g,h,i)letclassify(a,b,c,d,e,f,g,h,i)=(A.classifya,B.classifyb,C.classifyc,D.classifyd,E.classifye,F.classifyf,G.classifyg,H.classifyh,I.classifyi)letpartial_encoding(la,lb,lc,ld,le,lf,lg,lh,li)=Encoding.tup9(A.partial_encodingla)(B.partial_encodinglb)(C.partial_encodinglc)(D.partial_encodingld)(E.partial_encodingle)(F.partial_encodinglf)(G.partial_encodinglg)(H.partial_encodinglh)(I.partial_encodingli)lettag(a,b,c,d,e,f,g,h,i)=join_tags[(A.taga,A.tag_len);(B.tagb,B.tag_len);(C.tagc,C.tag_len);(D.tagd,D.tag_len);(E.tage,E.tag_len);(F.tagf,F.tag_len);(G.tagg,G.tag_len);(H.tagh,H.tag_len);(I.tagi,I.tag_len);]lettitle_=Noneletjson_encoding=Encoding.tup9A.json_encodingB.json_encodingC.json_encodingD.json_encodingE.json_encodingF.json_encodingG.json_encodingH.json_encodingI.json_encodingend)lettup10:typeabcdefghij.at->bt->ct->dt->et->ft->gt->ht->it->jt->(a*b*c*d*e*f*g*h*i*j)t=fun(moduleA:Swithtypeinput=a)(moduleB:Swithtypeinput=b)(moduleC:Swithtypeinput=c)(moduleD:Swithtypeinput=d)(moduleE:Swithtypeinput=e)(moduleF:Swithtypeinput=f)(moduleG:Swithtypeinput=g)(moduleH:Swithtypeinput=h)(moduleI:Swithtypeinput=i)(moduleJ:Swithtypeinput=j):(moduleSwithtypeinput=a*b*c*d*e*f*g*h*i*j)->(modulestructtypeinput=A.input*B.input*C.input*D.input*E.input*F.input*G.input*H.input*I.input*J.inputtypelayout=A.layout*B.layout*C.layout*D.layout*E.layout*F.layout*G.layout*H.layout*I.layout*J.layoutlettag_len=letr=A.tag_len+B.tag_len+C.tag_len+D.tag_len+E.tag_len+F.tag_len+G.tag_len+H.tag_len+I.tag_len+J.tag_leninifr>=16thenraise@@Invalid_argument"Compact_encoding.tup10: tags do not fit";rletlayouts=letopenList_syntaxinlet*a=A.layoutsinlet*b=B.layoutsinlet*c=C.layoutsinlet*d=D.layoutsinlet*e=E.layoutsinlet*f=F.layoutsinlet*g=G.layoutsinlet*h=H.layoutsinlet*i=I.layoutsinlet*j=J.layoutsinreturn(a,b,c,d,e,f,g,h,i,j)letclassify(a,b,c,d,e,f,g,h,i,j)=(A.classifya,B.classifyb,C.classifyc,D.classifyd,E.classifye,F.classifyf,G.classifyg,H.classifyh,I.classifyi,J.classifyj)letpartial_encoding(la,lb,lc,ld,le,lf,lg,lh,li,lj)=Encoding.tup10(A.partial_encodingla)(B.partial_encodinglb)(C.partial_encodinglc)(D.partial_encodingld)(E.partial_encodingle)(F.partial_encodinglf)(G.partial_encodinglg)(H.partial_encodinglh)(I.partial_encodingli)(J.partial_encodinglj)lettag(a,b,c,d,e,f,g,h,i,j)=join_tags[(A.taga,A.tag_len);(B.tagb,B.tag_len);(C.tagc,C.tag_len);(D.tagd,D.tag_len);(E.tage,E.tag_len);(F.tagf,F.tag_len);(G.tagg,G.tag_len);(H.tagh,H.tag_len);(I.tagi,I.tag_len);(J.tagj,J.tag_len);]lettitle_=Noneletjson_encoding=Encoding.tup10A.json_encodingB.json_encodingC.json_encodingD.json_encodingE.json_encodingF.json_encodingG.json_encodingH.json_encodingI.json_encodingJ.json_encodingend)type'afield_contents={name:string;compact:'at}type('a,'b)field_open=|Req:'afield_contents->('a,'a)field_open|Opt:'afield_contents->('a,'aoption)field_openletfield_to_compact_open:typeab.(a,b)field_open->at=function|Reqf1->f1.compact|Optf1->f1.compactletfield_to_inner_compact:typeab.(a,b)field_open->bt=function|Reqf1->f1.compact|Optf1->optionf1.compacttype'afield=Field:('b,'a)field_open->'afield[@@unboxed]letfield_to_data_encoding_open:typeab.(a,b)field_open->bEncoding.field=function|Req{name;compact}->let(moduleA)=compactinEncoding.reqnameA.json_encoding|Opt{name;compact}->let(moduleA)=compactinEncoding.optnameA.json_encodingletreq:string->'at->'afield=funnamecompact->Field(Req{name;compact})letopt:string->'at->'aoptionfield=funnamecompact->Field(Opt{name;compact})letobj1_open:typeab.(a,b)field_open->(moduleSwithtypeinput=b)=funf1->let(moduleC)=field_to_compact_openf1inlet(moduleC_in)=field_to_inner_compactf1in(modulestructincludeC_inletjson_encoding=Encoding.obj1@@field_to_data_encoding_openf1end)letobj1(Fieldf1)=obj1_openf1letobj2_open:typeabcd.(a,b)field_open->(c,d)field_open->(moduleSwithtypeinput=b*d)=funf1f2->let(moduleTup)=tup2(field_to_inner_compactf1)(field_to_inner_compactf2)in(modulestructincludeTupletjson_encoding=Encoding.obj2(field_to_data_encoding_openf1)(field_to_data_encoding_openf2)end)letobj2(Fieldf1)(Fieldf2)=obj2_openf1f2letobj3_open:typeabcdef.(a,b)field_open->(c,d)field_open->(e,f)field_open->(moduleSwithtypeinput=b*d*f)=funf1f2f3->let(moduleTup)=tup3(field_to_inner_compactf1)(field_to_inner_compactf2)(field_to_inner_compactf3)in(modulestructincludeTupletjson_encoding=Encoding.obj3(field_to_data_encoding_openf1)(field_to_data_encoding_openf2)(field_to_data_encoding_openf3)end)letobj3(Fieldf1)(Fieldf2)(Fieldf3)=obj3_openf1f2f3letobj4_open:typeabcdefgh.(a,b)field_open->(c,d)field_open->(e,f)field_open->(g,h)field_open->(moduleSwithtypeinput=b*d*f*h)=funf1f2f3f4->let(moduleTup)=tup4(field_to_inner_compactf1)(field_to_inner_compactf2)(field_to_inner_compactf3)(field_to_inner_compactf4)in(modulestructincludeTupletjson_encoding=Encoding.obj4(field_to_data_encoding_openf1)(field_to_data_encoding_openf2)(field_to_data_encoding_openf3)(field_to_data_encoding_openf4)end)letobj4(Fieldf1)(Fieldf2)(Fieldf3)(Fieldf4)=obj4_openf1f2f3f4letobj5_open:typet1at1bt2at2bt3at3bt4at4bt5at5b.(t1a,t1b)field_open->(t2a,t2b)field_open->(t3a,t3b)field_open->(t4a,t4b)field_open->(t5a,t5b)field_open->(moduleSwithtypeinput=t1b*t2b*t3b*t4b*t5b)=funf1f2f3f4f5->let(moduleTup)=tup5(field_to_inner_compactf1)(field_to_inner_compactf2)(field_to_inner_compactf3)(field_to_inner_compactf4)(field_to_inner_compactf5)in(modulestructincludeTupletjson_encoding=Encoding.obj5(field_to_data_encoding_openf1)(field_to_data_encoding_openf2)(field_to_data_encoding_openf3)(field_to_data_encoding_openf4)(field_to_data_encoding_openf5)end)letobj5(Fieldf1)(Fieldf2)(Fieldf3)(Fieldf4)(Fieldf5)=obj5_openf1f2f3f4f5letobj6_open:typet1at1bt2at2bt3at3bt4at4bt5at5bt6at6b.(t1a,t1b)field_open->(t2a,t2b)field_open->(t3a,t3b)field_open->(t4a,t4b)field_open->(t5a,t5b)field_open->(t6a,t6b)field_open->(moduleSwithtypeinput=t1b*t2b*t3b*t4b*t5b*t6b)=funf1f2f3f4f5f6->let(moduleTup)=tup6(field_to_inner_compactf1)(field_to_inner_compactf2)(field_to_inner_compactf3)(field_to_inner_compactf4)(field_to_inner_compactf5)(field_to_inner_compactf6)in(modulestructincludeTupletjson_encoding=Encoding.obj6(field_to_data_encoding_openf1)(field_to_data_encoding_openf2)(field_to_data_encoding_openf3)(field_to_data_encoding_openf4)(field_to_data_encoding_openf5)(field_to_data_encoding_openf6)end)letobj6(Fieldf1)(Fieldf2)(Fieldf3)(Fieldf4)(Fieldf5)(Fieldf6)=obj6_openf1f2f3f4f5f6letobj7_open:typet1at1bt2at2bt3at3bt4at4bt5at5bt6at6bt7at7b.(t1a,t1b)field_open->(t2a,t2b)field_open->(t3a,t3b)field_open->(t4a,t4b)field_open->(t5a,t5b)field_open->(t6a,t6b)field_open->(t7a,t7b)field_open->(moduleSwithtypeinput=t1b*t2b*t3b*t4b*t5b*t6b*t7b)=funf1f2f3f4f5f6f7->let(moduleTup)=tup7(field_to_inner_compactf1)(field_to_inner_compactf2)(field_to_inner_compactf3)(field_to_inner_compactf4)(field_to_inner_compactf5)(field_to_inner_compactf6)(field_to_inner_compactf7)in(modulestructincludeTupletjson_encoding=Encoding.obj7(field_to_data_encoding_openf1)(field_to_data_encoding_openf2)(field_to_data_encoding_openf3)(field_to_data_encoding_openf4)(field_to_data_encoding_openf5)(field_to_data_encoding_openf6)(field_to_data_encoding_openf7)end)letobj7(Fieldf1)(Fieldf2)(Fieldf3)(Fieldf4)(Fieldf5)(Fieldf6)(Fieldf7)=obj7_openf1f2f3f4f5f6f7letobj8_open:typet1at1bt2at2bt3at3bt4at4bt5at5bt6at6bt7at7bt8at8b.(t1a,t1b)field_open->(t2a,t2b)field_open->(t3a,t3b)field_open->(t4a,t4b)field_open->(t5a,t5b)field_open->(t6a,t6b)field_open->(t7a,t7b)field_open->(t8a,t8b)field_open->(moduleSwithtypeinput=t1b*t2b*t3b*t4b*t5b*t6b*t7b*t8b)=funf1f2f3f4f5f6f7f8->let(moduleTup)=tup8(field_to_inner_compactf1)(field_to_inner_compactf2)(field_to_inner_compactf3)(field_to_inner_compactf4)(field_to_inner_compactf5)(field_to_inner_compactf6)(field_to_inner_compactf7)(field_to_inner_compactf8)in(modulestructincludeTupletjson_encoding=Encoding.obj8(field_to_data_encoding_openf1)(field_to_data_encoding_openf2)(field_to_data_encoding_openf3)(field_to_data_encoding_openf4)(field_to_data_encoding_openf5)(field_to_data_encoding_openf6)(field_to_data_encoding_openf7)(field_to_data_encoding_openf8)end)letobj8(Fieldf1)(Fieldf2)(Fieldf3)(Fieldf4)(Fieldf5)(Fieldf6)(Fieldf7)(Fieldf8)=obj8_openf1f2f3f4f5f6f7f8letobj9_open:typet1at1bt2at2bt3at3bt4at4bt5at5bt6at6bt7at7bt8at8bt9at9b.(t1a,t1b)field_open->(t2a,t2b)field_open->(t3a,t3b)field_open->(t4a,t4b)field_open->(t5a,t5b)field_open->(t6a,t6b)field_open->(t7a,t7b)field_open->(t8a,t8b)field_open->(t9a,t9b)field_open->(moduleSwithtypeinput=t1b*t2b*t3b*t4b*t5b*t6b*t7b*t8b*t9b)=funf1f2f3f4f5f6f7f8f9->let(moduleTup)=tup9(field_to_inner_compactf1)(field_to_inner_compactf2)(field_to_inner_compactf3)(field_to_inner_compactf4)(field_to_inner_compactf5)(field_to_inner_compactf6)(field_to_inner_compactf7)(field_to_inner_compactf8)(field_to_inner_compactf9)in(modulestructincludeTupletjson_encoding=Encoding.obj9(field_to_data_encoding_openf1)(field_to_data_encoding_openf2)(field_to_data_encoding_openf3)(field_to_data_encoding_openf4)(field_to_data_encoding_openf5)(field_to_data_encoding_openf6)(field_to_data_encoding_openf7)(field_to_data_encoding_openf8)(field_to_data_encoding_openf9)end)letobj9(Fieldf1)(Fieldf2)(Fieldf3)(Fieldf4)(Fieldf5)(Fieldf6)(Fieldf7)(Fieldf8)(Fieldf9)=obj9_openf1f2f3f4f5f6f7f8f9letobj10_open:typet1at1bt2at2bt3at3bt4at4bt5at5bt6at6bt7at7bt8at8bt9at9bt10at10b.(t1a,t1b)field_open->(t2a,t2b)field_open->(t3a,t3b)field_open->(t4a,t4b)field_open->(t5a,t5b)field_open->(t6a,t6b)field_open->(t7a,t7b)field_open->(t8a,t8b)field_open->(t9a,t9b)field_open->(t10a,t10b)field_open->(moduleSwithtypeinput=t1b*t2b*t3b*t4b*t5b*t6b*t7b*t8b*t9b*t10b)=funf1f2f3f4f5f6f7f8f9f10->let(moduleTup)=tup10(field_to_inner_compactf1)(field_to_inner_compactf2)(field_to_inner_compactf3)(field_to_inner_compactf4)(field_to_inner_compactf5)(field_to_inner_compactf6)(field_to_inner_compactf7)(field_to_inner_compactf8)(field_to_inner_compactf9)(field_to_inner_compactf10)in(modulestructincludeTupletjson_encoding=Encoding.obj10(field_to_data_encoding_openf1)(field_to_data_encoding_openf2)(field_to_data_encoding_openf3)(field_to_data_encoding_openf4)(field_to_data_encoding_openf5)(field_to_data_encoding_openf6)(field_to_data_encoding_openf7)(field_to_data_encoding_openf8)(field_to_data_encoding_openf9)(field_to_data_encoding_openf10)end)letobj10(Fieldf1)(Fieldf2)(Fieldf3)(Fieldf4)(Fieldf5)(Fieldf6)(Fieldf7)(Fieldf8)(Fieldf9)(Fieldf10)=obj10_openf1f2f3f4f5f6f7f8f9f10moduleCompact_bool=structtypeinput=booltypelayout=boolletlayouts=[true;false]lettag_len=1lettag=functiontrue->1|false->0lettitle_=Noneletpartial_encoding:layout->boolEncoding.t=funb->conv_partial(functionb'whenBool.equalbb'->Some()|_->None)(fun()->b)Encoding.unitletclassifyx=xletjson_encoding=Encoding.boolendletbool:boolt=(moduleCompact_bool)letint32_cases=[case~title:"small"~description:"An int32 which fits within a uint8"(payloadEncoding.uint8)(funi->if0l<=i&&i<=max_uint8_lthenSome(Int32.to_inti)elseNone)(funi->Int32.of_inti);case~title:"medium"~description:"An int32 which fits within a uint16"(payloadEncoding.uint16)(funi->ifmax_uint8_l<i&&i<=max_uint16_lthenSome(Int32.to_inti)elseNone)(funi->ifi<=max_uint8thenraise(Binary_error_types.Read_error(Invalid_int{min=max_uint8+1;v=i;max=max_uint16}));letr=Int32.of_intiinr);case~title:"big"~description:"An int32 which doesn't fit within a uint16"(payloadEncoding.int32)(funi->ifmax_uint16_l<i||i<0lthenSomeielseNone)(funi->if0l<=i&&i<=max_uint16_lthenraise(Binary_error_types.Read_error(Invalid_int{min=max_uint16+1;v=Int32.to_inti;max=0}));i);]letint32=splitted~json:Encoding.int32~compact:(union~union_tag_bits:2~cases_tag_bits:0int32_cases)letint64=splitted~json:Encoding.int64~compact:(union~union_tag_bits:2~cases_tag_bits:0[case~title:"small"~description:"An int64 which fits within a uint8"(payloadEncoding.uint8)(funi->if0L<=i&&i<=max_uint8_LthenSome(Int64.to_inti)elseNone)(funi->Int64.of_inti);case~title:"medium"~description:"An int64 which fits within a uint16"(payloadEncoding.uint16)(funi->ifmax_uint8_L<i&&i<=max_uint16_LthenSome(Int64.to_inti)elseNone)(funi->ifi<=max_uint8thenraise(Binary_error_types.Read_error(Invalid_int{min=max_uint8+1;v=i;max=max_uint16}));Int64.of_inti);case~title:"biggish"~description:"An int64 which fits within a uint32"(payloadEncoding.int32)(funi->ifmax_uint16_L<i&&i<=max_uint32_LthenSome(Int64.to_int32i)elseNone)(funx->letr=Int64.(logand0xFFFF_FFFFL(of_int32x))inifr<=max_uint16_Lthenraise(Binary_error_types.Read_error(Invalid_int{min=max_uint16+1;v=Int32.to_intx;max=max_uint32;}));r);case~title:"bigger"~description:"An int64 which doesn't fit within a uint32"(payloadEncoding.int64)(funi->ifmax_uint32_L<i||i<0LthenSomeielseNone)(funi->if0L<=i&&i<=max_uint32_Lthenraise(Binary_error_types.Read_error(Invalid_int{min=max_uint32+1;v=Int64.to_inti;max=0}));i);])moduleCompact_list=structtypelayout=Small_listofint|Big_listletlayoutsbits=letbits=pred(1lslbits)inletrecauxmacc=ifm<bitsthenaux(succm)(Small_listm::acc)elseaccinList.rev@@(Big_list::aux0[])(** ---- Tag -------------------------------------------------------------- *)lettagbits=functionSmall_listm->m|Big_list->pred(1lslbits)(** ---- Partial encoding ------------------------------------------------- *)letspecialised_listbitsencoding=matchbitswith|0->conv_partial(function[]->Some()|_->None)(fun()->[])Encoding.unit|n->Encoding.Fixed.listnencodingletpartial_encoding:'aEncoding.t->layout->'alistEncoding.t=funencoding->function|Small_listbits->specialised_listbitsencoding|Big_list->Encoding.listencodingletjson_encoding=Encoding.list(** ---- Classifier ------------------------------------------------------- *)letclassifybitsl=letm=pred(1lslbits)inletrecauxbitsl=ifbits<mthenmatchlwith[]->Small_listbits|_::rst->aux(bits+1)rstelseBig_listinaux0lendletlist:typea.bits:int->aEncoding.t->alistt=fun~bitsencoding->ifbits<0thenraise(Invalid_argument"Data_encoding.Compact.list: negative bit-length");(modulestructtypeinput=alistincludeCompact_listletlayouts=layoutsbitslettag_len=bitslettag=tagbitslettitle_=Noneletclassify=classifybitsletpartial_encoding=partial_encodingencodingletjson_encoding=json_encodingencodingend)letor_int32:typea.int32_title:string->alt_title:string->?alt_description:string->aEncoding.t->(int32,a)Either.tt=fun~int32_title~alt_title?alt_descriptionalt_encoding->letleft_cases=List.map(fun(Case{title;description;proj;inj;compact})->lettitle=Printf.sprintf"%s_%s"int32_titletitleinletproj=function|Either.Lefti32->proji32|Either.Right_->Noneinletinji=Either.Left(inji)inCase{title;description;proj;inj;compact})int32_casesinletright_case=case~title:alt_title?description:alt_description(payloadalt_encoding)(functionEither.Righta->Somea|Either.Left_->None)(funa->Either.Righta)inunion~union_tag_bits:2~cases_tag_bits:0(left_cases@[right_case])moduleCustom=structmoduletypeS=Stypetag=intletjoin_tags=join_tagsletmakex=xend