123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161(*----------------------------------------------------------------------------
* Copyright (c) 2019-2020 António Nuno Monteiro
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*---------------------------------------------------------------------------*)moduletypeRUNTIME=sigtypetvalnext_read_operation:t->[`Read|`Yield|`Close]valread:t->Bigstringaf.t->off:int->len:int->intvalread_eof:t->Bigstringaf.t->off:int->len:int->intvalyield_reader:t->(unit->unit)->unitvalnext_write_operation:t->[`WriteofBigstringaf.tFaraday.ioveclist|`Yield|`Closeofint]valreport_write_result:t->[`Okofint|`Closed]->unitvalyield_writer:t->(unit->unit)->unitvalreport_exn:t->exn->unitvalis_closed:t->boolvalshutdown:t->unitendtype'truntime=(moduleRUNTIMEwithtypet='t)typeimpl=Runtime:'truntime*'t->implletmakeruntimet=Runtime(runtime,t)moduleRuntime=structtypet={mutableconnection:impl}letcreate~protocolt'={connection=Runtime(protocol,t')}letupgrade_protocoltprotocol'=let{connection=Runtime((moduleP),t')}=tint.connection<-protocol';P.shutdownt'letnext_read_operation{connection=Runtime((moduleP),t)}=P.next_read_operationtletread{connection=Runtime((moduleP),t)}=P.readtletread_eof{connection=Runtime((moduleP),t)}=P.read_eoftletyield_reader{connection=Runtime((moduleP),t)}=P.yield_readertletnext_write_operation{connection=Runtime((moduleP),t)}=P.next_write_operationtletreport_write_result{connection=Runtime((moduleP),t)}=P.report_write_resulttletyield_writer{connection=Runtime((moduleP),t)}=P.yield_writertletreport_exn{connection=Runtime((moduleP),t)}=P.report_exntletshutdown{connection=Runtime((moduleP),t)}=P.shutdowntletis_closed{connection=Runtime((moduleP),t)}=P.is_closedtendmoduleReqd=structtype'reqdt={reqd:'reqd;upgrade:impl->unit}letcreatereqdupgrade={reqd;upgrade}endmoduleClient=RuntimemoduleServer=structincludeRuntimetype'reqdrequest_handler='reqdReqd.t->unitletcreate_upgradable:typet'reqd.protocol:t'runtime->create:((reqd->unit)->t')->reqdrequest_handler->t=fun~protocol~createrequest_handler->letrect=lazy{connection=Runtime(protocol,createrequest_handler')}andrequest_handler'reqd=letreqd'=Reqd.createreqd(upgrade_protocol(Lazy.forcet))inrequest_handlerreqd'inLazy.forcetendtype'reqdreqd='reqdReqd.t=private{reqd:'reqd;upgrade:impl->unit}moduleBuffer=structtypet={buffer:(char,Bigarray.int8_unsigned_elt,Bigarray.c_layout)Bigarray.Array1.t;mutableoff:int;mutablelen:int;cap:int}letcreatesize=letbuffer=Bigstringaf.createsizein{buffer;off=0;len=0;cap=size}letcompresst=ift.len=0then(t.off<-0;t.len<-0)elseift.off>0then(Bigstringaf.blitt.buffer~src_off:t.offt.buffer~dst_off:0~len:t.len;t.off<-0)letgett~f=letn=ft.buffer~off:t.off~len:t.lenint.off<-t.off+n;t.len<-t.len-n;ift.len=0thent.off<-0;nletputt~fk=compresst;letoff=t.off+t.leninletlen=t.cap-t.len-t.offinft.buffer~off~len(funn->t.len<-t.len+n;kn)end