12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152letreplace?(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,p2=Group.offsetsubstr0inifpos=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)