1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253letreplace?(pos=0)?len?(all=true)re~fs=ifpos<0theninvalid_arg"Re.replace";letlimit=matchlenwith|None->String.lengths|Somel->ifl<0||pos+l>String.lengthstheninvalid_arg"Re.replace";pos+lin(* buffer into which we write the result *)letbuf=Buffer.create(String.lengths)in(* iterate on matched substrings. *)letreciterposon_match=ifpos<=limitthen(matchCompile.match_str~groups:true~partial:falseres~pos~len:(limit-pos)with|Matchsubstr->letp1=Group.start_offsetsubstr0|>Group.Offset.get_no_checkinletp2=Group.stop_offsetsubstr0|>Group.Offset.get_no_checkinifpos=p1&&p1=p2&&on_matchthen((* if we matched an empty string right after a match,
we must manually advance by 1 *)ifp2<limitthenBuffer.add_charbufs.[p2];iter(p2+1)false)else((* add string between previous match and current match *)Buffer.add_substringbufspos(p1-pos);(* what should we replace the matched group with? *)letreplacing=fsubstrinBuffer.add_stringbufreplacing;ifallthen(* if we matched an empty string, we must manually advance by 1 *)iter(ifp1=p2then((* a non char could be past the end of string. e.g. $ *)ifp2<limitthenBuffer.add_charbufs.[p2];p2+1)elsep2)(p1<>p2)elseBuffer.add_substringbufsp2(limit-p2))|Running_->()|Failed->Buffer.add_substringbufspos(limit-pos))initerposfalse;Buffer.contentsbuf;;letreplace_string?pos?len?allre~bys=replace?pos?len?allres~f:(fun_->by)