123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892moduleB=Decompress_bmoduleQ=Decompress_qmoduleSafe=Decompress_safemoduleSeq=Decompress_seqmoduleHunk=Decompress_lz77.HunkmoduleL=Decompress_lz77letpf=Format.fprintfletinvalid_argfmt=Format.ksprintf(funs->invalid_args)fmt(** (imperative) Heap implementation *)moduleHeap=structtypet={mutablebuffer:intarray;mutablelength:int}letmakesize={buffer=Array.make(size*2)0;length=0}letget_parenti=(i-2)/4*2letget_childi=(2*i)+2exceptionBreakletpushindexvalue({buffer;length}asheap)=letswapij=lett=buffer.(i)inbuffer.(i)<-buffer.(j);buffer.(j)<-tinbuffer.(length)<-value;buffer.(length+1)<-index;letcurrent=reflengthin(trywhile!current>0doletparent=get_parent!currentinifbuffer.(!current)>buffer.(parent)then(swap!currentparent;swap(!current+1)(parent+1);current:=parent)elseraiseBreakdonewithBreak->());heap.length<-length+2letpop({buffer;length}asheap)=letswapij=lett=buffer.(i)inbuffer.(i)<-buffer.(j);buffer.(j)<-tinletvalue=buffer.(0)inletindex=buffer.(1)inheap.length<-length-2;buffer.(0)<-buffer.(heap.length);buffer.(1)<-buffer.(heap.length+1);letparent=ref0in(trywhiletruedoletcurrent=get_child!parentinifcurrent>=heap.lengththenraiseBreak;letcurrent=ifcurrent+2<heap.length&&buffer.(current+2)>buffer.(current)thencurrent+2elsecurrentinifbuffer.(current)>buffer.(!parent)then(swapcurrent!parent;swap(current+1)(!parent+1))elseraiseBreak;parent:=currentdonewithBreak->());(index,value)letlength{length;_}=lengthend(* Convenience function to create a canonic Huffman tree *)moduleT=struct(** Compute the optimal bit lengths for a tree.
[p] must be sorted by increasing frequency. *)letreverse_package_mergepnlimit=letminimum_cost=Array.makelimit0inletflag=Array.makelimit0inletcode_length=Array.makenlimitinletcurrent_position=Array.makelimit0inletexcess=ref((1lsllimit)-n)inlethalf=1lsl(limit-1)inminimum_cost.(limit-1)<-n;forj=0tolimit-1doif!excess<halfthenflag.(j)<-0else(flag.(j)<-1;excess:=!excess-half);excess:=!excesslsl1;iflimit-2-j>=0thenminimum_cost.(limit-2-j)<-(minimum_cost.(limit-1-j)/2)+ndone;minimum_cost.(0)<-flag.(0);letvalue=Array.initlimit(function|0->Array.makeminimum_cost.(0)0|j->ifminimum_cost.(j)>(2*minimum_cost.(j-1))+flag.(j)thenminimum_cost.(j)<-(2*minimum_cost.(j-1))+flag.(j);Array.makeminimum_cost.(j)0)inletty=Array.initlimit(funj->Array.makeminimum_cost.(j)0)in(* Decrease codeword lengths indicated by the first element in [ty.(j)],
recursively accessing other lists if that first element is a package. *)letrectake_packagej=letx=ty.(j).(current_position.(j))inifx=nthen(take_package(j+1);take_package(j+1))elsecode_length.(x)<-code_length.(x)-1;(* remove and discard the first elements of queues [value.(j)] and
[ty.(j)]. *)current_position.(j)<-current_position.(j)+1infort=0tominimum_cost.(limit-1)-1dovalue.(limit-1).(t)<-p.(t);ty.(limit-1).(t)<-tdone;ifflag.(limit-1)=1then(code_length.(0)<-code_length.(0)-1;current_position.(limit-1)<-current_position.(limit-1)+1);forj=limit-2downto0doleti=ref0inletnext=refcurrent_position.(j+1)infort=0tominimum_cost.(j)-1doletweight=if!next+1<minimum_cost.(j+1)thenvalue.(j+1).(!next)+value.(j+1).(!next+1)elsep.(!i)inifweight>p.(!i)then(value.(j).(t)<-weight;ty.(j).(t)<-n;next:=!next+2)else(value.(j).(t)<-p.(!i);ty.(j).(t)<-!i;incri)done;current_position.(j)<-0;ifflag.(j)=1thentake_packagejdone;code_lengthexceptionOKletget_lengthsfreqslimit=letlength=Array.make(Array.lengthfreqs)0in(letheap=Heap.make(2*286)inletmax_code=ref(-1)in(* Construct the initial heap, with the least frequent element in
heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
heap[0] is not used. See implementation in Heap module. *)Array.iteri(funifreq->iffreq>0then(max_code:=i;Heap.pushifreqheap))freqs;try(* The pkzip format requires that at least one distance code exists, and
that at least one bit should be sent even if there is only one
possible code. So to avoid special checks later on we force at least
two codes of non zero frequency. *)whileHeap.lengthheap/2<2doHeap.push(if!max_code<2then!max_code+1else0)1heap;if!max_code<2thenincrmax_codedone;letnodes=Array.make(Heap.lengthheap/2)(0,0)inletvalues=Array.make(Heap.lengthheap/2)0inifArray.lengthnodes=1then(letindex,_=Heap.popheapinlength.(index)<-1;raiseOK);(* The elements heap[length / 2 + 1 .. length] are leaves of the tree,
establish sub-heaps of increasing lengths: *)fori=0to(Heap.lengthheap/2)-1donodes.(i)<-Heap.popheap;values.(i)<-nodes.(i)|>snddone;(* We can now generate the bit lengths. *)letcode_length=reverse_package_mergevalues(Array.lengthvalues)limitinArray.iteri(funi(index,_)->length.(index)<-code_length.(i))nodeswithOK->());lengthletget_codes_from_lengths?(max_code_length=16)lengths=letcount=Array.make(max_code_length+1)0inletstart_code=Array.make(max_code_length+1)0inletcodes=Array.make(Array.lengthlengths)0inArray.iter(funlength->count.(length)<-count.(length)+1)lengths;letcode=ref0infori=1tomax_code_lengthdostart_code.(i)<-!code;code:=!code+count.(i);code:=!codelsl1done;fori=0toArray.lengthlengths-1docode:=start_code.(lengths.(i));start_code.(lengths.(i))<-start_code.(lengths.(i))+1;for_=0tolengths.(i)-1docodes.(i)<-(codes.(i)lsl1)lor(!codeland1);code:=!codelsr1donedone;codesend(* Table from zlib *)moduleTable=structlet_extra_lbits=[|0;0;0;0;0;0;0;0;1;1;1;1;2;2;2;2;3;3;3;3;4;4;4;4;5;5;5;5;0|]let_extra_dbits=[|0;0;0;0;1;1;2;2;3;3;4;4;5;5;6;6;7;7;8;8;9;9;10;10;11;11;12;12;13;13|]let_base_length=[|0;1;2;3;4;5;6;7;8;10;12;14;16;20;24;28;32;40;48;56;64;80;96;112;128;160;192;224;255|]let_base_dist=[|0;1;2;3;4;6;8;12;16;24;32;48;64;96;128;192;256;384;512;768;1024;1536;2048;3072;4096;6144;8192;12288;16384;24576|]let_distance=lett=[|0;1;2;3;4;4;5;5;6;6;6;6;7;7;7;7;8;8;8;8;8;8;8;8;9;9;9;9;9;9;9;9;10;10;10;10;10;10;10;10;10;10;10;10;10;10;10;10;11;11;11;11;11;11;11;11;11;11;11;11;11;11;11;11;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;12;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;13;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;14;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;15;0;0;16;17;18;18;19;19;20;20;20;20;21;21;21;21;22;22;22;22;22;22;22;22;23;23;23;23;23;23;23;23;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;28;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29;29|]infuncode->ifcode<256thent.(code)elset.(256+(codelsr7))let_length=[|0;1;2;3;4;5;6;7;8;8;9;9;10;10;11;11;12;12;12;12;13;13;13;13;14;14;14;14;15;15;15;15;16;16;16;16;16;16;16;16;17;17;17;17;17;17;17;17;18;18;18;18;18;18;18;18;19;19;19;19;19;19;19;19;20;20;20;20;20;20;20;20;20;20;20;20;20;20;20;20;21;21;21;21;21;21;21;21;21;21;21;21;21;21;21;21;22;22;22;22;22;22;22;22;22;22;22;22;22;22;22;22;23;23;23;23;23;23;23;23;23;23;23;23;23;23;23;23;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;24;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;25;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;26;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;27;28|]let_hclen_order=[|16;17;18;0;8;7;9;6;10;5;11;4;12;3;13;2;14;1;15|]let_static_ltree=[|(12,8);(140,8);(76,8);(204,8);(44,8);(172,8);(108,8);(236,8);(28,8);(156,8);(92,8);(220,8);(60,8);(188,8);(124,8);(252,8);(2,8);(130,8);(66,8);(194,8);(34,8);(162,8);(98,8);(226,8);(18,8);(146,8);(82,8);(210,8);(50,8);(178,8);(114,8);(242,8);(10,8);(138,8);(74,8);(202,8);(42,8);(170,8);(106,8);(234,8);(26,8);(154,8);(90,8);(218,8);(58,8);(186,8);(122,8);(250,8);(6,8);(134,8);(70,8);(198,8);(38,8);(166,8);(102,8);(230,8);(22,8);(150,8);(86,8);(214,8);(54,8);(182,8);(118,8);(246,8);(14,8);(142,8);(78,8);(206,8);(46,8);(174,8);(110,8);(238,8);(30,8);(158,8);(94,8);(222,8);(62,8);(190,8);(126,8);(254,8);(1,8);(129,8);(65,8);(193,8);(33,8);(161,8);(97,8);(225,8);(17,8);(145,8);(81,8);(209,8);(49,8);(177,8);(113,8);(241,8);(9,8);(137,8);(73,8);(201,8);(41,8);(169,8);(105,8);(233,8);(25,8);(153,8);(89,8);(217,8);(57,8);(185,8);(121,8);(249,8);(5,8);(133,8);(69,8);(197,8);(37,8);(165,8);(101,8);(229,8);(21,8);(149,8);(85,8);(213,8);(53,8);(181,8);(117,8);(245,8);(13,8);(141,8);(77,8);(205,8);(45,8);(173,8);(109,8);(237,8);(29,8);(157,8);(93,8);(221,8);(61,8);(189,8);(125,8);(253,8);(19,9);(275,9);(147,9);(403,9);(83,9);(339,9);(211,9);(467,9);(51,9);(307,9);(179,9);(435,9);(115,9);(371,9);(243,9);(499,9);(11,9);(267,9);(139,9);(395,9);(75,9);(331,9);(203,9);(459,9);(43,9);(299,9);(171,9);(427,9);(107,9);(363,9);(235,9);(491,9);(27,9);(283,9);(155,9);(411,9);(91,9);(347,9);(219,9);(475,9);(59,9);(315,9);(187,9);(443,9);(123,9);(379,9);(251,9);(507,9);(7,9);(263,9);(135,9);(391,9);(71,9);(327,9);(199,9);(455,9);(39,9);(295,9);(167,9);(423,9);(103,9);(359,9);(231,9);(487,9);(23,9);(279,9);(151,9);(407,9);(87,9);(343,9);(215,9);(471,9);(55,9);(311,9);(183,9);(439,9);(119,9);(375,9);(247,9);(503,9);(15,9);(271,9);(143,9);(399,9);(79,9);(335,9);(207,9);(463,9);(47,9);(303,9);(175,9);(431,9);(111,9);(367,9);(239,9);(495,9);(31,9);(287,9);(159,9);(415,9);(95,9);(351,9);(223,9);(479,9);(63,9);(319,9);(191,9);(447,9);(127,9);(383,9);(255,9);(511,9);(0,7);(64,7);(32,7);(96,7);(16,7);(80,7);(48,7);(112,7);(8,7);(72,7);(40,7);(104,7);(24,7);(88,7);(56,7);(120,7);(4,7);(68,7);(36,7);(100,7);(20,7);(84,7);(52,7);(116,7);(3,8);(131,8);(67,8);(195,8);(35,8);(163,8);(99,8);(227,8)|]let_static_dtree=[|(0,5);(16,5);(8,5);(24,5);(4,5);(20,5);(12,5);(28,5);(2,5);(18,5);(10,5);(26,5);(6,5);(22,5);(14,5);(30,5);(1,5);(17,5);(9,5);(25,5);(5,5);(21,5);(13,5);(29,5);(3,5);(19,5);(11,5);(27,5);(7,5);(23,5)|]end(** non-blocking and functionnal implementation of Deflate *)moduletypeDEFLATE=sigtypeerrormoduleF:sigtypet=intarray*intarrayendtype('i,'o)tvalpp_error:Format.formatter->error->unitvalpp:Format.formatter->('i,'o)t->unitvalget_frequencies:('i,'o)t->F.tvalset_frequencies:?paranoid:bool->F.t->('i,'o)t->('i,'o)tvalfinish:('a,'a)t->('a,'a)tvalno_flush:int->int->('a,'a)t->('a,'a)tvalpartial_flush:int->int->('a,'a)t->('a,'a)tvalsync_flush:int->int->('a,'a)t->('a,'a)tvalfull_flush:int->int->('a,'a)t->('a,'a)ttypemeth=PARTIAL|SYNC|FULLvalflush_of_meth:meth->int->int->('a,'a)t->('a,'a)tvalflush:int->int->('i,'o)t->('i,'o)tvaleval:'a->'a->('a,'a)t->[`Awaitof('a,'a)t|`Flushof('a,'a)t|`Endof('a,'a)t|`Errorof('a,'a)t*error]valused_in:('i,'o)t->intvalused_out:('i,'o)t->intvaldefault:witness:'aB.t->?wbits:int->int->('a,'a)tvalto_result:'a->'a->?meth:meth*int->('a->intoption->int)->('a->int->int)->('a,'a)t->(('a,'a)t,error)resultvalbytes:Bytes.t->Bytes.t->?meth:meth*int->(Bytes.t->intoption->int)->(Bytes.t->int->int)->(Bytes.t,Bytes.t)t->((Bytes.t,Bytes.t)t,error)resultvalbigstring:B.Bigstring.t->B.Bigstring.t->?meth:meth*int->(B.Bigstring.t->intoption->int)->(B.Bigstring.t->int->int)->(B.Bigstring.t,B.Bigstring.t)t->((B.Bigstring.t,B.Bigstring.t)t,error)resultendmoduletypeS_deflate=sigtype('i,'o)ttypeerrortypemeth=PARTIAL|SYNC|FULLvaleval:'a->'a->('a,'a)t->[`Awaitof('a,'a)t|`Flushof('a,'a)t|`Endof('a,'a)t|`Errorof('a,'a)t*error]valfinish:('a,'a)t->('a,'a)tvalno_flush:int->int->('a,'a)t->('a,'a)tvalflush_of_meth:meth->int->int->('a,'a)t->('a,'a)tvalflush:int->int->('a,'a)t->('a,'a)tvalused_out:('a,'a)t->intendmoduleConvenience_deflate(X:S_deflate)=structletto_resultsrcdst?methrefillerflushert=letrecgoacct=match(X.evalsrcdstt,meth)with|`Awaitt,None->letn=refillersrcNoneinlett=ifn=0thenX.finishtelseX.no_flush0ntingo(acc+n)t|`Awaitt,Some(meth,max)->letn=refillersrc(Some(max-acc))inlett,acc'=ifn=0&&max-acc<>0then(X.finisht,acc)elseifmax=accthen(X.flush_of_methmeth0nt,0)else(X.no_flush0nt,acc+n)ingoacc't|`Flusht,_->letn=X.used_outtinletn=flusherdstningoacc(X.flush0nt)|`Endt,_->ifX.used_outt=0thenOktelseletn=X.used_outtinletn=flusherdstninOk(X.flush0nt)|`Error(_,exn),_->Errorexningo0tletbytessrcdst?methrefillerflushert=to_resultsrcdst?methrefillerflushertletbigstringsrcdst?methrefillerflushert=to_resultsrcdst?methrefillerflushertendtypeerror_rfc1951_deflate=Lz77ofL.errormoduleRFC1951_deflate=structmoduleF=structtypet=intarray*intarrayletppfmt_=Format.fprintffmt"(#lit, #dst)"letmake()=letlit,dst=(Array.make2860,Array.make300)in(* XXX: to force the existence of the opcode EOB. *)lit.(256)<-1;(lit,dst)letadd_literal(lit,_)chr=lit.(Char.codechr)<-lit.(Char.codechr)+1letadd_distance(lit,dst)(len,dist)=lit.(Table._length.(len)+256+1)<-lit.(Table._length.(len)+256+1)+1;dst.(Table._distancedist)<-dst.(Table._distancedist)+1letget_literals(lit,_)=litletget_distances(_,dst)=dstendtypeerror=error_rfc1951_deflatetype('i,'o)t={hold:int;bits:int;temp:([Safe.ro|Safe.wo],'o)Safe.t;o_off:int;o_pos:int;o_len:int;i_off:int;i_pos:int;i_len:int;level:int;wbits:int;write:int;adler:Checkseum.Adler32.t;state:('i,'o)state;wi:'iB.t;wo:'oB.t}and('i,'o)k=(Safe.ro,'i)Safe.t->(Safe.wo,'o)Safe.t->('i,'o)t->('i,'o)resand('i,'o)state=|MakeBlockof('i,'o)block|WriteBlockof('i,'o)k|FastBlockof(int*int)array*(int*int)array*Hunk.tQ.t*code*flush|AlignBlockofF.toption*bool|FixedBlockofF.t|DynamicHeaderof('i,'o)k|StaticHeaderof('i,'o)k|AlignFof('i,'o)k|Finishofint|Exceptionoferrorand('i,'o)res=|Contof('i,'o)t|Waitof('i,'o)t|Flushof('i,'o)t|Okof('i,'o)t|Errorof('i,'o)t*errorand('i,'o)block=|Staticof{lz:'iL.t;frequencies:F.t;deflate:Hunk.tSeq.t}|Dynamicof{lz:'iL.t;frequencies:F.t;deflate:Hunk.tSeq.t}|Flatofintandflush=SyncofF.t|PartialofF.t|Full|Finalandcode=Length|ExtLength|Dist|ExtDistandmeth=PARTIAL|SYNC|FULLletpp_errorppf=functionLz77lz->pfppf"(Lz77 %a)"L.pp_errorlzletpp_codeppf=function|Length->pfppf"Length"|ExtLength->pfppf"ExtLength"|Dist->pfppf"Dist"|ExtDist->pfppf"ExtDist"letpp_flushppf=function|Syncf->pfppf"(Sync %a)"F.ppf|Partialf->pfppf"(Partial %a)"F.ppf|Full->pfppf"Full"|Final->pfppf"Final"letpp_blockppf=function|Static{lz;frequencies;_}->pfppf"(Static (%a, %a, #deflate))"L.pplzF.ppfrequencies|Dynamic{lz;frequencies;_}->pfppf"(Dynamic (%a, %a, #deflate))"L.pplzF.ppfrequencies|Flatpos->pfppf"(Flat %d)"posletpp_stateppf=function|MakeBlockblock->pfppf"(MakeBlock %a)"pp_blockblock|WriteBlock_->pfppf"(WriteBlock #fun)"|FastBlock(_,_,_,code,flush)->pfppf"(FastBlock (#ltree, #dtree, #deflate, %a, %a))"pp_codecodepp_flushflush|AlignBlock(Somef,last)->pfppf"(AlignBlock (Some %a, last:%b))"F.ppflast|AlignBlock(None,last)->pfppf"(AlignBlock (None, last:%b))"last|FixedBlockf->pfppf"(FixedBlock %a)"F.ppf|DynamicHeader_->pfppf"(DynamicHeader #fun)"|StaticHeader_->pfppf"(StaticHeader #fun)"|AlignF_->pfppf"(AlignF #fun)"|Finishn->pfppf"(Finish %d)"n|Exceptionexn->pfppf"(Exception %a)"pp_errorexnletppppf{hold;bits;o_off;o_pos;o_len;i_off;i_pos;i_len;level;wbits;adler;state;_}=pfppf"{@[<hov>hold = %d;@ bits = %d;@ o_off = %d;@ o_pos = %d;@ o_len = %d;@ \
i_off = %d;@ i_pos = %d;@ i_len = %d;@ level = %d;@ wbits = %d;@ adler \
= %a;@ state = %a@]}"holdbitso_offo_poso_leni_offi_posi_lenlevelwbitsCheckseum.Adler32.ppadlerpp_statestateletawaitt:('i,'o)res=Waittleterrortexn:('i,'o)res=Error({twithstate=Exceptionexn},exn)letoktrest:('i,'o)res=Ok{twithstate=Finishrest}letblock_of_flush=function|Partialflush->FixedBlockflush|Full->AlignBlock(None,false)|Final->AlignBlock(None,true)|Syncflush->AlignBlock(Someflush,false)letrecput_byte~ctorbyteksrcdstt=ift.o_len-t.o_pos>0then(Safe.sett.wodst(t.o_off+t.o_pos)(Char.unsafe_chrbyte);ksrcdst{twitho_pos=t.o_pos+1;write=t.write+1})elseFlush{twithstate=ctor(funsrcdstt->(put_byte[@tailcall])~ctorbyteksrcdstt)}letput_short_lsb~ctorshortksrcdstt=letput_byte=put_byte~ctorin(put_byte(shortland0xFF)@@put_byte((shortlsr8)land0xFF)k)srcdsttletalign~ctorksrcdstt=(* XXX: we ensure than [hold] can not store more than 2 bytes. *)ift.bits>8thenletksrcdstt=ksrcdst{twithhold=0;bits=0}input_short_lsb~ctort.holdksrcdsttelseift.bits>0thenletksrcdstt=ksrcdst{twithhold=0;bits=0}input_byte~ctort.holdksrcdsttelseksrcdst{twithhold=0;bits=0}letput_bits~ctor(code,len)ksrcdstt=ift.bits+len>16thenletksrcdstt=ksrcdst{twithhold=codelsr(16-t.bits);bits=t.bits+len-16}input_short_lsb~ctor(t.holdlor(codelslt.bits))ksrcdsttelseksrcdst{twithhold=t.holdlor(codelslt.bits);bits=t.bits+len}letput_bit~ctorbitksrcdstt=ifbitthenput_bits~ctor(1,1)ksrcdsttelseput_bits~ctor(0,1)ksrcdsttmoduleKWriteBlock=structletctork=WriteBlockkletput_short_lsbshortksrcdstt=put_short_lsb~ctorshortksrcdsttletput_bitsbitsksrcdstt=put_bits~ctorbitsksrcdsttletput_bitbitksrcdstt=put_bit~ctorbitksrcdsttletalignksrcdstt=align~ctorksrcdsttendmoduleKDynamicHeader=structletctor=KWriteBlock.ctorletput_bitsksrcdstt=put_bits~ctorksrcdsttletput_transtrans_lengthhclenksrcdstt=letrecgoisrcdstt=ifi=hclenthenksrcdsttelseput_bits(trans_length.(i),3)(go(i+1))srcdsttingo0srcdsttletput_symbolstree_symboltree_codetree_length:('x,'x)k->('x,'x)k=funksrcdstt->letrecgoisrcdstt=ifi=Array.lengthtree_symbolthenksrcdsttelseletcode=Array.unsafe_gettree_symboliinletksrcdstt=ifcode>=16thenletbitlen=matchcodewith|16->2|17->3|18->7|_->assertfalseinput_bits(tree_symbol.(i+1),bitlen)(go(i+2))srcdsttelsego(i+1)srcdsttinput_bits(Array.unsafe_gettree_codecode,Array.unsafe_gettree_lengthcode)ksrcdsttingo0srcdsttendletget_tree_symbolshlitlit_lengthshdistdist_lengths=letlen=hlit+hdistinletsrc=Array.makelen0inletresult=Array.make(286+30)0inletfreqs=Array.make190infori=0tohlit-1doArray.unsafe_setsrci(Array.unsafe_getlit_lengthsi)done;fori=hlittohlit+hdist-1doArray.unsafe_setsrci(Array.unsafe_getdist_lengths(i-hlit))done;letn=ref0inleti=ref0inwhile!i<lendoletj=ref1inwhile!i+!j<len&&Array.unsafe_getsrc(!i+!j)=Array.unsafe_getsrc!idoincrjdone;letrun_length=ref!jinifArray.unsafe_getsrc!i=0thenif!run_length<3thenwhile!run_length>0doArray.unsafe_setresult!n0;incrn;Array.unsafe_setfreqs0(Array.unsafe_getfreqs0+1);decrrun_lengthdoneelsewhile!run_length>0doletrpt=ref(if!run_length<138then!run_lengthelse138)inif!rpt>!run_length-3&&!rpt<!run_lengththenrpt:=!run_length-3;if!rpt<=10then(Array.unsafe_setresult!n17;incrn;Array.unsafe_setresult!n(!rpt-3);incrn;Array.unsafe_setfreqs17(Array.unsafe_getfreqs17+1))else(Array.unsafe_setresult!n18;incrn;Array.unsafe_setresult!n(!rpt-11);incrn;Array.unsafe_setfreqs18(Array.unsafe_getfreqs18+1));run_length:=!run_length-!rptdoneelse(Array.unsafe_setresult!n(Array.unsafe_getsrc!i);incrn;Array.unsafe_setfreqs(Array.unsafe_getsrc!i)(Array.unsafe_getfreqs(Array.unsafe_getsrc!i)+1);decrrun_length;if!run_length<3thenwhile!run_length>0doArray.unsafe_setresult!n(Array.unsafe_getsrc!i);incrn;Array.unsafe_setfreqs(Array.unsafe_getsrc!i)(Array.unsafe_getfreqs(Array.unsafe_getsrc!i)+1);decrrun_lengthdoneelsewhile!run_length>0doletrpt=ref(if!run_length<6then!run_lengthelse6)inif!rpt>!run_length-3&&!rpt<!run_lengththenrpt:=!run_length-3;Array.unsafe_setresult!n16;incrn;Array.unsafe_setresult!n(!rpt-3);incrn;Array.unsafe_setfreqs16(Array.unsafe_getfreqs16+1);run_length:=!run_length-!rptdone);i:=!i+!jdone;(Array.subresult0!n,freqs)letblock_of_level~witness~wbits?frequencieslevel=matchlevelwith|0->Flat0|n->(letfrequencies=matchfrequencieswithSomefreqs->freqs|None->F.make()inleton=function|Hunk.Literalchr->F.add_literalfrequencieschr|Hunk.Match(len,dist)->F.add_distancefrequencies(len,dist)inmatchnwith|1|2|3->Static{lz=L.default~witness~on~levelwbits;frequencies;deflate=Seq.empty}|4|5|6|7|8|9->Dynamic{lz=L.default~witness~on~levelwbits;frequencies;deflate=Seq.empty}|n->invalid_arg"Invalid level: %d"n)letziparr1arr2=Array.init(Array.lengtharr1)(funi->(Array.unsafe_getarr1i,Array.unsafe_getarr2i))letwrite_blockltreedtreequeueflushsrcdstt=matchQ.take_front_exnqueuewith|Hunk.Literalchr,tl->(KWriteBlock.put_bits(Array.unsafe_getltree(Char.codechr))@@fun_src_dstt->Cont{twithstate=FastBlock(ltree,dtree,tl,Length,flush)})srcdstt|Hunk.Match(len,dist),tl->(KWriteBlock.put_bits(Array.unsafe_getltree(Array.unsafe_getTable._lengthlen+256+1))@@KWriteBlock.put_bits(len-Array.unsafe_getTable._base_length(Array.unsafe_getTable._lengthlen),Array.unsafe_getTable._extra_lbits(Array.unsafe_getTable._lengthlen))@@KWriteBlock.put_bits(Array.unsafe_getdtree(Table._distancedist))@@KWriteBlock.put_bits(dist-Array.unsafe_getTable._base_dist(Table._distancedist),Array.unsafe_getTable._extra_dbits(Table._distancedist))@@fun_src_dstt->Cont{twithstate=FastBlock(ltree,dtree,tl,Length,flush)})srcdstt|exceptionQ.Empty->(KWriteBlock.put_bits(Array.unsafe_getltree256)@@fun_src_dstt->Cont{twithstate=block_of_flushflush})srcdsttletstaticfrequenciesqueueflushsrcdstt=letflush=flushfrequenciesinletk_src_dstt=Cont{twithstate=FastBlock(Table._static_ltree,Table._static_dtree,queue,Length,flush)}in(KWriteBlock.put_bitfalse(* XXX: when the user expect a final block, zlib put an empty block to
align the output in byte - this last block has the final flag. *)@@KWriteBlock.put_bits(1,2)k)srcdsttletdynamicfrequenciesqueueflushsrcdstt=lettrans_length=Array.make190inletliteral_length=T.get_lengths(F.get_literalsfrequencies)15inletliteral_code=T.get_codes_from_lengthsliteral_lengthinletdistance_length=T.get_lengths(F.get_distancesfrequencies)7inletdistance_code=T.get_codes_from_lengthsdistance_lengthinlethlit=ref286inwhile!hlit>257&&literal_length.(!hlit-1)=0dodecrhlitdone;lethdist=ref30inwhile!hdist>1&&distance_length.(!hdist-1)=0dodecrhdistdone;lettree_symbol,f=get_tree_symbols!hlitliteral_length!hdistdistance_lengthinlettree_length=T.get_lengthsf7infori=0to18dotrans_length.(i)<-tree_length.(Table._hclen_order.(i))done;lethclen=ref19inwhile!hclen>4&&trans_length.(!hclen-1)=0dodecrhclendone;lettree_code=T.get_codes_from_lengthstree_lengthinlethlit=!hlitinlethdist=!hdistinlethclen=!hcleninletflush=flushfrequenciesinletk_src_dstt=letltree=zipliteral_codeliteral_lengthinletdtree=zipdistance_codedistance_lengthinCont{twithstate=FastBlock(ltree,dtree,queue,Length,flush)}in(KWriteBlock.put_bitfalse(* XXX: when the user expect a final block, zlib put an empty block to
align the output in byte - this last block has the final flag. *)@@KWriteBlock.put_bits(2,2)@@KWriteBlock.put_bits(hlit-257,5)@@KWriteBlock.put_bits(hdist-1,5)@@KWriteBlock.put_bits(hclen-4,4)@@KDynamicHeader.put_transtrans_lengthhclen@@KDynamicHeader.put_symbolstree_symboltree_codetree_lengthk)srcdsttletalign_bytessrcdstt=letrest=ift.bits>8then8-(t.bits-8)elseift.bits>0then8-t.bitselse0inletk_src_dstt=oktrestinKWriteBlock.alignksrcdsttletrecwrite_flatoffposlenfinal_srcdstt=iflen-pos=0theniffinalthenCont{twithstate=AlignFalign_bytes}elseCont{twithstate=MakeBlock(Flat0)}elseletn=min(len-pos)(t.o_len-t.o_pos)inSafe.blitt.wot.temp(off+pos)dst(t.o_off+t.o_pos)n;ift.o_len-(t.o_pos+n)=0thenFlush{twithstate=WriteBlock(funsrcdstt->(write_flat[@tailcall])0(pos+n)lenfinalsrcdstt);o_pos=t.o_pos+n;write=t.write+n}elseCont{twithstate=WriteBlock(funsrcdstt->(write_flat[@tailcall])0(pos+n)lenfinalsrcdstt);o_pos=t.o_pos+n;write=t.write+n}letflatoffposlenfinalsrcdstt=(KWriteBlock.put_bitfinal@@KWriteBlock.put_bits(0,2)@@KWriteBlock.align@@KWriteBlock.put_short_lsblen@@KWriteBlock.put_short_lsb(lnotlen)@@write_flatoffposlenfinal)(* XXX: from [make_block] may be, it's not necessary to pass [off], [pos]
and [final]. We use an internal buffer and ensure to start it to 0 for
example. [pos] is used only by [write_flat]. *)srcdsttletmake_blocksrc_dstt=function|Static{lz;frequencies;deflate}->(matchL.evalsrclzwith|`Await(lz,seq)->await{twithstate=MakeBlock(Static{lz;frequencies;deflate=Seq.appenddeflateseq});i_pos=t.i_pos+L.used_inlz;adler=Safe.adler32t.wisrc(t.i_off+t.i_pos)(L.used_inlz)t.adler}|`Error(_,exn)->errort(Lz77exn))|Dynamic{lz;frequencies;deflate}->(matchL.evalsrclzwith|`Await(lz,seq)->await{twithstate=MakeBlock(Dynamic{lz;frequencies;deflate=Seq.appenddeflateseq});i_pos=t.i_pos+L.used_inlz;adler=Safe.adler32t.wisrc(t.i_off+t.i_pos)(L.used_inlz)t.adler}|`Error(_,exn)->errort(Lz77exn))|Flatpos->letlen=min(t.i_len-t.i_pos)(0x8000-pos)inSafe.blitt.wosrc(t.i_off+t.i_pos)t.tempposlen;ifpos+len=0x8000thenCont{twithstate=WriteBlock(flat000x8000false);i_pos=t.i_pos+len;adler=Safe.adler32t.wisrc(t.i_off+t.i_pos)lent.adler}elseawait{twithstate=MakeBlock(Flat(pos+len));i_pos=t.i_pos+len;adler=Safe.adler32t.wisrc(t.i_off+t.i_pos)lent.adler}letfixed_blockfrequencieslastsrcdstt=(KWriteBlock.put_bitlast@@KWriteBlock.put_bits(1,2)@@KWriteBlock.put_bits(Array.unsafe_getTable._static_ltree256)@@fun_str_dstt->letblock=block_of_level~witness:t.wi~wbits:t.wbits~frequenciest.levelinCont{twithstate=(iflastthenAlignFalign_byteselseMakeBlockblock)})srcdsttletalign_blockfrequencieslastsrcdstt=(KWriteBlock.put_bitlast@@KWriteBlock.put_bits(0,2)@@KWriteBlock.align@@KWriteBlock.put_short_lsb0x0000@@KWriteBlock.put_short_lsb0xFFFF@@fun_src_dstt->letblock=block_of_level~witness:t.wi~wbits:t.wbits?frequenciest.levelinCont{twithstate=(iflastthenAlignFalign_byteselseMakeBlockblock)})srcdsttletwrite_fast_block_srcdsttltreedtreequeuecodeflush=letqueue=refqueueinlethold=reft.holdinletbits=reft.bitsinleto_pos=reft.o_posinletwrite=reft.writeinletgoto=refcodeinwhileQ.is_empty!queue=false&&t.o_len-!o_pos>1dolethd,tl=Q.take_front_exn!queueinlet(code,len),new_goto,new_queue=match(!goto,hd)with|Length,Hunk.Literalchr->(Array.unsafe_getltree(Char.codechr),Length,tl)|Length,Hunk.Match(len,_)->(Array.unsafe_getltree(Array.unsafe_getTable._lengthlen+256+1),ExtLength,!queue)|ExtLength,Hunk.Match(len,_)->letcode=Array.unsafe_getTable._lengthlenin((len-Array.unsafe_getTable._base_lengthcode,Array.unsafe_getTable._extra_lbitscode),Dist,!queue)|Dist,Hunk.Match(_,dist)->(Array.unsafe_getdtree(Table._distancedist),ExtDist,!queue)|ExtDist,Hunk.Match(_,dist)->letcode=Table._distancedistin((dist-Array.unsafe_getTable._base_distcode,Array.unsafe_getTable._extra_dbitscode),Length,tl)|ExtDist,Hunk.Literal_|Dist,Hunk.Literal_|ExtLength,Hunk.Literal_->assertfalseinif!bits+len>16then(Safe.sett.wodst(t.o_off+!o_pos)(Char.chr(!holdlor(codelsl!bits)land0xFF));incro_pos;incrwrite;Safe.sett.wodst(t.o_off+!o_pos)(Char.chr(((!holdlor(codelsl!bits))lsr8)land0xFF));incro_pos;incrwrite;hold:=codelsr(16-!bits);bits:=!bits+len-16)else(hold:=!holdlor(codelsl!bits);bits:=!bits+len);goto:=new_goto;queue:=new_queuedone;letk0queuesrcdstt=write_blockltreedtreequeueflushsrcdsttinletk1queuedistsrcdstt=KWriteBlock.put_bits(dist-Array.unsafe_getTable._base_dist(Table._distancedist),Array.unsafe_getTable._extra_dbits(Table._distancedist))(k0queue)srcdsttinletk2queuedistsrcdstt=KWriteBlock.put_bits(Array.unsafe_getdtree(Table._distancedist))(k1queuedist)srcdsttinletk3queuelendistsrcdstt=KWriteBlock.put_bits(len-Array.unsafe_getTable._base_length(Array.unsafe_getTable._lengthlen),Array.unsafe_getTable._extra_lbits(Array.unsafe_getTable._lengthlen))(k2queuedist)srcdsttinletkesrcdstt=KWriteBlock.put_bits(Array.unsafe_getltree256)(fun_src_dstt->Cont{twithstate=block_of_flushflush})srcdsttinletstate=match(Q.take_front_exn!queue,!goto)with|_,Length->WriteBlock(k0!queue)|(Hunk.Match(len,dist),tl),ExtLength->WriteBlock(k3tllendist)|(Hunk.Match(_,dist),tl),Dist->WriteBlock(k2tldist)|(Hunk.Match(_,dist),tl),ExtDist->WriteBlock(k1tldist)|(Hunk.Literal_,_),(ExtLength|Dist|ExtDist)->assertfalse|exceptionQ.Empty->WriteBlockkeinlett={twithhold=!hold;bits=!bits;o_pos=!o_pos;write=!write;state}inConttletflushofflent={twitho_off=off;o_len=len;o_pos=0}letget_frequenciest=matcht.statewith|MakeBlock(Dynamic{frequencies;_})|MakeBlock(Static{frequencies;_})->frequencies|_->invalid_arg"get_frequencies: invalid state"letset_frequencies?(paranoid=false)(lit,dst)t=letcheck=Seq.iter(function|Hunk.Literalchr->ifArray.unsafe_getlit(Char.codechr)=0theninvalid_arg"set_frequencies: invalid frequencies"|Hunk.Match(len,dist)->ifArray.unsafe_getlit(Array.unsafe_getTable._lengthlen+156+1)=0||Array.unsafe_getdst(Table._distancedist)=0theninvalid_arg"set_frequencies: invalid frequencies")inifArray.unsafe_getlit256>0thenmatcht.statewith|MakeBlock(Dynamicx)->ifparanoidthencheckx.deflate;{twithstate=MakeBlock(Dynamic{xwithfrequencies=(lit,dst)})}|MakeBlock(Staticx)->{twithstate=MakeBlock(Static{xwithfrequencies=(lit,dst)})}|_->invalid_arg"set_frequencies: invalid state"elseinvalid_arg"set_frequencies: invalid frequencies"letto_final_frequencies=Finalletto_partialfrequencies=Partialfrequenciesletto_syncfrequencies=Syncfrequenciesletto_full_frequencies=Fullletfinisht=matcht.statewith|MakeBlock(Dynamicx)->{twithstate=DynamicHeader(dynamicx.frequencies(Q.of_seqx.deflate)to_final)}|MakeBlock(Staticx)->{twithstate=StaticHeader(staticx.frequencies(Q.of_seqx.deflate)to_final)}|MakeBlock(Flatlen)->{twithstate=WriteBlock(flat00lentrue)}|_->invalid_arg"finish: invalid state"letno_flushofflent=matcht.statewith|MakeBlock(Dynamicx)->{twithstate=MakeBlock(Dynamic{xwithlz=L.refillofflenx.lz});i_off=off;i_len=len;i_pos=0}|MakeBlock(Staticx)->{twithstate=MakeBlock(Static{xwithlz=L.refillofflenx.lz});i_off=off;i_len=len;i_pos=0}|MakeBlock(Flatlen')->{twithstate=MakeBlock(Flatlen');i_off=off;i_len=len;i_pos=0}|_->invalid_arg"no_flush: invalid state"(* XXX: factorize *)letpartial_flushofflent=matcht.statewith|MakeBlockblock->ift.i_len-t.i_pos>0thenmatchblockwith|Dynamicx->{twithstate=DynamicHeader(dynamicx.frequencies(Q.of_seqx.deflate)to_partial);i_off=off;i_len=len;i_pos=0}|Staticx->{twithstate=StaticHeader(staticx.frequencies(Q.of_seqx.deflate)to_partial);i_off=off;i_len=len;i_pos=0}|Flatlen->{twithstate=WriteBlock(flat00lenfalse);i_off=off;i_len=len;i_pos=0}elseinvalid_arg"partial_flush: you lost something (pos: %d, len: %d)"t.i_post.i_len|_->invalid_arg"partial_flush: invalid state"letsync_flushofflent=matcht.statewith|MakeBlockblock->ift.i_len-t.i_pos>0thenmatchblockwith|Dynamicx->{twithstate=DynamicHeader(dynamicx.frequencies(Q.of_seqx.deflate)to_sync);i_off=off;i_len=len;i_pos=0}|Staticx->{twithstate=StaticHeader(staticx.frequencies(Q.of_seqx.deflate)to_sync);i_off=off;i_len=len;i_pos=0}|Flatlen->{twithstate=WriteBlock(flat00lenfalse);i_off=off;i_len=len;i_pos=0}elseinvalid_arg"sync_flush: you lost something (pos: %d, len: %d)"t.i_post.i_len|_->invalid_arg"sync_flush: invalid state"letfull_flushofflent=matcht.statewith|MakeBlockblock->ift.i_len-t.i_pos>0thenmatchblockwith|Dynamicx->{twithstate=DynamicHeader(dynamicx.frequencies(Q.of_seqx.deflate)to_full);i_off=off;i_len=len;i_pos=0}|Staticx->{twithstate=StaticHeader(staticx.frequencies(Q.of_seqx.deflate)to_full);i_off=off;i_len=len;i_pos=0}|Flatlen->{twithstate=WriteBlock(flat00lenfalse);i_off=off;i_len=len;i_pos=0}elseinvalid_arg"full_flush: you lost something (pos: %d, len: %d)"t.i_post.i_len|_->invalid_arg"full_flush: invalid state"letflush_of_meth=function|PARTIAL->partial_flush|SYNC->sync_flush|FULL->full_flushleteval0safe_srcsafe_dstt=matcht.statewith|MakeBlockblock->make_blocksafe_srcsafe_dsttblock|WriteBlockk->ksafe_srcsafe_dstt|FastBlock(ltree,dtree,queue,code,flush)->write_fast_blocksafe_srcsafe_dsttltreedtreequeuecodeflush|AlignBlock(freqs,last)->align_blockfreqslastsafe_srcsafe_dstt|FixedBlockfreqs->fixed_blockfreqsfalsesafe_srcsafe_dstt|DynamicHeaderk->ksafe_srcsafe_dstt|StaticHeaderk->ksafe_srcsafe_dstt|AlignFk->ksafe_srcsafe_dstt|Finishn->oktn|Exceptionexn->errortexnletevalsrcdstt=letsafe_src=Safe.rot.wisrcinletsafe_dst=Safe.wot.wodstinletrecloopt=matcheval0safe_srcsafe_dsttwith|Contt->loopt|Waitt->`Awaitt|Flusht->`Flusht|Okt->`Endt|Error(t,exn)->`Error(t,exn)inlooptletused_int=t.i_posletused_outt=t.o_posletbits_remainingt=matcht.statewith|Finishbits->bits|_->invalid_arg"bits_remaining: bad state"letdefault~witness?(wbits=15)level={hold=0;bits=0;temp=(iflevel<>0thenSafe.rwwitness(B.emptywitness)elseSafe.rwwitness(B.createwitness0x8000));o_off=0;o_pos=0;o_len=0;i_off=0;i_pos=0;i_len=0;write=0;level;wbits;adler=Checkseum.Adler32.default;state=MakeBlock(block_of_level~witness~wbitslevel);wi=witness;wo=witness}includeConvenience_deflate(structtypenonrec('i,'o)t=('i,'o)ttypenonrecerror=errortypenonrecmeth=meth=PARTIAL|SYNC|FULLleteval=evalletfinish=finishletno_flush=no_flushletflush_of_meth=flush_of_methletflush=flushletused_out=used_outend)endtypeerror_z_deflate=RFC1951oferror_rfc1951_deflatemoduleZlib_deflate=structtypeerror=error_z_deflatemoduleF=RFC1951_deflate.Ftype('i,'o)t={d:('i,'o)RFC1951_deflate.t;z:('i,'o)state}and('i,'o)k=(Safe.ro,'i)Safe.t->(Safe.wo,'o)Safe.t->('i,'o)t->('i,'o)resand('i,'o)state=|Headerof('i,'o)k|Deflate|Adler32of('i,'o)k|Finish|Exceptionoferrorand('i,'o)res=|Contof('i,'o)t|Waitof('i,'o)t|Flushof('i,'o)t|Okof('i,'o)t|Errorof('i,'o)t*errorandmeth=RFC1951_deflate.meth=PARTIAL|SYNC|FULLletpp_errorfmt=function|RFC1951err->Format.fprintffmt"(RFC1951 %a)"RFC1951_deflate.pp_errorerrletpp_statefmt=function|Header_->Format.fprintffmt"(Header #fun)"|Deflate->Format.fprintffmt"Deflate"|Adler32_->Format.fprintffmt"(Adler32 #fun)"|Finish->Format.fprintffmt"Finish"|Exceptione->Format.fprintffmt"(Exception %a)"pp_erroreletppfmt{d;z}=Format.fprintffmt"{@[<hov>d = @[<hov>%a@];@ z = %a;@]}"RFC1951_deflate.ppdpp_statezletokt:('i,'o)res=Ok{twithz=Finish}leterrortexn:('i,'o)res=Error({twithz=Exceptionexn},exn)letrecput_byte~ctorbyteksrcdstt=ift.d.RFC1951_deflate.o_len-t.d.RFC1951_deflate.o_pos>0then(Safe.sett.d.RFC1951_deflate.wodst(t.d.RFC1951_deflate.o_off+t.d.RFC1951_deflate.o_pos)(Char.unsafe_chrbyte);ksrcdst{twithd={t.dwithRFC1951_deflate.o_pos=t.d.RFC1951_deflate.o_pos+1;RFC1951_deflate.write=t.d.RFC1951_deflate.write+1}})elseFlush{twithz=ctor(funsrcdstt->(put_byte[@tailcall])~ctorbyteksrcdstt)}letput_short_lsb~ctorshortksrcdstt=letput_byte=put_byte~ctorin(put_byte(shortland0xFF)@@put_byte((shortlsr8)land0xFF)k)srcdsttletalign~ctorksrcdstt=(* XXX: we ensure than [hold] can not store more than 2 bytes. *)ift.d.RFC1951_deflate.bits>8thenletksrcdstt=ksrcdst{twithd={t.dwithRFC1951_deflate.hold=0;RFC1951_deflate.bits=0}}input_short_lsb~ctort.d.RFC1951_deflate.holdksrcdsttelseift.d.RFC1951_deflate.bits>0thenletksrcdstt=ksrcdst{twithd={t.dwithRFC1951_deflate.hold=0;RFC1951_deflate.bits=0}}input_byte~ctort.d.RFC1951_deflate.holdksrcdsttelseksrcdst{twithd={t.dwithRFC1951_deflate.hold=0;RFC1951_deflate.bits=0}}letput_short_msb~ctorshortksrcdstt=letput_byte=put_byte~ctorin(put_byte((shortlsr8)land0xFF)@@put_byte(shortland0xFF)k)srcdsttmoduleKHeader=structletctork=Headerkletput_short_msbshortksrcdstt=put_short_msb~ctorshortksrcdsttendmoduleKAdler32=structletctork=Adler32kletalignksrcdstt=align~ctorksrcdsttletput_short_msbshortksrcdstt=put_short_msb~ctorshortksrcdsttendletadler32srcdstt=letadler=t.d.RFC1951_deflate.adlerinletk_src_dstt=oktin(KAdler32.align@@KAdler32.put_short_msbOptint.(to_intInfix.(adler>>16&&of_int320xFFFFl))@@KAdler32.put_short_msbOptint.(to_intInfix.(adler&&of_int320xFFFFl))k)srcdsttletdeflatesrcdstt=matchRFC1951_deflate.eval0srcdstt.dwith|RFC1951_deflate.Contd->Cont{twithd}|RFC1951_deflate.Waitd->Wait{twithd}|RFC1951_deflate.Flushd->Flush{twithd}|RFC1951_deflate.Okd->Cont{z=Adler32adler32;d}|RFC1951_deflate.Error(d,exn)->error{twithd}(RFC1951exn)letheaderwbitssrcdstt=letheader=(8+((wbits-8)lsl4))lsl8inletheader=headerlor(0x4lsl5)in(* XXX: FDICT = 0 and FLEVEL = 2, we use a default algorithm. *)letheader=header+(31-(headermod31))inletk_src_dstt=Cont{d={t.dwithRFC1951_deflate.hold=0;RFC1951_deflate.bits=0};z=Deflate}inKHeader.put_short_msbheaderksrcdsttletevalsrcdstt=letsafe_src=Safe.rot.d.RFC1951_deflate.wisrcinletsafe_dst=Safe.wot.d.RFC1951_deflate.wodstinleteval0t=matcht.zwith|Headerk->ksafe_srcsafe_dstt|Deflate->deflatesafe_srcsafe_dstt|Adler32k->ksafe_srcsafe_dstt|Finish->okt|Exceptionexn->errortexninletrecloopt=matcheval0twith|Contt->loopt|Waitt->`Awaitt|Flusht->`Flusht|Okt->`Endt|Error(t,exn)->`Error(t,exn)inlooptletdefault~witness?(wbits=15)level={d=RFC1951_deflate.default~witness~wbitslevel;z=Header(headerwbits)}letget_frequenciest=RFC1951_deflate.get_frequenciest.dletset_frequencies?paranoidfreqst={twithd=RFC1951_deflate.set_frequencies?paranoidfreqst.d}letfinisht={twithd=RFC1951_deflate.finisht.d}letno_flushofflent={twithd=RFC1951_deflate.no_flushofflent.d}letpartial_flushofflent={twithd=RFC1951_deflate.partial_flushofflent.d}letsync_flushofflent={twithd=RFC1951_deflate.sync_flushofflent.d}letfull_flushofflent={twithd=RFC1951_deflate.full_flushofflent.d}letflush_of_methmethofflent={twithd=RFC1951_deflate.flush_of_methmethofflent.d}letflushofflent={twithd=RFC1951_deflate.flushofflent.d}letused_int=RFC1951_deflate.used_int.dletused_outt=RFC1951_deflate.used_outt.dincludeConvenience_deflate(structtypenonrec('i,'o)t=('i,'o)ttypenonrecerror=errortypenonrecmeth=meth=PARTIAL|SYNC|FULLleteval=evalletfinish=finishletno_flush=no_flushletflush_of_meth=flush_of_methletflush=flushletused_out=used_outend)endmoduleWindow=structtype'at={rpos:int;wpos:int;size:int;buffer:([Safe.ro|Safe.wo],'a)Safe.t;crc:Checkseum.Adler32.t;witness:'aB.t}letcreate~witness=letsize=1lsl15in{rpos=0;wpos=0;size=size+1;buffer=Safe.rwwitness(B.createwitness(size+1));crc=Checkseum.Adler32.default;witness}letcrc{crc;_}=crcletresett={twithrpos=0;wpos=0;crc=Checkseum.Adler32.default}letavailable_to_write{wpos;rpos;size;_}=ifwpos>=rposthensize-(wpos-rpos)-1elserpos-wpos-1letdropn({rpos;size;_}ast)={twithrpos=(ifrpos+n<sizethenrpos+nelserpos+n-size)}letmoven({wpos;size;_}ast)={twithwpos=(ifwpos+n<sizethenwpos+nelsewpos+n-size)}externalhack:('a,'i)Safe.t->(Safe.ro,'i)Safe.t="%identity"(* consider than [buf] is the window. *)letwritebufoffdstdst_offlent=lett=iflen>available_to_writetthendrop(len-available_to_writet)telsetinletpre=t.size-t.wposinletextra=len-preinifextra>0then(Safe.blit2t.witnessbufofft.buffert.wposdstdst_offpre;Safe.blit2t.witnessbuf(off+pre)t.buffer0dst(dst_off+pre)extra)elseSafe.blit2t.witnessbufofft.buffert.wposdstdst_offlen;movelen{twithcrc=Safe.adler32t.witness(hackdst)dst_offlent.crc}(* XXX(dinosaure): [dst] is more reliable than [buf] because [buf] is the
[window]. *)letwrite_charchrt=lett=if1>available_to_writetthendrop(1-available_to_writet)telsetinSafe.sett.witnesst.buffert.wposchr;move1{twithcrc=Checkseum.Adler32.digest_bytes(Bytes.make1chr)01t.crc}letfill_charchrlent=lett=iflen>available_to_writetthendrop(len-available_to_writet)telsetinletpre=t.size-t.wposinletextra=len-preinifextra>0then(Safe.fillt.witnesst.buffert.wposprechr;Safe.fillt.witnesst.buffer0extrachr)elseSafe.fillt.witnesst.buffert.wposlenchr;movelen{twithcrc=Checkseum.Adler32.digest_bytes(Bytes.makelenchr)0lent.crc}letrecsanitizen({size;_}ast)=ifn<0thensanitize(size+n)telseifn>=0&&n<sizethennelsesanitize(n-size)tlet(%)nt=ifn<t.sizethensanitizentelseraise(Failure"Window.( % )")end(** non-blocking and functionnal implementation of Inflate *)moduletypeINFLATE=sigtypeerrortype('i,'o)tvalpp_error:Format.formatter->error->unitvalpp:Format.formatter->('i,'o)t->unitvaleval:'a->'a->('a,'a)t->[`Awaitof('a,'a)t|`Flushof('a,'a)t|`Endof('a,'a)t|`Errorof('a,'a)t*error]valrefill:int->int->('i,'o)t->('i,'o)tvalflush:int->int->('i,'o)t->('i,'o)tvalused_in:('i,'o)t->intvalused_out:('i,'o)t->intvalwrite:('i,'o)t->intvaldefault:'oWindow.t->('i,'o)tvalto_result:'a->'a->('a->int)->('a->int->int)->('a,'a)t->(('a,'a)t,error)resultvalbytes:Bytes.t->Bytes.t->(Bytes.t->int)->(Bytes.t->int->int)->(Bytes.t,Bytes.t)t->((Bytes.t,Bytes.t)t,error)resultvalbigstring:B.Bigstring.t->B.Bigstring.t->(B.Bigstring.t->int)->(B.Bigstring.t->int->int)->(B.Bigstring.t,B.Bigstring.t)t->((B.Bigstring.t,B.Bigstring.t)t,error)resultendmoduletypeS_inflate=sigtype('i,'o)ttypeerrorvaleval:'a->'a->('a,'a)t->[`Awaitof('a,'a)t|`Flushof('a,'a)t|`Endof('a,'a)t|`Errorof('a,'a)t*error]valrefill:int->int->('i,'o)t->('i,'o)tvalflush:int->int->('i,'o)t->('i,'o)tvalused_out:('i,'o)t->intendmoduleConvenience_inflate(X:S_inflate)=structletto_resultsrcdstrefillerflushert=letrecgot=matchX.evalsrcdsttwith|`Awaitt->letn=refillersrcingo(X.refill0nt)|`Flusht->letn=X.used_outtinletn=flusherdstningo(X.flush0nt)|`Endt->ifX.used_outt=0thenOktelseletn=X.used_outtinletn=flusherdstninOk(X.flush0nt)|`Error(_,exn)->Errorexningotletbytessrcdstrefillerflushert=to_resultsrcdstrefillerflushertletbigstringsrcdstrefillerflushert=to_resultsrcdstrefillerflushertendtypeerror_rfc1951_inflate=|Invalid_kind_of_block|Invalid_complement_of_length|Invalid_dictionary|Invalid_distance_code|Invalid_distanceof{distance:int;max:int}moduleRFC1951_inflate=struct(* functionnal implementation of Heap, bisoux @c-cube *)moduleHeap=structtypepriority=inttype'aqueue=None|Nodeofpriority*'a*'aqueue*'aqueueletrecpushqueuepriorityelt=matchqueuewith|None->Node(priority,elt,None,None)|Node(p,e,left,right)->ifpriority<=pthenNode(priority,elt,pushrightpe,left)elseNode(p,e,pushrightpriorityelt,left)exceptionEmptyletrecremove=function|None->raiseEmpty|Node(_,_,left,None)->left|Node(_,_,None,right)->right|Node(_,_,(Node(lp,le,_,_)asleft),(Node(rp,re,_,_)asright))->iflp<=rpthenNode(lp,le,removeleft,right)elseNode(rp,re,left,removeright)lettake=function|None->raiseEmpty|Node(p,e,_,_)asqueue->(p,e,removequeue)endmoduleHuffman=structexceptionInvalid_huffmanletprefixheapmax=assert(max<=15);(* lol *)lettbl=Array.make(1lslmax)0inletrecbackwardhuffincr=ifhufflandincr<>0thenbackwardhuff(incrlsr1)elseincrinletrecauxhuffheap=matchHeap.takeheapwith|_,(len,value),heap->letrecloopdecrfill=tbl.(huff+fill)<-(lenlsl15)lorvalue;iffill<>0thenloopdecr(fill-decr)inletdecr=1lslleninloopdecr((1lslmax)-decr);letincr=backwardhuff(1lsl(len-1))inaux(ifincr<>0then(huffland(incr-1))+increlse0)heap|exceptionHeap.Empty->()inaux0heap;tbllet_MAX_BITS=15exceptionBreakletmake?(kind=`CODES)tableoffcodes_max_bits=letbl_count=Array.make(_MAX_BITS+1)0inforsym=0tocodes-1doletp=table.(off+sym)inbl_count.(p)<-bl_count.(p)+1done;letmax=ref_MAX_BITSinlet()=trywhile!max>=1doifbl_count.(!max)<>0thenraiseBreak;decrmaxdonewithBreak->()inletcode=ref0inletleft=ref1inletnext_code=Array.make(_MAX_BITS+1)0infori=1to_MAX_BITSdoleft:=!leftlsl1;left:=!left-bl_count.(i);if!left<0thenraiseInvalid_huffman;code:=(!code+bl_count.(i))lsl1;next_code.(i)<-!codedone;if!left>0&&(kind=`CODES||!max<>1)thenraiseInvalid_huffman;letordered=refHeap.Noneinletmax=ref0infori=0tocodes-1doletl=table.(off+i)inifl<>0then(letn=next_code.(l-1)innext_code.(l-1)<-n+1;ordered:=Heap.push!orderedn(l,i);max:=ifl>!maxthenlelse!max)done;(prefix!ordered!max,!max)endletreverse_bits=lett=[|0x00;0x80;0x40;0xC0;0x20;0xA0;0x60;0xE0;0x10;0x90;0x50;0xD0;0x30;0xB0;0x70;0xF0;0x08;0x88;0x48;0xC8;0x28;0xA8;0x68;0xE8;0x18;0x98;0x58;0xD8;0x38;0xB8;0x78;0xF8;0x04;0x84;0x44;0xC4;0x24;0xA4;0x64;0xE4;0x14;0x94;0x54;0xD4;0x34;0xB4;0x74;0xF4;0x0C;0x8C;0x4C;0xCC;0x2C;0xAC;0x6C;0xEC;0x1C;0x9C;0x5C;0xDC;0x3C;0xBC;0x7C;0xFC;0x02;0x82;0x42;0xC2;0x22;0xA2;0x62;0xE2;0x12;0x92;0x52;0xD2;0x32;0xB2;0x72;0xF2;0x0A;0x8A;0x4A;0xCA;0x2A;0xAA;0x6A;0xEA;0x1A;0x9A;0x5A;0xDA;0x3A;0xBA;0x7A;0xFA;0x06;0x86;0x46;0xC6;0x26;0xA6;0x66;0xE6;0x16;0x96;0x56;0xD6;0x36;0xB6;0x76;0xF6;0x0E;0x8E;0x4E;0xCE;0x2E;0xAE;0x6E;0xEE;0x1E;0x9E;0x5E;0xDE;0x3E;0xBE;0x7E;0xFE;0x01;0x81;0x41;0xC1;0x21;0xA1;0x61;0xE1;0x11;0x91;0x51;0xD1;0x31;0xB1;0x71;0xF1;0x09;0x89;0x49;0xC9;0x29;0xA9;0x69;0xE9;0x19;0x99;0x59;0xD9;0x39;0xB9;0x79;0xF9;0x05;0x85;0x45;0xC5;0x25;0xA5;0x65;0xE5;0x15;0x95;0x55;0xD5;0x35;0xB5;0x75;0xF5;0x0D;0x8D;0x4D;0xCD;0x2D;0xAD;0x6D;0xED;0x1D;0x9D;0x5D;0xDD;0x3D;0xBD;0x7D;0xFD;0x03;0x83;0x43;0xC3;0x23;0xA3;0x63;0xE3;0x13;0x93;0x53;0xD3;0x33;0xB3;0x73;0xF3;0x0B;0x8B;0x4B;0xCB;0x2B;0xAB;0x6B;0xEB;0x1B;0x9B;0x5B;0xDB;0x3B;0xBB;0x7B;0xFB;0x07;0x87;0x47;0xC7;0x27;0xA7;0x67;0xE7;0x17;0x97;0x57;0xD7;0x37;0xB7;0x77;0xF7;0x0F;0x8F;0x4F;0xCF;0x2F;0xAF;0x6F;0xEF;0x1F;0x9F;0x5F;0xDF;0x3F;0xBF;0x7F;0xFF|]infunbits->t.(bits)moduleLookup=structtypet={table:intarray;max:int;mask:int}letmax_mask=(1lsl15)-1letmaketablemax={table;max;mask=(1lslmax)-1}letfixed_chr=lettbl=Array.init288(funn->ifn<144then8elseifn<256then9elseifn<280then7else8)inlettbl,max=Huffman.make~kind:`LENStbl02889inmaketblmaxletfixed_dst=lettbl=Array.make(1lsl5)0inArray.iteri(funi_->tbl.(i)<-(5lsl15)lorreverse_bits(ilsl3))tbl;maketbl5letgettidx=letshadow=t.table.(idx)in(shadowlsr15,shadowlandmax_mask)endtype('i,'o)t={last:bool;hold:int;bits:int;o_off:int;o_pos:int;o_len:int;i_off:int;i_pos:int;i_len:int;write:int;state:('i,'o)state;window:'oWindow.t;wbits:int;wi:'iB.t;wo:'oB.t}and('i,'o)k=(Safe.ro,'i)Safe.t->(Safe.wo,'o)Safe.t->('i,'o)t->('i,'o)resand('i,'o)state=|Last|Block|Flatof('i,'o)k|Fixed|Dictionaryof('i,'o)k|Inffastof(Lookup.t*Lookup.t*code)|Inflateof('i,'o)k|Switch|Finishofint|Exceptionoferrorand('i,'o)res=|Contof('i,'o)t|Waitof('i,'o)t|Flushof('i,'o)t|Okof('i,'o)t|Errorof('i,'o)t*errorandcode=|Length|ExtLengthofint|Distofint|ExtDistofint*int|Writeofint*intanderror=error_rfc1951_inflateletpp_errorppf=function|Invalid_kind_of_block->pfppf"Invalid_kind_of_block"|Invalid_complement_of_length->pfppf"Invalid_complement_of_length"|Invalid_dictionary->pfppf"Invalid_dictionary"|Invalid_distance_code->pfppf"Invalid_distance_code"|Invalid_distance{distance;max}->pfppf"(Invalid_distance { @[distance = %d;@ max = %d;@] })"distancemaxletpp_codeppf=function|Length->pfppf"Length"|ExtLengthc->pfppf"(ExtLength %d)"c|Distc->pfppf"(Dist %d)"c|ExtDist(a,b)->pfppf"(ExtDist (%d, %d))"ab|Write(a,b)->pfppf"(Write (%d, %d))"abletpp_stateppf=function|Last->pfppf"Last"|Block->pfppf"Block"|Flat_->pfppf"(Flat #fun)"|Fixed->pfppf"Fixed"|Dictionary_->pfppf"(Dictionary #fun)"|Inffast(_,_,c)->pfppf"(Inffast %a)"pp_codec|Inflate_->pfppf"(Inflate #fun)"|Switch->pfppf"Switch"|Finishn->pfppf"(Finish %d)"n|Exceptione->pfppf"(Exception %a)"pp_erroreletppppf{last;hold;bits;o_off;o_pos;o_len;i_off;i_pos;i_len;write;state;wbits;_}=pfppf"{ @[<hov>last = %b;@ hold = %d;@ bits = %d;@ o_off = %d;@ o_pos = %d;@ \
o_len = %d;@ i_off = %d;@ i_pos = %d;@ i_len = %d;@ write = %d;@ state \
= %a;@ wbits = %d;@ window = #window;@] }"lastholdbitso_offo_poso_leni_offi_posi_lenwritepp_statestatewbitsleterrortexn=Error({twithstate=Exceptionexn},exn)letoktn=Ok{twithstate=Finishn}(* Basics operations. *)letrecget_byte~ctorksrcdstt=ift.i_len-t.i_pos>0thenletbyte=Char.code(Safe.gett.wisrc(t.i_off+t.i_pos))inkbytesrcdst{twithi_pos=t.i_pos+1}elseWait{twithstate=ctor(funsrcdstt->(get_byte[@tailcall])~ctorksrcdstt)}letrecput_byte~ctorbyteksrcdstt=ift.o_len-t.o_pos>0then(letchr=Char.unsafe_chrbyteinletwindow=Window.write_charchrt.windowinSafe.sett.wodst(t.o_off+t.o_pos)chr;ksrcdst{twitho_pos=t.o_pos+1;write=t.write+1;window})elseFlush{twithstate=ctor(funsrcdstt->(put_byte[@tailcall])~ctorbyteksrcdstt)}letrecfill_byte~ctorbytelengthksrcdstt=ift.o_len-t.o_pos>0then(letchr=Char.unsafe_chrbyteinletlen=minlength(t.o_len-t.o_pos)inletwindow=Window.fill_charchrlent.windowinSafe.fillt.wodst(t.o_off+t.o_pos)lenchr;iflength-len>0thenFlush{twithstate=ctor(funsrcdstt->(fill_byte[@tailcall])~ctorbyte(length-len)ksrcdstt);o_pos=t.o_pos+len;write=t.write+len;window}elseksrcdst{twitho_pos=t.o_pos+len;write=t.write+len;window})elseFlush{twithstate=ctor(funsrcdstt->(fill_byte[@tailcall])~ctorbytelengthksrcdstt)}letpeek_bits~ctornksrcdstt=letget_byte=get_byte~ctorinletrecgosrcdstt=ift.bits<nthenget_byte(funbytesrcdstt->(go[@tailcall])srcdst{twithhold=t.holdlor(bytelslt.bits);bits=t.bits+8})srcdsttelseksrcdsttingosrcdsttletdrop_bits~ctornksrcdstt=letgosrcdstt=ksrcdst{twithhold=t.holdlsrn;bits=t.bits-n}inift.bits<nthenpeek_bits~ctorngosrcdsttelsegosrcdsttletget_bits~ctornksrcdstt=letgosrcdstt=letv=t.holdland((1lsln)-1)inkvsrcdst{twithhold=t.holdlsrn;bits=t.bits-n}inift.bits<nthenpeek_bits~ctorngosrcdsttelsegosrcdsttletget_with_holding~ctorksrcdstt=(* XXX: [hold] contains one already read byte. *)ift.bits>=8thenletbyte=t.holdland0xFFinkbytesrcdst{twithhold=t.holdlsr8;bits=t.bits-8}elseget_byte~ctorksrcdsttletget_int16~ctorksrcdstt=letget_byte=get_with_holding~ctorinletkbyte0srcdstt=letkbyte1srcdstt=k(byte0lor(byte1lsl8))srcdsttinget_byteksrcdsttinget_byteksrcdsttmoduleKLast=structletctor_k=Lastletpeek_bitsnksrcdstt=peek_bits~ctornksrcdsttendmoduleKBlock=structletctor_k=Blockletpeek_bitsnksrcdstt=peek_bits~ctornksrcdsttendmoduleKDictionary=structletctork=Dictionarykletpeek_bitsnksrcdstt=peek_bits~ctornksrcdsttletdrop_bitsnksrcdstt=drop_bits~ctornksrcdsttletget_bitsnksrcdstt=get_bits~ctornksrcdsttendmoduleKFlat=structletctork=Flatkletget_int16ksrcdstt=get_int16~ctorksrcdsttletdrop_bitsnksrcdstt=drop_bits~ctornksrcdsttendmoduleKInflate=structletctork=Inflatekletpeek_bitsnksrcdstt=peek_bits~ctornksrcdsttletput_bytebyteksrcdstt=put_byte~ctorbyteksrcdsttletfill_bytebytelengthksrcdstt=fill_byte~ctorbytelengthksrcdsttletgetlookupksrcdstt0=letsafesrcdstt1=letlen,v=Lookup.getlookup(t1.holdlandlookup.Lookup.mask)inkvsrcdst{t1withhold=t1.holdlsrlen;bits=t1.bits-len}inpeek_bitslookup.Lookup.maxsafesrcdstt0letrecputlookup_chrlookup_dstlengthdistanceksrcdstt=matchdistancewith|1->letchr=Safe.gett.wot.window.Window.bufferWindow.((t.window.wpos-1)%t.window)inletbyte=Char.codechrinfill_bytebytelengthksrcdstt|distance->ifdistance>1lslt.wbitsthenerrort(Invalid_distance{distance;max=1lslt.wbits})elseletlen=min(t.o_len-t.o_pos)lengthinletoff=Window.((t.window.wpos-distance)%t.window)inletsze=t.window.Window.sizeinletpre=sze-offinletext=len-preinletwindow=ifext>0thenletwindow=Window.writet.window.Window.bufferoffdst(t.o_off+t.o_pos)pret.windowinWindow.writewindow.Window.buffer0dst(t.o_off+t.o_pos+pre)extwindowelseWindow.writet.window.Window.bufferoffdst(t.o_off+t.o_pos)lent.windowiniflength-len>0thenFlush{twitho_pos=t.o_pos+len;write=t.write+len;state=Inflate(putlookup_chrlookup_dst(length-len)distancek);window}elseCont{twitho_pos=t.o_pos+len;write=t.write+len;state=Inffast(lookup_chr,lookup_dst,Length);window}letread_extra_distdistanceksrcdstt=matchTable._extra_dbits.(distance)with|len->letsafesrcdstt=letextra=t.holdland((1lsllen)-1)ink(Table._base_dist.(distance)+1+extra)srcdst{twithhold=t.holdlsrlen;bits=t.bits-len}inpeek_bitslensafesrcdstt|exceptionInvalid_argument_->errortInvalid_distance_codeletread_extra_lengthlengthksrcdstt=letlen=Table._extra_lbits.(length)inletsafesrcdstt=letextra=t.holdland((1lsllen)-1)ink(Table._base_length.(length)+3+extra)srcdst{twithhold=t.holdlsrlen;bits=t.bits-len}inpeek_bitslensafesrcdsttendmoduleDictionary=structtypet={idx:int;prv:int;max:int;dictionary:intarray}letmakemax={idx=0;prv=0;max;dictionary=Array.makemax0}letinflate(tbl,max_bits,max)ksrcdstt=letmask_bits=(1lslmax_bits)-1inletgetksrcdstt=letksrcdstt=(* safe-zone
optimization: tbl is an integer array which integer is split in
two parts. As we know about RFC1951, [v] should not be more than
32767. So, [len] is stored as [len << 15] and [v] is masked on [(1
<< 15) - 1] - TODO it could not be necessary to mask 2 times to
get [v]. *)letlen,v=(tbl.(t.holdlandmask_bits)lsr15,tbl.(t.holdlandmask_bits)landLookup.max_mask)inletksrcdstt=kvsrcdsttinKDictionary.drop_bitslenksrcdsttinKDictionary.peek_bitsmax_bitsksrcdsttinletrecgostatevaluesrcdstt=matchvaluewith|16->letkstatensrcdstt=ifstate.idx+n+3>state.maxthenerrortInvalid_dictionaryelse(forj=0ton+3-1dostate.dictionary.(state.idx+j)<-state.prvdone;ifstate.idx+n+3<state.maxthenletkvsrcdstt=(go[@tailcall]){statewithidx=state.idx+n+3}vsrcdsttingetksrcdsttelsekstate.dictionarysrcdstt)in(* XXX(dinosaure): see invalid bit length repeat error on [zlib]. *)ifstate.idx=0thenerrortInvalid_dictionaryelseKDictionary.get_bits2(kstate)srcdstt|17->letkstatensrcdstt=ifstate.idx+n+3>state.maxthenerrortInvalid_dictionaryelseifstate.idx+n+3<state.maxthenletkvsrcdstt=(go[@tailcall]){statewithidx=state.idx+n+3}vsrcdsttingetksrcdsttelsekstate.dictionarysrcdsttinKDictionary.get_bits3(kstate)srcdstt|18->letkstatensrcdstt=ifstate.idx+n+11>state.maxthenerrortInvalid_dictionaryelseifstate.idx+n+11<state.maxthenletkvsrcdstt=(go[@tailcall]){statewithidx=state.idx+n+11}vsrcdsttingetksrcdsttelsekstate.dictionarysrcdsttinKDictionary.get_bits7(kstate)srcdstt|n->ifn<=15then(state.dictionary.(state.idx)<-n;ifstate.idx+1<state.maxthenletkvsrcdstt=(go[@tailcall]){statewithidx=state.idx+1;prv=n}vsrcdsttingetksrcdsttelsekstate.dictionarysrcdstt)elseerrortInvalid_dictionaryinletstate=makemaxinletkvsrcdstt=gostatevsrcdsttingetksrcdsttendletfixed_src_dstt=Cont{twithstate=Inffast(Lookup.fixed_chr,Lookup.fixed_dst,Length)}letdictionarysrcdstt=letmake_tablehlithdist_hclenbufsrcdstt=matchHuffman.make~kind:`CODESbuf0197with|tbl,max->letkdict_src_dstt=match(Huffman.make~kind:`LENSdict0hlit15,Huffman.make~kind:`DISTdicthlithdist15)with|(tbl_chr,max_chr),(tbl_dst,max_dst)->ifmax_chr>0(* && max_dst > 0 ? *)thenCont{twithstate=Inffast(Lookup.maketbl_chrmax_chr,Lookup.maketbl_dstmax_dst,Length)}elseerrortInvalid_dictionary|exceptionHuffman.Invalid_huffman->errortInvalid_dictionaryinDictionary.inflate(tbl,max,hlit+hdist)ksrcdstt|exceptionHuffman.Invalid_huffman->errortInvalid_dictionaryinletread_tablehlithdisthclensrcdstt=letbuf=Array.make190inletrecgoidxcodesrcdstt=buf.(Table._hclen_order.(idx))<-code;ifidx+1=hclenthen(fori=hclento18doArray.unsafe_setbuf(Array.unsafe_getTable._hclen_orderi)0done;make_tablehlithdisthclenbufsrcdstt)elseletksrcdstt=(go[@tailcall])(idx+1)srcdsttinKDictionary.get_bits3ksrcdsttinletkcodesrcdstt=go0codesrcdsttinKDictionary.get_bits3ksrcdsttinletread_hclenhlithdistsrcdstt=letkhclensrcdstt=read_tablehlithdist(hclen+4)srcdsttinKDictionary.get_bits4ksrcdsttinletread_hdisthlitsrcdstt=letkhdistsrcdstt=ifhlit>286||hdist>30thenerrortInvalid_dictionaryelseread_hclenhlit(hdist+1)srcdsttinKDictionary.get_bits5ksrcdsttinletread_hlitsrcdstt=letkhlitsrcdstt=read_hdist(hlit+257)srcdsttinKDictionary.get_bits5ksrcdsttinread_hlitsrcdsttletswitch_src_dstt=ift.lastthenoktt.bitselseCont{twithstate=Last}letflatsrcdstt=letrecgolengthsrcdstt=letn=minlength(min(t.i_len-t.i_pos)(t.o_len-t.o_pos))inletwindow=Window.writesrc(t.i_off+t.i_pos)dst(t.o_off+t.o_pos)nt.windowiniflength-n=0thenCont{twithi_pos=t.i_pos+n;o_pos=t.o_pos+n;write=t.write+n;state=Switch;window}elsematch(t.i_len-(t.i_pos+n),t.o_len-(t.o_pos+n))with|0,_->Wait{twithi_pos=t.i_pos+n;o_pos=t.o_pos+n;write=t.write+n;state=Flat(go(length-n));window}|_,0->Flush{twithi_pos=t.i_pos+n;o_pos=t.o_pos+n;write=t.write+n;state=Flat(go(length-n));window}|_,_->Cont{twithi_pos=t.i_pos+n;o_pos=t.o_pos+n;write=t.write+n;state=Flat(go(length-n));window}inletheaderlennlen_src_dstt=ifnlen<>0xFFFF-lenthenerrortInvalid_complement_of_lengthelseCont{twithhold=0;bits=0;state=Flat(golen)}in(* XXX: not sure about that, may be a part of [int16] is in [hold]. *)(KFlat.drop_bits(t.bitsmod8)@@KFlat.get_int16@@funlen->KFlat.get_int16@@funnlen->headerlennlen)srcdsttletinflatelookup_chrlookup_dstsrcdstt=letrecgolengthsrcdstt0=(* XXX: recursion. *)letklength_src_dstt7=Cont{t7withstate=Inflate(funsrcdstt8->(go[@tailcall])lengthsrcdstt8)}inletksrcdstt6=KInflate.getlookup_chrksrcdstt6inmatchlengthwith|256->Cont{t0withstate=Switch}|length->iflength<256thenKInflate.put_bytelengthksrcdstt0elseletklengthdistancesrcdstt5=KInflate.putlookup_chrlookup_dstlengthdistanceksrcdstt5inletklengthdistancesrcdstt3=KInflate.read_extra_distdistance(fundistsrcdstt4->klengthdistsrcdstt4)srcdstt3inletklengthsrcdstt1=KInflate.getlookup_dst(fundistsrcdstt2->klengthdistsrcdstt2)srcdstt1inKInflate.read_extra_length(length-257)ksrcdstt0inKInflate.getlookup_chrgosrcdsttexceptionEnd(* this is the end, beautiful friend. *)exceptionExn_invalid_distanceof(int*int)letinffastsrcdsttlookup_chrlookup_dstgoto=lethold=reft.holdinletbits=reft.bitsinletgoto=refgotoinleti_pos=reft.i_posinleto_pos=reft.o_posinletwrite=reft.writeinletwindow=reft.windowintrywhilet.i_len-!i_pos>1&&t.o_len-!o_pos>0domatch!gotowith|Length->if!bits<lookup_chr.Lookup.maxthen(hold:=!holdlor(Char.code(Safe.gett.wisrc(t.i_off+!i_pos))lsl!bits);bits:=!bits+8;incri_pos;hold:=!holdlor(Char.code(Safe.gett.wisrc(t.i_off+!i_pos))lsl!bits);bits:=!bits+8;incri_pos);letlen,value=Lookup.getlookup_chr(!holdlandlookup_chr.Lookup.mask)inhold:=!holdlsrlen;bits:=!bits-len;ifvalue<256then(Safe.sett.wodst(t.o_off+!o_pos)(Char.chrvalue);window:=Window.write_char(Char.chrvalue)!window;incro_pos;incrwrite;goto:=Length)elseifvalue=256thenraiseEndelsegoto:=ExtLength(value-257)|ExtLengthlength->letlen=Table._extra_lbits.(length)inif!bits<lenthen(hold:=!holdlor(Char.code(Safe.gett.wisrc(t.i_off+!i_pos))lsl!bits);bits:=!bits+8;incri_pos);letextra=!holdland((1lsllen)-1)inhold:=!holdlsrlen;bits:=!bits-len;goto:=Dist(Table._base_length.(length)+3+extra)|Distlength->if!bits<lookup_dst.Lookup.maxthen(hold:=!holdlor(Char.code(Safe.gett.wisrc(t.i_off+!i_pos))lsl!bits);bits:=!bits+8;incri_pos;hold:=!holdlor(Char.code(Safe.gett.wisrc(t.i_off+!i_pos))lsl!bits);bits:=!bits+8;incri_pos);letlen,value=Lookup.getlookup_dst(!holdlandlookup_dst.Lookup.mask)inhold:=!holdlsrlen;bits:=!bits-len;goto:=ExtDist(length,value)|ExtDist(length,dist)->letlen=Table._extra_dbits.(dist)inif!bits<lenthen(hold:=!holdlor(Char.code(Safe.gett.wisrc(t.i_off+!i_pos))lsl!bits);bits:=!bits+8;incri_pos;hold:=!holdlor(Char.code(Safe.gett.wisrc(t.i_off+!i_pos))lsl!bits);bits:=!bits+8;incri_pos);letextra=!holdland((1lsllen)-1)inhold:=!holdlsrlen;bits:=!bits-len;goto:=Write(length,Table._base_dist.(dist)+1+extra)|Write(length,1)->letchr=Safe.gett.wo!window.Window.bufferWindow.((!window.wpos-1)%!window)inletn=minlength(t.o_len-!o_pos)inwindow:=Window.fill_charchrn!window;Safe.fillt.wodst(t.o_off+!o_pos)nchr;o_pos:=!o_pos+n;write:=!write+n;goto:=iflength-n=0thenLengthelseWrite(length-n,1)|Write(length,dist)->ifdist>1lslt.wbitsthenraise(Exn_invalid_distance(dist,1lslt.wbits));letn=minlength(t.o_len-!o_pos)inletoff=Window.((!window.wpos-dist)%!window)inletlen=!window.Window.sizeinletpre=len-offinletext=n-preinwindow:=ifext>0thenletwindow=Window.write!window.Window.bufferoffdst(t.o_off+!o_pos)pre!windowinWindow.writewindow.Window.buffer0dst(t.o_off+!o_pos+pre)extwindowelseWindow.write!window.Window.bufferoffdst(t.o_off+!o_pos)n!window;o_pos:=!o_pos+n;write:=!write+n;goto:=iflength-n=0thenLengthelseWrite(length-n,dist)done;letk0srcdstt=inflatelookup_chrlookup_dstsrcdsttinletk1lengthdistancesrcdstt=KInflate.putlookup_chrlookup_dstlengthdistancek0srcdsttinletk2lengthdistancesrcdstt=KInflate.read_extra_distdistance(k1length)srcdsttinletk3lengthsrcdstt=KInflate.getlookup_dst(k2length)srcdsttinletk4lengthsrcdstt=KInflate.read_extra_lengthlengthk3srcdsttinletstate=match!gotowith|Length->Inflate(inflatelookup_chrlookup_dst)|ExtLengthlength->Inflate(k4length)|Distlength->Inflate(k3length)|ExtDist(length,distance)->Inflate(k2lengthdistance)|Write(length,distance)->Inflate(k1lengthdistance)inCont{twithhold=!hold;bits=!bits;i_pos=!i_pos;o_pos=!o_pos;write=!write;state;window=!window}withEnd->Cont{twithhold=!hold;bits=!bits;i_pos=!i_pos;o_pos=!o_pos;write=!write;state=Switch;window=!window}letblocksrcdstt=letsafe_src_dstt=letstate=matcht.holdland0x3with|0->Flatflat|1->Fixed|2->Dictionarydictionary|_->ExceptionInvalid_kind_of_blockinCont{twithhold=t.holdlsr2;bits=t.bits-2;state}inKBlock.peek_bits2safesrcdsttletlastsrcdstt=letsafe_src_dstt=letlast=t.holdland1=1inCont{twithlast;hold=t.holdlsr1;bits=t.bits-1;state=Block}inKLast.peek_bits1safesrcdsttleteval0safe_srcsafe_dstt=matcht.statewith|Last->lastsafe_srcsafe_dstt|Block->blocksafe_srcsafe_dstt|Flatk->ksafe_srcsafe_dstt|Fixed->fixedsafe_srcsafe_dstt|Dictionaryk->ksafe_srcsafe_dstt|Inffast(lookup_chr,lookup_dst,code)->(tryinffastsafe_srcsafe_dsttlookup_chrlookup_dstcodewithExn_invalid_distance(distance,max)->errort(Invalid_distance{distance;max}))|Inflatek->ksafe_srcsafe_dstt|Switch->switchsafe_srcsafe_dstt|Finishn->oktn|Exceptionexn->errortexnletevalsrcdstt=letsafe_src=Safe.rot.wisrcinletsafe_dst=Safe.wot.wodstinletrecloopt=matcheval0safe_srcsafe_dsttwith|Contt->loopt|Waitt->`Awaitt|Flusht->`Flusht|Okt->`Endt|Error(t,exn)->`Error(t,exn)inlooptletdefault~witness?(wbits=15)window=ifwbits<8||wbits>15theninvalid_arg"Invalid wbits value (8 >= wbits <= 15)";{last=false;hold=0;bits=0;i_off=0;i_pos=0;i_len=0;o_off=0;o_pos=0;o_len=0;write=0;state=Last;wbits;window;wi=witness;wo=witness}letrefillofflent=ift.i_pos=t.i_lenthen{twithi_off=off;i_len=len;i_pos=0}elsematcht.statewith|Finish_->(* XXX(dinosaure): when inflation computation is done, we don care if
we lost something. *){twithi_off=off;i_len=len;i_pos=0}|_->invalid_arg"refill: you lost something (pos: %d, len: %d)"t.i_post.i_lenletflushofflent={twitho_off=off;o_len=len;o_pos=0}letused_int=t.i_posletused_outt=t.o_posletwritet=t.writeletbits_remainingt=matcht.statewith|Finishn->n|_->invalid_arg"bits_remaining: bad state"includeConvenience_inflate(structtypenonrec('i,'o)t=('i,'o)ttypenonrecerror=errorleteval=evalletrefill=refillletflush=flushletused_out=used_outend)endtypeerror_z_inflate=|RFC1951ofRFC1951_inflate.error|Invalid_header|Invalid_checksumof{have:Optint.t;expect:Optint.t}moduleZlib_inflate=structtype('i,'o)t={d:('i,'o)RFC1951_inflate.t;z:('i,'o)state;expected_wbits:intoption}and('i,'o)k=(Safe.ro,'i)Safe.t->(Safe.wo,'o)Safe.t->('i,'o)t->('i,'o)resand('i,'o)state=|Headerof('i,'o)k|Inflate|Adler32of('i,'o)k|Finish|Exceptionoferrorand('i,'o)res=|Contof('i,'o)t|Waitof('i,'o)t|Flushof('i,'o)t|Okof('i,'o)t|Errorof('i,'o)t*erroranderror=error_z_inflateletpp_errorppf=function|RFC1951err->pfppf"(RFC1951 %a)"RFC1951_inflate.pp_errorerr|Invalid_header->pfppf"Invalid_header"|Invalid_checksum{have;expect}->pfppf"(Invalid_check (have:%a, expect:%a))"Optint.pphaveOptint.ppexpectletpp_stateppf=function|Header_->pfppf"(Header #fun)"|Inflate->pfppf"Inflate"|Adler32_->pfppf"(Adler32 #fun)"|Finish->pfppf"Finish"|Exceptione->pfppf"(Exception %a)"pp_erroreletppppf{d;z;_}=pfppf"{@[<hov>d = @[<hov>%a@];@ z = %a;@]}"RFC1951_inflate.ppdpp_statezleterrortexn=Error({twithz=Exceptionexn},exn)letokt=Ok{twithz=Finish}letrecget_byte~ctorksrcdstt=ift.d.RFC1951_inflate.i_len-t.d.RFC1951_inflate.i_pos>0thenletbyte=Char.code(Safe.gett.d.RFC1951_inflate.wisrc(t.d.RFC1951_inflate.i_off+t.d.RFC1951_inflate.i_pos))inkbytesrcdst{twithd={t.dwithRFC1951_inflate.i_pos=t.d.RFC1951_inflate.i_pos+1}}elseWait{twithz=ctor(funsrcdstt->(get_byte[@tailcall])~ctorksrcdstt)}letget_with_holding~ctorksrcdstt=(* XXX: [hold] contains one already read byte. *)ift.d.RFC1951_inflate.bits>=8thenletbyte=t.d.RFC1951_inflate.holdland0xFFinkbytesrcdst{twithd={t.dwithRFC1951_inflate.hold=t.d.RFC1951_inflate.holdlsr8;RFC1951_inflate.bits=t.d.RFC1951_inflate.bits-8}}elseget_byte~ctorksrcdsttletpeek_bits~ctornksrcdstt=letget_byte=get_byte~ctorinletrecgosrcdstt=ift.d.RFC1951_inflate.bits<nthenget_byte(funbytesrcdstt->(go[@tailcall])srcdst{twithd={t.dwithRFC1951_inflate.hold=t.d.RFC1951_inflate.holdlor(bytelslt.d.RFC1951_inflate.bits);RFC1951_inflate.bits=t.d.RFC1951_inflate.bits+8}})srcdsttelseksrcdsttingosrcdsttletdrop_bits~ctornksrcdstt=letgosrcdstt=ksrcdst{twithd={t.dwithRFC1951_inflate.hold=t.d.RFC1951_inflate.holdlsrn;RFC1951_inflate.bits=t.d.RFC1951_inflate.bits-n}}inift.d.RFC1951_inflate.bits<nthenpeek_bits~ctorngosrcdsttelsegosrcdsttmoduleKHeader=structletctork=Headerkletget_byteksrcdstzlib=get_byte~ctorksrcdstzlibendmoduleKCrc=structletctork=Adler32kletget_with_holdingksrcdstt=get_with_holding~ctorksrcdsttletdrop_bitsnksrcdstt=drop_bits~ctornksrcdsttendletadler32srcdstt=lethave=Window.crct.d.RFC1951_inflate.windowin(KCrc.drop_bits(t.d.RFC1951_inflate.bitsmod8)@@KCrc.get_with_holding@@funa1->KCrc.get_with_holding@@funa2->KCrc.get_with_holding@@funb1->KCrc.get_with_holding@@funb2_src_dstt->leta1=Optint.of_inta1inleta2=Optint.of_inta2inletb1=Optint.of_intb1inletb2=Optint.of_intb2inletexpect=Optint.Infix.(a1<<24||a2<<16||b1<<8||b2)inifOptint.equalhaveexpectthenoktelseerrort(Invalid_checksum{have;expect}))srcdsttletinflatesrcdstt=matchRFC1951_inflate.eval0srcdstt.dwith|RFC1951_inflate.Contd->Cont{twithd}|RFC1951_inflate.Waitd->Wait{twithd}|RFC1951_inflate.Flushd->Flush{twithd}|RFC1951_inflate.Okd->Cont{twithz=Adler32adler32;d}|RFC1951_inflate.Error(d,exn)->error{twithd}(RFC1951exn)letheadersrcdstt=(KHeader.get_byte@@funbyte0->KHeader.get_byte@@funbyte1_src_dstt->lethold=byte0inlethold=hold+(byte1lsl8)inletbits?(hold=hold)n=holdland((1lsln)-1)inletdropn=holdlsrninletoption_isve=matchvwithSomee'->e=e'|None->trueinif((bits8lsl8)+(holdlsr8))mod31=0&&bits4=8&&bits~hold:(drop4)4+8<=15&&option_ist.expected_wbits(bits~hold:(drop4)4+8)thenCont{twithz=Inflate;d={t.dwithRFC1951_inflate.wbits=bits~hold:(drop4)4+8}}elseerrortInvalid_header)srcdsttletevalsrcdstt=letsafe_src=Safe.rot.d.RFC1951_inflate.wisrcinletsafe_dst=Safe.wot.d.RFC1951_inflate.wodstinleteval0t=matcht.zwith|Headerk->ksafe_srcsafe_dstt|Inflate->inflatesafe_srcsafe_dstt|Adler32k->ksafe_srcsafe_dstt|Finish->okt|Exceptionexn->errortexninletrecloopt=matcheval0twith|Contt->loopt|Waitt->`Awaitt|Flusht->`Flusht|Okt->`Endt|Error(t,exn)->`Error(t,exn)inlooptletdefault~witness?(wbits=None)window={d=RFC1951_inflate.default~witness?wbitswindow;z=Headerheader;expected_wbits=wbits}letrefillofflent={twithd=RFC1951_inflate.refillofflent.d}letflushofflent={twithd=RFC1951_inflate.flushofflent.d}letused_int=RFC1951_inflate.used_int.dletused_outt=RFC1951_inflate.used_outt.dletwritet=RFC1951_inflate.writet.dincludeConvenience_inflate(structtypenonrec('i,'o)t=('i,'o)ttypenonrecerror=errorleteval=evalletrefill=refillletflush=flushletused_out=used_outend)end