123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887letio_buffer_size=65536letkstrfkfmt=Format.kasprintfkfmtletinvalid_argfmt=Format.kasprintfinvalid_argfmtmoduleBigarray=Bigarray_compat(* XXX(dinosaure): MirageOS compatibility. *)typebigstring=(char,Bigarray.int8_unsigned_elt,Bigarray.c_layout)Bigarray.Array1.ttypewindow=De.windowtypeoptint=Optint.tletbigstring_createl=Bigarray.Array1.createBigarray.charBigarray.c_layoutlletbigstring_empty=Bigarray.Array1.createBigarray.charBigarray.c_layout0letbigstring_lengthx=Bigarray.Array1.dimx[@@inline]externalswap16:int->int="%bswap16"externalswap32:int32->int32="caml_int32_bswap"externalunsafe_get_uint8:bigstring->int->int="%caml_ba_ref_1"externalunsafe_get_char:bigstring->int->char="%caml_ba_ref_1"externalunsafe_get_uint16:bigstring->int->int="%caml_bigstring_get16"externalunsafe_get_uint32:bigstring->int->int32="%caml_bigstring_get32"externalunsafe_set_char:bigstring->int->char->unit="%caml_ba_set_1"externalunsafe_set_uint8:bigstring->int->int->unit="%caml_ba_set_1"externalunsafe_set_uint16:bigstring->int->int->unit="%caml_bigstring_set16"externalunsafe_set_uint32:bigstring->int->int32->unit="%caml_bigstring_set32"letbytes_unsafe_get_uint8:bytes->int->int=funbufoff->Char.code(Bytes.getbufoff)externalbytes_unsafe_get_uint32:bytes->int->int32="%caml_bytes_get32"letbytes_unsafe_set_uint8:bytes->int->int->unit=funbufoffv->Bytes.setbufoff(Char.unsafe_chr(vland0xff))externalbytes_unsafe_set_uint16:bytes->int->int->unit="%caml_bytes_set16"externalbytes_unsafe_set_uint32:bytes->int->int32->unit="%caml_bytes_set32"letstring_unsafe_get_uint8:string->int->int=funbufoff->Char.code(String.getbufoff)externalstring_unsafe_get_uint32:string->int->int32="%caml_string_get32"externalstring_unsafe_get_uint16:string->int->int="%caml_string_get16"letinput_bigstringicbufofflen=lettmp=Bytes.createleninletres=inputictmp0leninletlen0=resland3inletlen1=resasr2infori=0tolen1-1doleti=i*4inletv=bytes_unsafe_get_uint32tmpiinunsafe_set_uint32buf(off+i)vdone;fori=0tolen0-1doleti=len1*4+iinletv=bytes_unsafe_get_uint8tmpiinunsafe_set_uint8buf(off+i)vdone;resletbigstring_to_stringv=letlen=bigstring_lengthvinletres=Bytes.createleninletlen0=lenland3inletlen1=lenasr2infori=0tolen1-1doleti=i*4inletv=unsafe_get_uint32viinbytes_unsafe_set_uint32resivdone;fori=0tolen0-1doleti=len1*4+iinletv=unsafe_get_uint8viinbytes_unsafe_set_uint8resivdone;Bytes.unsafe_to_stringresletoutput_bigstringocbufofflen=(* XXX(dinosaure): stupidly slow! *)letv=Bigarray.Array1.subbufoffleninletv=bigstring_to_stringvinoutput_stringocvletbigstring_of_stringv=letlen=String.lengthvinletres=bigstring_createleninletlen0=lenland3inletlen1=lenasr2infori=0tolen1-1doleti=i*4inletv=string_unsafe_get_uint32viinunsafe_set_uint32resivdone;fori=0tolen0-1doleti=len1*4+iinletv=string_unsafe_get_uint8viinunsafe_set_uint8resivdone;resletunsafe_get_uint16_be=ifSys.big_endianthenfunbufoff->unsafe_get_uint16bufoffelsefunbufoff->swap16(unsafe_get_uint16bufoff)letunsafe_set_uint16_be=ifSys.big_endianthenfunbufoffv->unsafe_set_uint16bufoffvelsefunbufoffv->unsafe_set_uint16bufoff(swap16v)letunsafe_get_uint32_be=ifSys.big_endianthenfunbufoff->unsafe_get_uint32bufoffelsefunbufoff->swap32(unsafe_get_uint32bufoff)letunsafe_get_uint32_le=ifSys.big_endianthenfunbufoff->swap32(unsafe_get_uint32bufoff)elsefunbufoff->unsafe_get_uint32bufoffletunsafe_set_uint32_be=ifSys.big_endianthenfunbufoffv->unsafe_set_uint32bufoffvelsefunbufoffv->unsafe_set_uint32bufoff(swap32v)letunsafe_set_uint32_le=ifSys.big_endianthenfunbufoffv->unsafe_set_uint32bufoff(swap32v)elsefunbufoffv->unsafe_set_uint32bufoffvletbytes_unsafe_set_uint16_be=ifSys.big_endianthenfunbufoffv->bytes_unsafe_set_uint16bufoffvelsefunbufoffv->bytes_unsafe_set_uint16bufoff(swap16v)letbytes_unsafe_set_uint32_be=ifSys.big_endianthenfunbufoffv->bytes_unsafe_set_uint32bufoffvelsefunbufoffv->bytes_unsafe_set_uint32bufoff(swap32v)letstring_unsafe_get_uint16_be=ifSys.big_endianthenfunbufoff->string_unsafe_get_uint16bufoffelsefunbufoff->swap16(string_unsafe_get_uint16bufoff)letinvalid_boundsofflen=invalid_arg"Out of bounds (off: %d, len: %d)"offlentypeos=|FAT|Amiga|VMS|Unix|VM|Atari|HPFS|Macintosh|Z|CPM|TOPS20|NTFS|QDOS|Acorn|Unknownletpp_string=Format.pp_print_stringletpp_osppf=function|FAT->pp_stringppf"FAT filesystem (MS-DOS, OS/2, NT/Win32)"|Amiga->pp_stringppf"Amiga"|VMS->pp_stringppf"VMS"|Unix->pp_stringppf"Unix"|VM->pp_stringppf"VM/CMS"|Atari->pp_stringppf"Atari TOS"|HPFS->pp_stringppf"HPFS filesystem (OS/2, NT)"|Macintosh->pp_stringppf"Macintosh"|Z->pp_stringppf"Z-System"|CPM->pp_stringppf"CP/M"|TOPS20->pp_stringppf"TOPS-20"|NTFS->pp_stringppf"NTFS filesysttem (NT)"|QDOS->pp_stringppf"QDOS"|Acorn->pp_stringppf"Acorn RISCOS"|Unknown->pp_stringppf"Unknown"letequal_osab=matcha,bwith|FAT,FAT|Amiga,Amiga|VMS,VMS|Unix,Unix|VM,VM|Atari,Atari|HPFS,HPFS|Macintosh,Macintosh|Z,Z|CPM,CPM|TOPS20,TOPS20|NTFS,NTFS|QDOS,QDOS|Acorn,Acorn|Unknown,Unknown->true|_,_->falseletos_to_int=function|FAT->0|Amiga->1|VMS->2|Unix->3|VM->4|Atari->5|HPFS->6|Macintosh->7|Z->8|CPM->9|TOPS20->10|NTFS->11|QDOS->12|Acorn->13|Unknown->255letos_of_int=function|0->FAT|1->Amiga|2->VMS|3->Unix|4->VM|5->Atari|6->HPFS|7->Macintosh|8->Z|9->CPM|10->TOPS20|11->NTFS|12->QDOS|13->Acorn|_->UnknownmoduleInf=structtypesrc=[`Channelofin_channel|`Stringofstring|`Manual]typedecoder={src:De.Inf.src;i:bigstring;i_pos:int;i_len:int;wr:optint;crc:optint;dd:dd;flg:int;cm:int;mtime:int32;xfl:int;os:int;fextra:stringoption;fname:stringoption;fcomment:stringoption;f:bool;t:bigstring;t_need:int;t_len:int;k:decoder->signal}anddd=|Ddof{state:De.Inf.decoder;window:De.window;o:De.bigstring}|Hdof{o:De.bigstring}andsignal=[`Awaitofdecoder|`Flushofdecoder|`Endofdecoder|`Malformedofstring]letmalformedffmt=kstrf(funs->`Malformeds)fmtleterr_unexpected_end_of_input_=malformedf"Unexpected end of input"leterr_invalid_checksumexpectd=malformedf"Invalid checksum (expect:%04lx, has:%04lx)"expect(Optint.to_int32d.crc)leterr_invalid_isizeexpectd=malformedf"Invalid input size (expect:%ld, inflated:%ld)"expect(Optint.to_int32d.wr)leterr_invalid_header_=malformedf"Invalid GZip header"leterr_invalid_header_crcd=malformedf"Invalid GZip header checksum"(* remaining bytes to read [d.i]. *)leti_remd=d.i_len-d.i_pos+1[@@inline](* End of input [eoi] is signalled by [d.i_pos = 0] and [d.i_len = min_int]
which implies [i_rem d < 0] is [true]. *)leteoid={dwithi=bigstring_empty;i_pos=0;i_len=min_int}letrefillkd=matchd.dd,d.srcwith|Dd{state;_},`String_->De.Inf.srcstatebigstring_empty00;k(eoid)|Dd{state;_},`Channelic->letres=input_bigstringicd.i0(bigstring_lengthd.i)inDe.Inf.srcstated.i0res;kd|(Dd_|Hd_),`Manual->`Await{dwithk}|Hd_,`String_->k(eoid)|Hd_,`Channelic->letres=input_bigstringicd.i0(bigstring_lengthd.i)inifres==0thenk(eoid)elsek{dwithi_pos=0;i_len=res-1}letflushkd=`Flush{dwithk}letblitsrc~src_offdst~dst_off~len=leta=Bigarray.Array1.subsrcsrc_offleninletb=Bigarray.Array1.subdstdst_offleninBigarray.Array1.blitabletrect_fillkd=letblitdlen=blitd.i~src_off:d.i_posd.t~dst_off:d.t_len~len;{dwithi_pos=d.i_pos+len;t_len=d.t_len+len}inletrem=i_remdinifrem<0thenerr_unexpected_end_of_inputdelseletneed=d.t_need-d.t_leninifrem<needthenletd=blitdreminrefill(t_fillk)delseletd=blitdneedink{dwitht_need=0}lett_neednd={dwitht_need=n}letchecksumd=letkd=matchd.ddwith|Dd{state;_}->letcrc=unsafe_get_uint32_led.t0inletisize=unsafe_get_uint32_led.t4inifOptint.to_int32d.crc=crc&&Optint.to_int32d.wr=isizethen`Enddelse(ifOptint.to_int32d.crc<>crcthenerr_invalid_checksumcrcdelseerr_invalid_isizeisized)|_->assertfalseint_fillk(t_need8d)letreczero_terminatedkd=letbuf=Buffer.create16inletrecgod=ifi_remd>=0thenleti_pos=refd.i_posinletchr=ref'\000'inwhiled.i_len-!i_pos+1>0&&(chr:=unsafe_get_chard.i!i_pos;!chr!='\000')doBuffer.add_charbuf!chr;incri_posdone;ifi_remd>0&&!chr!='\000'thenrefillgo{dwithi_pos=!i_pos}elsek(Some(Buffer.contentsbuf)){dwithi_pos=!i_pos+1(* + '\000' *)}elseerr_unexpected_end_of_inputdingodlettake_whilenkd=letbuf=Buffer.create16inletrecgond=ifi_remd>=0thenleti_pos=refd.i_posinletr_pos=refninwhiled.i_len-!i_pos+1>0&&!r_pos>0doBuffer.add_charbuf(unsafe_get_chard.i!i_pos);incri_pos;decrr_posdone;if!r_pos==0thenk(Buffer.contentsbuf){dwithi_pos=!i_pos}elserefill(go!r_pos){dwithi_pos=!i_pos}elseerr_unexpected_end_of_inputdingondletoption_apply~nonexf=matchxwith|Somex->fx|None->noneletzero=String.make1'\000'letoption_iterf=function|Somex->fx|None->()letstring_of_hdrd=lethdr=Bytes.create10inbytes_unsafe_set_uint16_behdr00x1f8b;bytes_unsafe_set_uint8hdr2d.cm;bytes_unsafe_set_uint8hdr3d.flg;bytes_unsafe_set_uint32_behdr4d.mtime;bytes_unsafe_set_uint8hdr8d.xfl;bytes_unsafe_set_uint8hdr9d.os;letres=Buffer.create16inBuffer.add_stringres(Bytes.unsafe_to_stringhdr);option_iter(funfname->Buffer.add_stringresfname;Buffer.add_charres'\000')d.fname;option_iter(funfcomment->Buffer.add_stringresfcomment;Buffer.add_charres'\000')d.fcomment;Buffer.contentsresletrecfhcrckd=letrecgod=ifi_remd>=2thenlethdr=string_of_hdrdinletcrc32=Checkseum.Crc32.defaultinletcrc32=Checkseum.Crc32.digest_stringhdr0(String.lengthhdr)crc32inletcrc16_0=Int32.(to_int(shift_right_logical(logand(Optint.to_int32crc32)0xFFFF0000l)16))inletcrc16_1=unsafe_get_uint16_bed.id.i_posinifcrc16_0!=crc16_1thenerr_invalid_header_crcdelsek{dwithi_pos=d.i_pos+2}elseifi_remd=0thenrefillgodelseerr_unexpected_end_of_inputdinifd.flgland0b10!=0thengodelsekdletfpayloadkd=let(>>=)kf=kfinletnoopvk=kvinletfiber:decoder->signal=(ifd.flgland0b01000!=0thenzero_terminatedelsenoopNone)>>=funfname->(ifd.flgland0b10000!=0thenzero_terminatedelsenoopNone)>>=funfcomment->(fund->k{dwithfname;fcomment;})infiberdletfextrakd=letrecgod=ifi_remd>0thenletlen=unsafe_get_uint16_bed.id.i_posintake_whilelen(funvd->k{dwithfextra=Somev}){dwithi_pos=d.i_pos+2}elseifi_remd=0thenrefillgodelseerr_unexpected_end_of_inputdingodletrecheaderd=letkd=let[@warning"-8"]Hd{o;}=d.ddinletkfinald=letwindow=De.make_window~bits:15inletstate=De.Inf.decoder`Manual~o~w:windowinletdd=Dd{state;window;o;}inDe.Inf.srcstated.id.i_pos(i_remd);decode{dwithk=decode;dd}inletid=unsafe_get_uint16_bed.id.i_posinifid!=0x1f8bthenerr_invalid_headerdelseletcm=unsafe_get_uint8d.i(d.i_pos+2)inletflg=unsafe_get_uint8d.i(d.i_pos+3)inletmtime=unsafe_get_uint32_bed.i(d.i_pos+4)inletxfl=unsafe_get_uint8d.i(d.i_pos+8)inletos=unsafe_get_uint8d.i(d.i_pos+9)inifflgland4!=0thenfextra(fpayload(fhcrckfinal)){dwithcm;flg;mtime;xfl;os;i_pos=d.i_pos+10}elsefpayload(fhcrckfinal){dwithcm;flg;mtime;xfl;os;i_pos=d.i_pos+10}inifi_remd>=10thenkdelse(ifi_remd<0thenerr_unexpected_end_of_inputdelserefilldecoded)anddecoded=matchd.ddwith|Hd_->headerd|Dd{state;o;_}->matchDe.Inf.decodestatewith|`Flush->ifd.fthenflushdecodedelseletlen=bigstring_lengtho-De.Inf.dst_remstateinletcrc=Checkseum.Crc32.digest_bigstringo0lend.crcinflushdecode{dwithwr=Optint.addd.wr(Optint.of_intlen);crc;f=true}|`Await->letlen=i_remd-De.Inf.src_remstateinrefilldecode{dwithi_pos=d.i_pos+len}|`End->ifd.fthenflushdecoded(* Do nothing! *)elseletlen=bigstring_lengtho-De.Inf.dst_remstateinletcrc=Checkseum.Crc32.digest_bigstringo0lend.crciniflen>0thenflushdecode{dwithi_pos=d.i_pos+(i_remd-De.Inf.src_remstate);wr=Optint.addd.wr(Optint.of_intlen);crc;f=true}elsechecksum{dwithi_pos=d.i_pos+(i_remd-De.Inf.src_remstate);k=checksum;crc}|`Malformederr->`Malformederrletsrcdsjl=if(j<0||l<0||j+l>bigstring_lengths)theninvalid_boundsjl;letd=if(l==0)theneoidelse{dwithi=s;i_pos=j;i_len=j+l-1}inmatchd.ddwith|Dd{state;_}->De.Inf.srcstatesjl;d|Hd_->dletflushd=matchd.ddwith|Hd_->{dwithf=false;}|Dd{state;_}->De.Inf.flushstate;{dwithf=false;}letdst_remd=matchd.ddwith|Hd_->invalid_arg"Invalid state to know bytes remaining"(* TODO(dinosaure): return [bigstring_length o]? *)|Dd{state;_}->De.Inf.dst_remstateletsrc_remd=i_remdletwrite{wr;_}=Optint.to_intwrletdecodersrc~o=leti,i_pos,i_len=matchsrcwith|`Manual->bigstring_empty,1,0|`Stringx->bigstring_of_stringx,0,String.lengthx-1|`Channel_->bigstring_createio_buffer_size,1,0in{i;i_pos;i_len;src;f=false;wr=Optint.zero;crc=Checkseum.Crc32.default;dd=Hd{o;};flg=0;cm=0;mtime=0l;xfl=0;os=0;fextra=None;fname=None;fcomment=None;t=bigstring_create8;t_need=0;t_len=0;k=decode}letresetd=leti,i_pos,i_len=matchd.srcwith|`Manual->bigstring_empty,1,0|`Stringx->bigstring_of_stringx,0,String.lengthx-1|`Channel_->bigstring_createio_buffer_size,1,0inleto=matchd.ddwith|Hd{o;}->o|Dd{o;_}->oin{i;i_pos;i_len;f=false;src=d.src;wr=Optint.zero;crc=Checkseum.Crc32.default;dd=Hd{o;};flg=0;cm=0;mtime=0l;xfl=0;os=0;fextra=None;fname=None;fcomment=None;t=bigstring_create8;t_need=0;t_len=0;k=decode}letdecoded=d.kdletfilename{fname;_}=fnameletcomment{fcomment;_}=fcommentletos{os;_}=os_of_intosletextra~key{fextra;_}=ifString.lengthkey<>2theninvalid_arg"Subfield ID must be 2 characters.";matchfextrawith|None->None|Somepayload->letrecgoaccidx=ifidx+2>String.lengthpayloadthenList.revaccelsetryletkey=String.subpayloadidx2inletlen=string_unsafe_get_uint16_bepayload(idx+2)inletres=String.subpayload(idx+4)leningo((key,res)::acc)(idx+4+len)with_->List.revaccinletextra=go[]0inmatchList.assockeyextrawith|v->Somev|exception_->NoneendmoduleDef=structtypesrc=[`Channelofin_channel|`Stringofstring|`Manual]typedst=[`Channelofout_channel|`BufferofBuffer.t|`Manual]typeencoder={src:src;dst:dst;i:bigstring;i_pos:int;i_len:int;o:bigstring;o_pos:int;o_len:int;rd:optint;crc:optint;q:De.Queue.t;s:De.Lz77.state;e:De.Def.encoder;w:De.window;state:state;flg:int;xfl:int;os:int;mtime:int32;fname:stringoption;fcomment:stringoption;k:encoder->[`Awaitofencoder|`Flushofencoder|`Endofencoder]}andstate=Hd|Ddtyperet=[`Awaitofencoder|`Endofencoder|`Flushofencoder]leto_reme=e.o_len-e.o_pos+1leti_rems=s.i_len-s.i_pos+1leteoie=De.Lz77.srce.sbigstring_empty00;{ewithi=bigstring_empty;i_pos=0;i_len=min_int}letsrcesjl=if(j<0||l<0||j+l>bigstring_lengths)theninvalid_boundsjl;De.Lz77.srce.ssjl;if(l==0)theneoieelseletcrc=Checkseum.Crc32.digest_bigstringsjle.crcinletrd=Optint.adde.rd(Optint.of_intl)in{ewithi=s;rd;crc;i_pos=j;i_len=j+l-1}letdstesjl=if(j<0||l<0||j+l>bigstring_lengths)theninvalid_boundsjl;((matche.statewith|Hd->()|Dd->De.Def.dste.esjl);{ewitho=s;o_pos=j;o_len=j+l-1})letrefillke=matche.srcwith|`String_->k(eoie)|`Channelic->letres=input_bigstringice.i0(bigstring_lengthe.i)ink(srcee.i0res)|`Manual->`Await{ewithk}letflushke=matche.dstwith|`Bufferb->letlen=bigstring_lengthe.o-o_remeinfori=0tolen-1doBuffer.add_charbe.o.{i}done;k(dstee.o0(bigstring_lengthe.o))|`Channeloc->output_bigstringoce.o0(bigstring_lengthe.o-o_reme);k(dstee.o0(bigstring_lengthe.o))|`Manual->`Flush{ewithk}letidentitye=`Endeletrecchecksume=letke=letchecksum=Optint.to_int32e.crcinletisize=Optint.to_int32e.rdinunsafe_set_uint32_lee.oe.o_poschecksum;unsafe_set_uint32_lee.o(e.o_pos+4)isize;flushidentity{ewitho_pos=e.o_pos+8}inifo_reme>=8thenkeelseflushchecksumeletmake_block?(last=false)e=iflast=falsethenletliterals=De.Lz77.literalse.sinletdistances=De.Lz77.distancese.sinletdynamic=De.Def.dynamic_of_frequencies~literals~distancesin{De.Def.kind=De.Def.Dynamicdynamic;last;}else{De.Def.kind=De.Def.Fixed;last;}letzero_terminatedstrkfinale=letpos=ref0inletrecke=letlen=min(String.lengthstr-!pos)(o_reme)infori=0tolen-1dounsafe_set_chare.o(e.o_pos+i)(String.getstr(!pos+i))done;pos:=!pos+len;if!pos==String.lengthstrthen(ifo_rem{ewitho_pos=e.o_pos+len}>0then(unsafe_set_uint8e.o(e.o_pos+len)0;kfinal{ewitho_pos=e.o_pos+len+1})elserefillk{ewitho_pos=e.o_pos+len})elserefillk{ewitho_pos=e.o_pos+len}inkeletoption_iterf=function|Somex->fx|None->()letstring_of_hdre=lethdr=Bytes.create10inbytes_unsafe_set_uint16_behdr00x1f8b;bytes_unsafe_set_uint8hdr28;bytes_unsafe_set_uint8hdr3e.flg;bytes_unsafe_set_uint32_behdr4e.mtime;bytes_unsafe_set_uint8hdr8e.xfl;bytes_unsafe_set_uint8hdr9e.os;letres=Buffer.create16inBuffer.add_stringres(Bytes.unsafe_to_stringhdr);option_iter(funfname->Buffer.add_stringresfname;Buffer.add_charres'\000')e.fname;option_iter(funfcomment->Buffer.add_stringresfcomment;Buffer.add_charres'\000')e.fcomment;Buffer.contentsresletrecfhcrce=letkfinale=ifi_reme>0thenDe.Lz77.srce.se.ie.i_pos(i_reme);(* XXX(dinosaure): we need to protect [e.s] against EOI signal. *)De.Def.dste.ee.oe.o_pos(o_reme);encode{ewithstate=Dd}inletrecgoe=ifo_reme>=2thenletcrc32=Checkseum.Crc32.defaultinlethdr=string_of_hdreinletcrc32=Checkseum.Crc32.digest_stringhdr0(String.lengthhdr)crc32inletcrc16=Int32.(to_int(shift_right_logical(logand(Optint.to_int32crc32)0xFFFF0000l)16))inunsafe_set_uint16_bee.oe.o_poscrc16;kfinal{ewitho_pos=e.o_pos+2}elseflushgoeinife.flgland0b10!=0thengoeelsekfinaleandencodee=matche.statewith|Hd->letke=unsafe_set_uint16_bee.oe.o_pos0x1f8b;unsafe_set_uint8e.o(e.o_pos+2)8;unsafe_set_uint8e.o(e.o_pos+3)e.flg;unsafe_set_uint32_bee.o(e.o_pos+4)e.mtime;unsafe_set_uint8e.o(e.o_pos+8)e.xfl;unsafe_set_uint8e.o(e.o_pos+9)e.os;letk=matche.fname,e.fcommentwith|Somefname,Somefcomment->zero_terminatedfname(zero_terminatedfcommentfhcrc)|Somefname,None->zero_terminatedfnamefhcrc|None,Somefcomment->zero_terminatedfcommentfhcrc|None,None->fhcrcink{ewitho_pos=e.o_pos+10}inifo_reme>=10thenkeelseflushencodee|Dd->letrecpartialke=ke(De.Def.encodee.e`Await)andcompresse=matchDe.Lz77.compresse.swith|`Await->refillcompress{ewithi_pos=e.i_pos+(i_reme-De.Lz77.src_reme.s)}|`Flush->encode_deflatee(De.Def.encodee.e`Flush)|`End->De.Queue.push_exne.qDe.Queue.eob;letblock=make_block~last:trueeintrailinge(De.Def.encodee.e(`Blockblock))andencode_deflatee=function|`Partial->letlen=o_reme-De.Def.dst_reme.einflush(partialencode_deflate){ewitho_pos=e.o_pos+len}|`Ok->compresse|`Block->letblock=make_blockeinencode_deflatee(De.Def.encodee.e(`Blockblock))andtrailinge=function|`Partial->letlen=o_reme-De.Def.dst_reme.einflush(partialtrailing){ewitho_pos=e.o_pos+len}|`Ok->letlen=o_reme-De.Def.dst_reme.einchecksum{ewitho_pos=e.o_pos+len}|`Block->assertfalseincompresseletsrc_rem=i_remletdst_rem=o_remletis_some=function|Some_->true|None->falseletflg~ascii~hcrc~extra~filename~comment=letflg=0b0lor(ifasciithen0b1else0b0)inletflg=flglor(ifhcrcthen0b10else0b0)inletflg=flglor(ifis_someextrathen0b100else0b0)inletflg=flglor(ifis_somefilenamethen0b1000else0b0)inletflg=flglor(ifis_somecommentthen0b10000else0b0)inflgletencodersrcdst?(ascii=false)?(hcrc=false)?filename?comment~mtimeos~q~w~level=leti,i_pos,i_len=matchsrcwith|`Manual->bigstring_empty,1,0|`Stringx->bigstring_of_stringx,0,String.lengthx-1|`Channel_->bigstring_createio_buffer_size,1,0inleto,o_pos,o_len=matchdstwith|`Manual->bigstring_empty,1,0|`Buffer_|`Channel_->bigstring_createio_buffer_size,0,io_buffer_size-1inletrd,crc=matchsrcwith|`Stringx->Optint.of_int(String.lengthx),Checkseum.Crc32.digest_stringx0(String.lengthx)Checkseum.Crc32.default|`Manual|`Channel_->Optint.zero,Checkseum.Crc32.defaultiniflevel<0||level>3theninvalid_arg"Invalid compression level %d (must be in the range 0...3)"level;letxfl=matchlevelwith|0|1->2|2|3->4|_->assertfalseinletflg=flg~ascii~hcrc~extra:None~filename~commentin{src;dst;i;i_pos;i_len;o;o_pos;o_len;rd;crc;e=De.Def.encoder`Manual~q;s=De.Lz77.state`Manual~q~w;q;w;state=Hd;xfl;flg;mtime;os=os_to_intos;fname=filename;fcomment=comment;k=encode}letencodee=e.keendmoduleHigher=structtype'tconfiguration={ascii:bool;hcrc:bool;os:os;mtime:'t->int32}letconfiguration?(ascii=false)?(hcrc=false)osmtime={ascii;hcrc;os;mtime;}letcompress?(level=0)?filename?comment~w~q~i~o~refill~flushtimeconfiguration=letencoder=Def.encoder`Manual`Manual~q~w~level~ascii:configuration.ascii~hcrc:configuration.hcrc~mtime:(configuration.mtimetime)configuration.osinletrecgoencoder=matchDef.encodeencoderwith|`Awaitencoder->letlen=refilliingo(Def.srcencoderi0len)|`Flushencoder->letlen=bigstring_lengtho-Def.dst_remencoderinflusholen;go(Def.dstencodero0(bigstring_lengtho))|`Endencoder->letlen=bigstring_lengtho-Def.dst_remencoderiniflen>0thenflusholeningo(Def.dstencodero0(bigstring_lengtho))typemetadata={filename:stringoption;comment:stringoption;os:os;extra:key:string->stringoption}letuncompress~i~o~refill~flush=letdecoder=Inf.decoder`Manual~oinletrecgodecoder=matchInf.decodedecoderwith|`Awaitdecoder->letlen=refilliingo(Inf.srcdecoderi0len)|`Flushdecoder->letlen=bigstring_lengtho-Inf.dst_remdecoderinflusholen;go(Inf.flushdecoder)|`Enddecoder->letlen=bigstring_lengtho-Inf.dst_remdecoderiniflen>0thenflusholen;Ok{filename=Inf.filenamedecoder;comment=Inf.commentdecoder;os=Inf.osdecoder;extra=Inf.extradecoder}|`Malformederr->Error(`Msgerr)ingodecoderend