123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758(*
include String
let empty = ""
let of_string = copy
let to_string = copy
let sub_string = sub
let extend s left right =
let len = left + length s + right in
let result = create len in
let trim_left = max (- left) 0 in
unsafe_blit s trim_left result (max left 0)
(length s - trim_left - max (- right) 0);
result
let blit_string = blit
let cat = ( ^ )
let unsafe_of_string s = s
let unsafe_to_string s = s
let init n f =
let s = create n in
for i = 0 to n - 1 do
s.[i] <- f i
done;
s
let mapi f s =
init (length s) (fun i -> f i (unsafe_get s i))
*)(*
let iteri f s =
for i = 0 to length s - 1 do
f i (unsafe_get s i)
done
let map f s =
init (length s) (fun i -> f (unsafe_get s i))
let is_space = function
| ' ' | '\012' | '\n' | '\r' | '\t' -> true
| _ -> false
let rec rindex_no_space_from i s =
if i >= 0 && is_space (unsafe_get s i) then
rindex_no_space_from (pred i) s
else
i
let rec index_no_space_between i j s =
if i <= j && is_space (unsafe_get s i) then
index_no_space_between (succ i) j s
else
i
let trim s =
let off_end = rindex_no_space_from (length s - 1) s in
let off_start = index_no_space_between 0 off_end s in
if off_start > off_end then
""
else if off_start = 0 && off_end = length s - 1 then
s
else
sub s off_start (off_end - off_start + 1)
*)includeBytes(*
let index_opt s c =
Stdcompat__tools.option_find (index s) c
let rindex_opt s c =
Stdcompat__tools.option_find (rindex s) c
let index_from_opt s i c =
Stdcompat__tools.option_find (index_from s i) c
let rindex_from_opt s i c =
Stdcompat__tools.option_find (rindex_from s i) c
*)(*
let uppercase_ascii = uppercase
let lowercase_ascii = lowercase
let capitalize_ascii = capitalize
let uncapitalize_ascii = uncapitalize
let equal : t -> t -> bool = ( = )
*)(*
let of_seq g =
Stdcompat__buffer.to_bytes (Stdcompat__buffer.of_seq g)
let to_seq s = Stdcompat__tools.vec_to_seq length unsafe_get s
let to_seqi s = Stdcompat__tools.vec_to_seqi length unsafe_get s
*)(*
let pad_sign i w =
let pad_width = Stdcompat__sys.int_size - w in
(i lsl pad_width) asr pad_width
let index_out_of_bounds () =
invalid_arg "index out of bounds"
let unsafe_get_uint8 b i =
int_of_char (get b i)
let get_uint8 b i =
if i < 0 || i >= length b then
index_out_of_bounds ();
unsafe_get_uint8 b i
let get_int8 b i =
pad_sign (get_uint8 b i) 8
let unsafe_get_uint16_le b i =
let l = unsafe_get_uint8 b i in
let u = unsafe_get_uint8 b (succ i) in
l lor u lsl 8
let get_uint16_le b i =
if i < 0 || succ i >= length b then
index_out_of_bounds ();
unsafe_get_uint16_le b i
let unsafe_get_uint16_be b i =
let u = unsafe_get_uint8 b i in
let l = unsafe_get_uint8 b (succ i) in
l lor u lsl 8
let get_uint16_be b i =
if i < 0 || succ i >= length b then
index_out_of_bounds ();
unsafe_get_uint16_be b i
let get_uint16_ne b i =
if Stdcompat__sys.big_endian then get_uint16_be b i
else get_uint16_le b i
let get_int16_le b i =
pad_sign (get_uint16_le b i) 16
let get_int16_be b i =
pad_sign (get_uint16_be b i) 16
let get_int16_ne b i =
pad_sign (get_uint16_ne b i) 16
let get_int32_le b i =
if i < 0 || i + 3 >= length b then
index_out_of_bounds ();
let i0 = unsafe_get_uint8 b i in
let i1 = unsafe_get_uint8 b (i + 1) in
let i2 = unsafe_get_uint8 b (i + 2) in
let i3 = unsafe_get_uint8 b (i + 3) in
Int32.logor (Int32.of_int i0)
(Int32.logor (Int32.shift_left (Int32.of_int i1) 8)
(Int32.logor (Int32.shift_left (Int32.of_int i2) 16)
(Int32.shift_left (Int32.of_int i3) 24)))
let get_int32_be b i =
if i < 0 || i + 3 >= length b then
index_out_of_bounds ();
let i3 = unsafe_get_uint8 b i in
let i2 = unsafe_get_uint8 b (i + 1) in
let i1 = unsafe_get_uint8 b (i + 2) in
let i0 = unsafe_get_uint8 b (i + 3) in
Int32.logor (Int32.of_int i0)
(Int32.logor (Int32.shift_left (Int32.of_int i1) 8)
(Int32.logor (Int32.shift_left (Int32.of_int i2) 16)
(Int32.shift_left (Int32.of_int i3) 24)))
let get_int32_ne b i =
if Stdcompat__sys.big_endian then get_int32_be b i
else get_int32_le b i
let get_int64_le b i =
if i < 0 || i + 7 >= length b then
index_out_of_bounds ();
let i0 = unsafe_get_uint8 b i in
let i1 = unsafe_get_uint8 b (i + 1) in
let i2 = unsafe_get_uint8 b (i + 2) in
let i3 = unsafe_get_uint8 b (i + 3) in
let i4 = unsafe_get_uint8 b (i + 4) in
let i5 = unsafe_get_uint8 b (i + 5) in
let i6 = unsafe_get_uint8 b (i + 6) in
let i7 = unsafe_get_uint8 b (i + 7) in
Int64.logor (Int64.of_int i0)
(Int64.logor (Int64.shift_left (Int64.of_int i1) 8)
(Int64.logor (Int64.shift_left (Int64.of_int i2) 16)
(Int64.logor (Int64.shift_left (Int64.of_int i3) 24)
(Int64.logor (Int64.shift_left (Int64.of_int i4) 32)
(Int64.logor (Int64.shift_left (Int64.of_int i5) 40)
(Int64.logor (Int64.shift_left (Int64.of_int i6) 48)
(Int64.shift_left (Int64.of_int i7) 56)))))))
let get_int64_be b i =
if i < 0 || i + 7 >= length b then
index_out_of_bounds ();
let i7 = unsafe_get_uint8 b i in
let i6 = unsafe_get_uint8 b (i + 1) in
let i5 = unsafe_get_uint8 b (i + 2) in
let i4 = unsafe_get_uint8 b (i + 3) in
let i3 = unsafe_get_uint8 b (i + 4) in
let i2 = unsafe_get_uint8 b (i + 5) in
let i1 = unsafe_get_uint8 b (i + 6) in
let i0 = unsafe_get_uint8 b (i + 7) in
Int64.logor (Int64.of_int i0)
(Int64.logor (Int64.shift_left (Int64.of_int i1) 8)
(Int64.logor (Int64.shift_left (Int64.of_int i2) 16)
(Int64.logor (Int64.shift_left (Int64.of_int i3) 24)
(Int64.logor (Int64.shift_left (Int64.of_int i4) 32)
(Int64.logor (Int64.shift_left (Int64.of_int i5) 40)
(Int64.logor (Int64.shift_left (Int64.of_int i6) 48)
(Int64.shift_left (Int64.of_int i7) 56)))))))
let get_int64_ne b i =
if Stdcompat__sys.big_endian then get_int64_be b i
else get_int64_le b i
let unsafe_set_uint8 b i v =
unsafe_set b i (char_of_int (v land 0xFF))
let set_uint8 b i v =
if i < 0 || i >= length b then
index_out_of_bounds ();
unsafe_set_uint8 b i v
let set_int8 = set_uint8
let unsafe_set_uint16_le b i v =
unsafe_set_uint8 b i v;
unsafe_set_uint8 b (succ i) (v lsr 8)
let set_uint16_le b i v =
if i < 0 || succ i >= length b then
index_out_of_bounds ();
unsafe_set_uint16_le b i v
let unsafe_set_uint16_be b i v =
unsafe_set_uint8 b i (v lsr 8);
unsafe_set_uint8 b (succ i) v
let set_uint16_be b i v =
if i < 0 || succ i >= length b then
index_out_of_bounds ();
unsafe_set_uint16_be b i v
let set_uint16_ne b i v =
if Stdcompat__sys.big_endian then set_uint16_be b i v
else set_uint16_le b i v
let set_int16_le = set_uint16_le
let set_int16_be = set_uint16_be
let set_int16_ne = set_uint16_ne
let set_int32_le b i v =
if i < 0 || i + 3 >= length b then
index_out_of_bounds ();
unsafe_set_uint8 b i (Int32.to_int v);
unsafe_set_uint8 b (i + 1) (Int32.to_int (Int32.shift_right v 8));
unsafe_set_uint8 b (i + 2) (Int32.to_int (Int32.shift_right v 16));
unsafe_set_uint8 b (i + 3) (Int32.to_int (Int32.shift_right v 24))
let set_int32_be b i v =
if i < 0 || i + 3 >= length b then
index_out_of_bounds ();
unsafe_set_uint8 b i (Int32.to_int (Int32.shift_right v 24));
unsafe_set_uint8 b (i + 1) (Int32.to_int (Int32.shift_right v 16));
unsafe_set_uint8 b (i + 2) (Int32.to_int (Int32.shift_right v 8));
unsafe_set_uint8 b (i + 3) (Int32.to_int v)
let set_int32_ne b i v =
if Stdcompat__sys.big_endian then set_int32_be b i v
else set_int32_le b i v
let set_int64_le b i v =
if i < 0 || i + 7 >= length b then
index_out_of_bounds ();
unsafe_set_uint8 b i (Int64.to_int v);
unsafe_set_uint8 b (i + 1) (Int64.to_int (Int64.shift_right v 8));
unsafe_set_uint8 b (i + 2) (Int64.to_int (Int64.shift_right v 16));
unsafe_set_uint8 b (i + 3) (Int64.to_int (Int64.shift_right v 24));
unsafe_set_uint8 b (i + 4) (Int64.to_int (Int64.shift_right v 32));
unsafe_set_uint8 b (i + 5) (Int64.to_int (Int64.shift_right v 40));
unsafe_set_uint8 b (i + 6) (Int64.to_int (Int64.shift_right v 48));
unsafe_set_uint8 b (i + 7) (Int64.to_int (Int64.shift_right v 56))
let set_int64_be b i v =
if i < 0 || i + 7 >= length b then
index_out_of_bounds ();
unsafe_set_uint8 b i (Int64.to_int (Int64.shift_right v 56));
unsafe_set_uint8 b (i + 1) (Int64.to_int (Int64.shift_right v 48));
unsafe_set_uint8 b (i + 2) (Int64.to_int (Int64.shift_right v 40));
unsafe_set_uint8 b (i + 3) (Int64.to_int (Int64.shift_right v 32));
unsafe_set_uint8 b (i + 4) (Int64.to_int (Int64.shift_right v 24));
unsafe_set_uint8 b (i + 5) (Int64.to_int (Int64.shift_right v 16));
unsafe_set_uint8 b (i + 6) (Int64.to_int (Int64.shift_right v 8));
unsafe_set_uint8 b (i + 7) (Int64.to_int v)
let set_int64_ne b i v =
if Stdcompat__sys.big_endian then set_int64_be b i v
else set_int64_le b i v
*)externalunsafe_get_uint8:bytes->int->int="%bytes_unsafe_get"externalunsafe_get_uint16_ne:bytes->int->int="%caml_bytes_get16u"externalget_uint8:bytes->int->int="%bytes_safe_get"externalget_uint16_ne:bytes->int->int="%caml_bytes_get16"externalget_int32_ne:bytes->int->int32="%caml_bytes_get32"externalget_int64_ne:bytes->int->int64="%caml_bytes_get64"externalunsafe_set_uint8:bytes->int->int->unit="%bytes_unsafe_set"externalunsafe_set_uint16_ne:bytes->int->int->unit="%caml_bytes_set16u"externalset_int8:bytes->int->int->unit="%bytes_safe_set"externalset_int16_ne:bytes->int->int->unit="%caml_bytes_set16"externalset_int32_ne:bytes->int->int32->unit="%caml_bytes_set32"externalset_int64_ne:bytes->int->int64->unit="%caml_bytes_set64"externalswap16:int->int="%bswap16"letunsafe_get_uint16_lebi=ifSys.big_endianthenswap16(unsafe_get_uint16_nebi)elseunsafe_get_uint16_nebiletunsafe_get_uint16_bebi=ifSys.big_endianthenunsafe_get_uint16_nebielseswap16(unsafe_get_uint16_nebi)letunsafe_set_uint16_lebix=ifSys.big_endianthenunsafe_set_uint16_nebi(swap16x)elseunsafe_set_uint16_nebixletunsafe_set_uint16_bebix=ifSys.big_endianthenunsafe_set_uint16_nebixelseunsafe_set_uint16_nebi(swap16x)(*
external unsafe_blit_string :
string -> int -> bytes -> int -> int -> unit = "caml_blit_string"[@@noalloc]
(*
external unsafe_blit_string :
string -> int -> Stdcompat__init.bytes -> int -> int -> unit =
"caml_blit_string" "noalloc"
(*
external unsafe_blit_string :
string -> int -> Stdcompat__init.bytes -> int -> int -> unit =
"blit_string" "noalloc"
*)
*)
*)letrecfold_left_recfinitbytesi=ifi>=lengthbytestheninitelsefold_left_recf(finit(unsafe_getbytesi))bytes(succi)letfold_leftfinitbytes=fold_left_recfinitbytes0letrecfold_right_recfbytesiniti=ifi=0theninitelseletj=prediinfold_right_recfbytes(f(unsafe_getbytesj)init)jletfold_rightfbytesinit=fold_right_recfbytesinit(lengthbytes)letrecfor_all_recfbytesi=ifi>=lengthbytesthentrueelseiff(unsafe_getbytesi)thenfor_all_recfbytes(succi)elsefalseletfor_allfbytes=for_all_recfbytes0letrecexists_recfbytesi=ifi>=lengthbytesthenfalseelseiff(unsafe_getbytesi)thentrueelseexists_recfbytes(succi)letexistsfbytes=exists_recfbytes0letrecunsafe_sub_equalbytes0off0bytes1off1length=iflength=0thentrueelseifunsafe_getbytes0off0=unsafe_getbytes1off1thenunsafe_sub_equalbytes0(succoff0)bytes1(succoff1)(predlength)elsefalseletstarts_with~prefixbytes=lengthprefix<=lengthbytes&&unsafe_sub_equalbytes0prefix0(lengthprefix)letends_with~suffixbytes=lengthsuffix<=lengthbytes&&unsafe_sub_equalbytes(lengthbytes-lengthsuffix)suffix0(lengthsuffix)letsplit_on_charcs=letprevious_index=ref(lengths)inletaccu=ref[]infori=lengths-1downto0doifunsafe_getsi=cthenbeginaccu:=subs(i+1)(!previous_index-i-1)::!accu;previous_index:=ienddone;subs0!previous_index::!acculetdec_invalid=Stdcompat__uchar.utf_decode_invalidletdec_retnu=Stdcompat__uchar.utf_decoden(Stdcompat__uchar.unsafe_of_intu)(* In case of decoding error, if we error on the first byte, we
consume the byte, otherwise we consume the [n] bytes preceeding
the erroring byte.
This means that if a client uses decodes without caring about
validity it naturally replace bogus data with Stdcompat__uchar.rep according
to the WHATWG Encoding standard. Other schemes are possible by
consulting the number of used bytes on invalid decodes. For more
details see https://hsivonen.fi/broken-utf-8/
For this reason in [get_utf_8_uchar] we gradually check the next
byte is available rather than doing it immediately after the
first byte. Contrast with [is_valid_utf_8]. *)(* UTF-8 *)letnot_in_x80_to_xBFb=blsr6<>0b10letnot_in_xA0_to_xBFb=blsr5<>0b101letnot_in_x80_to_x9Fb=blsr5<>0b100letnot_in_x90_to_xBFb=b<0x90||0xBF<bletnot_in_x80_to_x8Fb=blsr4<>0x8letutf_8_uchar_2b0b1=((b0land0x1F)lsl6)lor((b1land0x3F))letutf_8_uchar_3b0b1b2=((b0land0x0F)lsl12)lor((b1land0x3F)lsl6)lor((b2land0x3F))letutf_8_uchar_4b0b1b2b3=((b0land0x07)lsl18)lor((b1land0x3F)lsl12)lor((b2land0x3F)lsl6)lor((b3land0x3F))letget_utf_8_ucharbi=letb0=get_uint8biin(* raises if [i] is not a valid index. *)letget=unsafe_get_uint8inletmax=lengthb-1inmatchChar.unsafe_chrb0with(* See The Unicode Standard, Table 3.7 *)|'\x00'..'\x7F'->dec_ret1b0|'\xC2'..'\xDF'->leti=i+1inifi>maxthendec_invalid1elseletb1=getbiinifnot_in_x80_to_xBFb1thendec_invalid1elsedec_ret2(utf_8_uchar_2b0b1)|'\xE0'->leti=i+1inifi>maxthendec_invalid1elseletb1=getbiinifnot_in_xA0_to_xBFb1thendec_invalid1elseleti=i+1inifi>maxthendec_invalid2elseletb2=getbiinifnot_in_x80_to_xBFb2thendec_invalid2elsedec_ret3(utf_8_uchar_3b0b1b2)|'\xE1'..'\xEC'|'\xEE'..'\xEF'->leti=i+1inifi>maxthendec_invalid1elseletb1=getbiinifnot_in_x80_to_xBFb1thendec_invalid1elseleti=i+1inifi>maxthendec_invalid2elseletb2=getbiinifnot_in_x80_to_xBFb2thendec_invalid2elsedec_ret3(utf_8_uchar_3b0b1b2)|'\xED'->leti=i+1inifi>maxthendec_invalid1elseletb1=getbiinifnot_in_x80_to_x9Fb1thendec_invalid1elseleti=i+1inifi>maxthendec_invalid2elseletb2=getbiinifnot_in_x80_to_xBFb2thendec_invalid2elsedec_ret3(utf_8_uchar_3b0b1b2)|'\xF0'->leti=i+1inifi>maxthendec_invalid1elseletb1=getbiinifnot_in_x90_to_xBFb1thendec_invalid1elseleti=i+1inifi>maxthendec_invalid2elseletb2=getbiinifnot_in_x80_to_xBFb2thendec_invalid2elseleti=i+1inifi>maxthendec_invalid3elseletb3=getbiinifnot_in_x80_to_xBFb3thendec_invalid3elsedec_ret4(utf_8_uchar_4b0b1b2b3)|'\xF1'..'\xF3'->leti=i+1inifi>maxthendec_invalid1elseletb1=getbiinifnot_in_x80_to_xBFb1thendec_invalid1elseleti=i+1inifi>maxthendec_invalid2elseletb2=getbiinifnot_in_x80_to_xBFb2thendec_invalid2elseleti=i+1inifi>maxthendec_invalid3elseletb3=getbiinifnot_in_x80_to_xBFb3thendec_invalid3elsedec_ret4(utf_8_uchar_4b0b1b2b3)|'\xF4'->leti=i+1inifi>maxthendec_invalid1elseletb1=getbiinifnot_in_x80_to_x8Fb1thendec_invalid1elseleti=i+1inifi>maxthendec_invalid2elseletb2=getbiinifnot_in_x80_to_xBFb2thendec_invalid2elseleti=i+1inifi>maxthendec_invalid3elseletb3=getbiinifnot_in_x80_to_xBFb3thendec_invalid3elsedec_ret4(utf_8_uchar_4b0b1b2b3)|_->dec_invalid1letset_utf_8_ucharbiu=letset=unsafe_set_uint8inletmax=lengthb-1inmatchStdcompat__uchar.to_intuwith|uwhenu<0->assertfalse|uwhenu<=0x007F->set_uint8biu;1|uwhenu<=0x07FF->letlast=i+1iniflast>maxthen0else(set_uint8bi(0xC0lor(ulsr6));setblast(0x80lor(uland0x3F));2)|uwhenu<=0xFFFF->letlast=i+2iniflast>maxthen0else(set_uint8bi(0xE0lor(ulsr12));setb(i+1)(0x80lor((ulsr6)land0x3F));setblast(0x80lor(uland0x3F));3)|uwhenu<=0x10FFFF->letlast=i+3iniflast>maxthen0else(set_uint8bi(0xF0lor(ulsr18));setb(i+1)(0x80lor((ulsr12)land0x3F));setb(i+2)(0x80lor((ulsr6)land0x3F));setblast(0x80lor(uland0x3F));4)|_->assertfalseletis_valid_utf_8b=letrecloopmaxbi=ifi>maxthentrueelseletget=unsafe_get_uint8inmatchChar.unsafe_chr(getbi)with|'\x00'..'\x7F'->loopmaxb(i+1)|'\xC2'..'\xDF'->letlast=i+1iniflast>max||not_in_x80_to_xBF(getblast)thenfalseelseloopmaxb(last+1)|'\xE0'->letlast=i+2iniflast>max||not_in_xA0_to_xBF(getb(i+1))||not_in_x80_to_xBF(getblast)thenfalseelseloopmaxb(last+1)|'\xE1'..'\xEC'|'\xEE'..'\xEF'->letlast=i+2iniflast>max||not_in_x80_to_xBF(getb(i+1))||not_in_x80_to_xBF(getblast)thenfalseelseloopmaxb(last+1)|'\xED'->letlast=i+2iniflast>max||not_in_x80_to_x9F(getb(i+1))||not_in_x80_to_xBF(getblast)thenfalseelseloopmaxb(last+1)|'\xF0'->letlast=i+3iniflast>max||not_in_x90_to_xBF(getb(i+1))||not_in_x80_to_xBF(getb(i+2))||not_in_x80_to_xBF(getblast)thenfalseelseloopmaxb(last+1)|'\xF1'..'\xF3'->letlast=i+3iniflast>max||not_in_x80_to_xBF(getb(i+1))||not_in_x80_to_xBF(getb(i+2))||not_in_x80_to_xBF(getblast)thenfalseelseloopmaxb(last+1)|'\xF4'->letlast=i+3iniflast>max||not_in_x80_to_x8F(getb(i+1))||not_in_x80_to_xBF(getb(i+2))||not_in_x80_to_xBF(getblast)thenfalseelseloopmaxb(last+1)|_->falseinloop(lengthb-1)b0(* UTF-16BE *)letget_utf_16be_ucharbi=letget=unsafe_get_uint16_beinletmax=lengthb-1inifi<0||i>maxtheninvalid_arg"index out of bounds"elseifi=maxthendec_invalid1elsematchgetbiwith|uwhenu<0xD800||u>0xDFFF->dec_ret2u|uwhenu>0xDBFF->dec_invalid2|hi->(* combine [hi] with a low surrogate *)letlast=i+3iniflast>maxthendec_invalid(max-i+1)elsematchgetb(i+2)with|uwhenu<0xDC00||u>0xDFFF->dec_invalid2(* retry here *)|lo->letu=(((hiland0x3FF)lsl10)lor(loland0x3FF))+0x10000indec_ret4uletset_utf_16be_ucharbiu=letset=unsafe_set_uint16_beinletmax=lengthb-1inifi<0||i>maxtheninvalid_arg"index out of bounds"elsematchStdcompat__uchar.to_intuwith|uwhenu<0->assertfalse|uwhenu<=0xFFFF->letlast=i+1iniflast>maxthen0else(setbiu;2)|uwhenu<=0x10FFFF->letlast=i+3iniflast>maxthen0elseletu'=u-0x10000inlethi=(0xD800lor(u'lsr10))inletlo=(0xDC00lor(u'land0x3FF))insetbihi;setb(i+2)lo;4|_->assertfalseletis_valid_utf_16beb=letrecloopmaxbi=letget=unsafe_get_uint16_beinifi>maxthentrueelseifi=maxthenfalseelsematchgetbiwith|uwhenu<0xD800||u>0xDFFF->loopmaxb(i+2)|uwhenu>0xDBFF->false|_hi->letlast=i+3iniflast>maxthenfalseelsematchgetb(i+2)with|uwhenu<0xDC00||u>0xDFFF->false|_lo->loopmaxb(i+4)inloop(lengthb-1)b0(* UTF-16LE *)letget_utf_16le_ucharbi=letget=unsafe_get_uint16_leinletmax=lengthb-1inifi<0||i>maxtheninvalid_arg"index out of bounds"elseifi=maxthendec_invalid1elsematchgetbiwith|uwhenu<0xD800||u>0xDFFF->dec_ret2u|uwhenu>0xDBFF->dec_invalid2|hi->(* combine [hi] with a low surrogate *)letlast=i+3iniflast>maxthendec_invalid(max-i+1)elsematchgetb(i+2)with|uwhenu<0xDC00||u>0xDFFF->dec_invalid2(* retry here *)|lo->letu=(((hiland0x3FF)lsl10)lor(loland0x3FF))+0x10000indec_ret4uletset_utf_16le_ucharbiu=letset=unsafe_set_uint16_leinletmax=lengthb-1inifi<0||i>maxtheninvalid_arg"index out of bounds"elsematchStdcompat__uchar.to_intuwith|uwhenu<0->assertfalse|uwhenu<=0xFFFF->letlast=i+1iniflast>maxthen0else(setbiu;2)|uwhenu<=0x10FFFF->letlast=i+3iniflast>maxthen0elseletu'=u-0x10000inlethi=(0xD800lor(u'lsr10))inletlo=(0xDC00lor(u'land0x3FF))insetbihi;setb(i+2)lo;4|_->assertfalseletis_valid_utf_16leb=letrecloopmaxbi=letget=unsafe_get_uint16_leinifi>maxthentrueelseifi=maxthenfalseelsematchgetbiwith|uwhenu<0xD800||u>0xDFFF->loopmaxb(i+2)|uwhenu>0xDBFF->false|_hi->letlast=i+3iniflast>maxthenfalseelsematchgetb(i+2)with|uwhenu<0xDC00||u>0xDFFF->false|_lo->loopmaxb(i+4)inloop(lengthb-1)b0letunsafe_escapeb=escapedb