123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162(*----------------------------------------------------------------------------
* Copyright (c) 2017 Inhabited Type LLC.
* Copyright (c) 2019 Antonio N. 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 author nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE 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 AUTHORS 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.
*---------------------------------------------------------------------------*)moduleWriter=Serialize.Writertype_t={faraday:Faraday.t;mutableread_scheduled:bool;mutableon_eof:unit->unit;mutableon_read:Bigstringaf.t->off:int->len:int->unit;buffered_bytes:intref;done_reading:int->unit;ready_to_write:unit->unit}letdefault_done_reading=Sys.opaque_identity(fun_->())letdefault_on_eof=Sys.opaque_identity(fun()->())letdefault_on_read=Sys.opaque_identity(fun_~off:_~len:_->())let_createbuffer~done_reading~ready_to_write={faraday=Faraday.of_bigstringbuffer;read_scheduled=false;on_eof=default_on_eof;on_read=default_on_read;buffered_bytes=ref0;done_reading;ready_to_write}letcreate_reader=_create~ready_to_write:ignoreletcreate_writer=_create~done_reading:default_done_readingletcreate_empty()=lett=create_readerBigstringaf.empty~done_reading:default_done_readinginFaraday.closet.faraday;tletempty=create_empty()letready_to_writet=t.ready_to_write()letwrite_chartc=Faraday.write_chart.faradayc;ready_to_writetletwrite_stringt?off?lens=Faraday.write_string?off?lent.faradays;ready_to_writetletwrite_bigstringt?off?lenb=Faraday.write_bigstring?off?lent.faradayb;ready_to_writetletschedule_bigstringt?off?len(b:Bigstringaf.t)=Faraday.schedule_bigstring?off?lent.faradayb;ready_to_writetletflushtkontinue=Faraday.flusht.faradaykontinue;ready_to_writetletis_closedt=Faraday.is_closedt.faradaylethas_pending_outputt=Faraday.has_pending_outputt.faradayletclose_writert=Faraday.closet.faraday;ready_to_writetletunsafe_faradayt=t.faradayletrecdo_execute_readton_eofon_read=matchFaraday.operationt.faradaywith|`Yield->()|`Close->t.read_scheduled<-false;t.on_eof<-default_on_eof;t.on_read<-default_on_read;on_eof()|`Writev[]->assertfalse|`Writev(iovec::_)->t.read_scheduled<-false;t.on_eof<-default_on_eof;t.on_read<-default_on_read;let{Httpaf.IOVec.buffer;off;len}=iovecinFaraday.shiftt.faradaylen;on_readbuffer~off~len;(* Application is done reading, we can give flow control tokens back to the
* peer. *)t.done_readinglen;execute_readtandexecute_readt=ift.read_scheduledthendo_execute_readtt.on_eoft.on_readletschedule_readt~on_eof~on_read=ift.read_scheduledthenfailwith"Body.schedule_read: reader already scheduled";ifis_closedtthendo_execute_readton_eofon_readelse(t.read_scheduled<-true;t.on_eof<-on_eof;t.on_read<-on_read)letclose_readert=Faraday.closet.faraday;execute_readtlettransfer_to_writertwriter~max_frame_size~max_bytesstream_id=letfaraday=t.faradayinmatchFaraday.operationfaradaywith|`Yield|`Close->0|`Writeviovecs->letbuffered=t.buffered_bytesinletiovecs=Httpaf.IOVec.shiftviovecs!bufferedinletlengthv=Httpaf.IOVec.lengthviovecsinletwritev_len=ifmax_bytes<lengthvthenmax_byteselselengthvinbuffered:=!buffered+writev_len;letframe_info=Writer.make_frame_info~max_frame_sizestream_idinWriter.schedule_iovecswriterframe_info~len:writev_leniovecs;Writer.flushwriter(fun()->Faraday.shiftfaradaywritev_len;buffered:=!buffered-writev_len);writev_len