123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500(* Write_ml: writing values to the binary protocol using (mostly) OCaml. *)(* Note: the code is this file is carefully written to avoid unnecessary allocations. When
touching this code, be sure to run the benchmarks to check for regressions. *)openBigarrayopenCommontype'awriter=buf->pos:pos->'a->postype('a,'b)writer1='awriter->'bwritertype('a,'b,'c)writer2='awriter->('b,'c)writer1type('a,'b,'c,'d)writer3='awriter->('b,'c,'d)writer2externalunsafe_set:buf->int->char->unit="%caml_ba_unsafe_set_1"externalunsafe_set8:buf->int->int->unit="%caml_ba_unsafe_set_1"externalunsafe_set16:buf->int->int->unit="%caml_bigstring_set16u"externalunsafe_set32:buf->int->int32->unit="%caml_bigstring_set32u"externalunsafe_set64:buf->int->int64->unit="%caml_bigstring_set64u"externalbswap16:int->int="%bswap16"externalbswap32:int32->int32="%bswap_int32"externalbswap64:int64->int64="%bswap_int64"(*$ open Bin_prot_cinaps $*)letcode_NEG_INT8=(*$ Code.char NEG_INT8 *)'\xff'(*$*)letcode_INT16=(*$ Code.char INT16 *)'\xfe'(*$*)letcode_INT32=(*$ Code.char INT32 *)'\xfd'(*$*)letcode_INT64=(*$ Code.char INT64 *)'\xfc'(*$*)letarch_sixtyfour=Sys.word_size=64letarch_big_endian=Sys.big_endianletunsafe_set16be=ifarch_big_endianthenunsafe_set16elsefunbufposx->unsafe_set16bufpos(bswap16x);;letunsafe_set32be=ifarch_big_endianthenunsafe_set32elsefunbufposx->unsafe_set32bufpos(bswap32x);;letunsafe_set64be=ifarch_big_endianthenunsafe_set64elsefunbufposx->unsafe_set64bufpos(bswap64x);;letunsafe_set16le=ifarch_big_endianthenfunbufposx->unsafe_set16bufpos(bswap16x)elseunsafe_set16;;letunsafe_set32le=ifarch_big_endianthenfunbufposx->unsafe_set32bufpos(bswap32x)elseunsafe_set32;;letunsafe_set64le=ifarch_big_endianthenfunbufposx->unsafe_set64bufpos(bswap64x)elseunsafe_set64;;letbin_write_unitbuf~pos()=assert_pospos;check_posbufpos;unsafe_setbufpos'\000';pos+1;;letbin_write_boolbuf~posb=assert_pospos;check_posbufpos;unsafe_setbufpos(ifbthen'\001'else'\000');pos+1;;letall_bin_write_small_intbufposn=check_posbufpos;unsafe_set8bufposn;pos+1;;letall_bin_write_neg_int8bufposn=letnext=pos+2incheck_nextbufnext;unsafe_setbufposcode_NEG_INT8;unsafe_set8buf(pos+1)n;next;;letall_bin_write_int16bufposn=letnext=pos+3incheck_nextbufnext;unsafe_setbufposcode_INT16;unsafe_set16lebuf(pos+1)n;next;;letall_bin_write_int32bufposn=letnext=pos+5incheck_nextbufnext;unsafe_setbufposcode_INT32;unsafe_set32lebuf(pos+1)n;next[@@inline];;letall_bin_write_int64bufposn=letnext=pos+9incheck_nextbufnext;unsafe_setbufposcode_INT64;unsafe_set64lebuf(pos+1)n;next[@@inline];;letbin_write_charbuf~posc=assert_pospos;check_posbufpos;unsafe_setbufposc;pos+1;;letbin_write_intbuf~posn=assert_pospos;ifn>=0thenifn<0x00000080thenall_bin_write_small_intbufposnelseifn<0x00008000thenall_bin_write_int16bufposnelseifarch_sixtyfour&&n>=1lsl31thenall_bin_write_int64bufpos(Int64.of_intn)elseall_bin_write_int32bufpos(Int32.of_intn)elseifn>=-0x00000080thenall_bin_write_neg_int8bufposnelseifn>=-0x00008000thenall_bin_write_int16bufposnelseifarch_sixtyfour&&n<-(1lsl31)thenall_bin_write_int64bufpos(Int64.of_intn)elseall_bin_write_int32bufpos(Int32.of_intn);;letbin_write_nat0buf~posnat0=assert_pospos;letn=(nat0:Nat0.t:>int)inifn<0x00000080thenall_bin_write_small_intbufposnelseifn<0x00010000thenall_bin_write_int16bufposnelseifarch_sixtyfour&&n>=1lsl32thenall_bin_write_int64bufpos(Int64.of_intn)elseall_bin_write_int32bufpos(Int32.of_intn);;letbin_write_stringbuf~posstr=letlen=String.lengthstrinletplen=Nat0.unsafe_of_intleninletnew_pos=bin_write_nat0buf~pospleninletnext=new_pos+lenincheck_nextbufnext;(* TODO: optimize for small strings *)unsafe_blit_string_buf~src_pos:0str~dst_pos:new_posbuf~len;next;;letbin_write_bytesbuf~posstr=letlen=Bytes.lengthstrinletplen=Nat0.unsafe_of_intleninletnew_pos=bin_write_nat0buf~pospleninletnext=new_pos+lenincheck_nextbufnext;(* TODO: optimize for small bytes *)unsafe_blit_bytes_buf~src_pos:0str~dst_pos:new_posbuf~len;next;;letbin_write_floatbuf~posx=assert_pospos;letnext=pos+8incheck_nextbufnext;unsafe_set64lebufpos(Int64.bits_of_floatx);next[@@inline];;letbin_write_int32=ifarch_sixtyfourthenfun[@inline]buf~posn->bin_write_intbuf~pos(Int32.to_intn)elsefun[@inline]buf~posn->ifn>=0x00008000l||n<-0x00008000lthen(assert_pospos;all_bin_write_int32bufposn)elsebin_write_intbuf~pos(Int32.to_intn);;letbin_write_int64buf~posn=ifn>=0x80000000L||n<-0x80000000Lthen(assert_pospos;all_bin_write_int64bufposn)elseifarch_sixtyfourthenbin_write_intbuf~pos(Int64.to_intn)elseifn>=0x00008000L||n<-0x00008000Lthen(assert_pospos;all_bin_write_int32bufpos(Int64.to_int32n))elsebin_write_intbuf~pos(Int64.to_intn)[@@inline];;letbin_write_nativeintbuf~posn=ifarch_sixtyfour&&(n>=(* 0x80000000n *)Nativeint.shift_left1n31||n<(* -0x80000000n *)Nativeint.neg(Nativeint.shift_left1n31))then(assert_pospos;all_bin_write_int64bufpos(Int64.of_nativeintn))elseif((notarch_sixtyfour)&&n>=0x8000n)||n<-0x8000nthen(assert_pospos;all_bin_write_int32bufpos(Nativeint.to_int32n))elsebin_write_intbuf~pos(Nativeint.to_intn)[@@inline];;letbin_write_refbin_write_elbuf~posr=bin_write_elbuf~pos!rletbin_write_lazybin_write_elbuf~poslv=letv=Lazy.forcelvinbin_write_elbuf~posv;;letbin_write_optionbin_write_elbuf~pos=function|None->bin_write_boolbuf~posfalse|Somev->letnext=bin_write_boolbuf~postrueinbin_write_elbuf~pos:nextv;;letbin_write_pairbin_write_abin_write_bbuf~pos(a,b)=letnext=bin_write_abuf~posainbin_write_bbuf~pos:nextb;;letbin_write_triplebin_write_abin_write_bbin_write_cbuf~pos(a,b,c)=letnext1=bin_write_abuf~posainletnext2=bin_write_bbuf~pos:next1binbin_write_cbuf~pos:next2c;;letbin_write_listbin_write_elbuf~poslst=letrecloopels_pos=function|[]->els_pos|h::t->letnew_els_pos=bin_write_elbuf~pos:els_poshinloopnew_els_postinletlen=Nat0.unsafe_of_int(List.lengthlst)inletels_pos=bin_write_nat0buf~posleninloopels_poslst;;letbin_write_float_arraybuf~posa=letlen=Array.lengthainletplen=Nat0.unsafe_of_intleninletpos=bin_write_nat0buf~pospleninletsize=len*8inletnext=pos+sizeincheck_nextbufnext;unsafe_blit_float_array_bufabuf~src_pos:0~dst_pos:pos~len;next;;letbin_write_array_loopbin_write_elbuf~els_pos~nar=letels_pos_ref=refels_posinfori=0ton-1doels_pos_ref:=bin_write_elbuf~pos:!els_pos_ref(Array.unsafe_getari)done;!els_pos_ref;;letbin_write_array(typea)bin_write_elbuf~posar=if(Obj.magic(bin_write_el:awriter):floatwriter)==bin_write_floatthenbin_write_float_arraybuf~pos(Obj.magic(ar:aarray):floatarray)else(letn=Array.lengtharinletpn=Nat0.unsafe_of_intninletels_pos=bin_write_nat0buf~pospninbin_write_array_loopbin_write_elbuf~els_pos~nar);;letbin_write_hashtblbin_write_keybin_write_valbuf~poshtbl=letlen=Hashtbl.lengthhtblinletplen=Nat0.unsafe_of_intleninletels_pos=bin_write_nat0buf~pospleninletcnt_ref=ref0inletcoll_htblkvels_pos=incrcnt_ref;letnew_els_pos=bin_write_keybuf~pos:els_poskinbin_write_valbuf~pos:new_els_posvinletres_pos=Hashtbl.foldcoll_htblhtblels_posinif!cnt_ref<>lenthenraise_concurrent_modification"bin_write_hashtbl";res_pos;;externalbuf_of_vec32:vec32->buf="%identity"externalbuf_of_vec64:vec64->buf="%identity"externalbuf_of_mat32:mat32->buf="%identity"externalbuf_of_mat64:mat64->buf="%identity"letbin_write_float32_vecbuf~posv=letlen=Array1.dimvinletplen=Nat0.unsafe_of_intleninletpos=bin_write_nat0buf~pospleninletsize=len*4inletnext=pos+sizeincheck_nextbufnext;unsafe_blit_buf~src:(buf_of_vec32v)~src_pos:0~dst:buf~dst_pos:pos~len:size;next;;letbin_write_float64_vecbuf~posv=letlen=Array1.dimvinletplen=Nat0.unsafe_of_intleninletpos=bin_write_nat0buf~pospleninletsize=len*8inletnext=pos+sizeincheck_nextbufnext;unsafe_blit_buf~src:(buf_of_vec64v)~src_pos:0~dst:buf~dst_pos:pos~len:size;next;;letbin_write_vec=bin_write_float64_vecletbin_write_float32_matbuf~posm=letlen1=Array2.dim1minletlen2=Array2.dim2minletpos=bin_write_nat0buf~pos(Nat0.unsafe_of_intlen1)inletpos=bin_write_nat0buf~pos(Nat0.unsafe_of_intlen2)inletsize=len1*len2*4inletnext=pos+sizeincheck_nextbufnext;unsafe_blit_buf~src:(buf_of_mat32m)~src_pos:0~dst:buf~dst_pos:pos~len:size;next;;letbin_write_float64_matbuf~posm=letlen1=Array2.dim1minletlen2=Array2.dim2minletpos=bin_write_nat0buf~pos(Nat0.unsafe_of_intlen1)inletpos=bin_write_nat0buf~pos(Nat0.unsafe_of_intlen2)inletsize=len1*len2*8inletnext=pos+sizeincheck_nextbufnext;unsafe_blit_buf~src:(buf_of_mat64m)~src_pos:0~dst:buf~dst_pos:pos~len:size;next;;letbin_write_mat=bin_write_float64_matletbin_write_bigstringbuf~poss=letlen=Array1.dimsinletplen=Nat0.unsafe_of_intleninletpos=bin_write_nat0buf~pospleninletnext=pos+lenincheck_nextbufnext;unsafe_blit_buf~src:s~src_pos:0~dst:buf~dst_pos:pos~len;next;;letbin_write_variant_intbuf~posx=assert_pospos;letnext=pos+4incheck_nextbufnext;unsafe_set32lebufpos(Int32.logor(Int32.shift_left(Int32.of_intx)1)1l);next;;letbin_write_int_8bitbuf~posn=assert_pospos;check_posbufpos;unsafe_set8bufposn;pos+1;;letbin_write_int_16bitbuf~posn=assert_pospos;letnext=pos+2incheck_nextbufnext;unsafe_set16lebufposn;next;;letbin_write_int_32bitbuf~posn=assert_pospos;letnext=pos+4incheck_nextbufnext;unsafe_set32lebufpos(Int32.of_intn);next;;letbin_write_int_64bitbuf~posn=assert_pospos;letnext=pos+8incheck_nextbufnext;unsafe_set64lebufpos(Int64.of_intn);next;;letbin_write_int64_bitsbuf~posn=assert_pospos;letnext=pos+8incheck_nextbufnext;unsafe_set64lebufposn;next;;letbin_write_network16_intbuf~posn=assert_pospos;letnext=pos+2incheck_nextbufnext;unsafe_set16bebufposn;next;;letbin_write_network32_intbuf~posn=assert_pospos;letnext=pos+4incheck_nextbufnext;unsafe_set32bebufpos(Int32.of_intn);next;;letbin_write_network32_int32buf~posn=assert_pospos;letnext=pos+4incheck_nextbufnext;unsafe_set32bebufposn;next;;letbin_write_network64_intbuf~posn=assert_pospos;letnext=pos+8incheck_nextbufnext;unsafe_set64bebufpos(Int64.of_intn);next;;letbin_write_network64_int64buf~posn=assert_pospos;letnext=pos+8incheck_nextbufnext;unsafe_set64bebufposn;next;;letbin_write_array_no_lengthbin_write_elbuf~posar=bin_write_array_loopbin_write_elbuf~els_pos:pos~n:(Array.lengthar)ar;;externalunsafe_string_get32:string->int->int32="%caml_string_get32u"externalunsafe_string_get64:string->int->int64="%caml_string_get64u"letbin_write_md5buf~posx=letx=Md5_lib.to_binaryxinassert(String.lengthx=16);assert_pospos;letnext=pos+16incheck_nextbufnext;ifarch_sixtyfourthen(leta=unsafe_string_get64x0inletb=unsafe_string_get64x8inunsafe_set64bufposa;unsafe_set64buf(pos+8)b)else(leta=unsafe_string_get32x0inletb=unsafe_string_get32x4inletc=unsafe_string_get32x8inletd=unsafe_string_get32x12inunsafe_set32bufposa;unsafe_set32buf(pos+4)b;unsafe_set32buf(pos+8)c;unsafe_set32buf(pos+12)d);next;;