1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465open!Coreopen!Importtypeoutput_chars=bigstring->len:int->unittypet={mutablebigstring_buf:Bigstring.t;output_char:char->unit;output_chars:output_chars;flush:unit->unit;sexp:unit->Sexp.t}[@@derivingfields]letsexp_of_tt=t.sexp()letinvariantt=Invariant.invariant[%here]t[%sexp_of:t](fun()->let_checkf=Invariant.check_fieldtfinFields.iter~bigstring_buf:ignore~output_char:ignore~output_chars:ignore~flush:ignore~sexp:ignore);;letcreate~output_char~output_chars~flush~sexp={bigstring_buf=Bigstring.create0;output_char;output_chars;flush;sexp};;letof_out_channelout_channel:t=letbytes_buf=Bytes.of_string""|>refincreate~output_char:(func->Out_channel.output_charout_channelc)~output_chars:(funbuf~len->iflen>Bytes.length!bytes_bufthenbytes_buf:=Bytes.create(len*2);Bigstring.To_bytes.blit~len~src:buf~src_pos:0~dst:!bytes_buf~dst_pos:0;Out_channel.outputout_channel~buf:!bytes_buf~pos:0~len)~flush:(fun()->Out_channel.flushout_channel)~sexp:(fun()->[%sexp{out_channel:Out_channel.t}]);;letof_output_charoutput_char:t=create~output_char~flush:Fn.id~sexp:(fun()->[%sexp()])~output_chars:(funbuf~len->fori=0tolen-1dooutput_charbuf.{i}done);;(* Implement the polymorphic [write_gen_* ~blit_to_string] API here rather than in every
abstraction. [create ~output_chars] is a simpler basis for this functionality with
very little cost in abstraction - it only gives up buffer management details. *)letoutputt~blit_to_bigstring~src~src_len~src_pos=ifsrc_len>Bigstring.lengtht.bigstring_bufthent.bigstring_buf<-Bigstring.create(src_len*2);blit_to_bigstring~src~src_pos~dst:t.bigstring_buf~dst_pos:0~len:src_len;t.output_charst.bigstring_buf~len:src_len;;letflusht=t.flush()