diff --git a/quest/m3/README.md b/quest/m3/README.md index 43276607c..7ab70819d 100644 --- a/quest/m3/README.md +++ b/quest/m3/README.md @@ -38,7 +38,6 @@ generic std gap is planned here even when moq never calls it. - [A vector's exact capacity as it shrinks](/quest/m3/ts-vec-exact-capacity.md) - a deque made from a `Vec` splits its slices where std's does - [A B-tree's searches call Ord as std's do](/quest/m3/ts-btree-search-order.md) - a B-tree's lookups and inserts call a key's own `Ord` in std's order and number - [Rc and Arc of a slice](/quest/m3/ts-shared-slices.md) - `Rc<[T]>` and `Arc<[T]>` from a `Vec`, a slice, or an iterator translate -- [The rest of str's searches](/quest/m3/ts-str-searches.md) - `find`, `strip_prefix`, `replace`, `rsplit`, `splitn`, `matches`, `lines`, and the rest of `str`'s searches translate - [Adding to a String](/quest/m3/ts-string-add.md) - `String + &str` translates as `+=` does - [The rest of a vector's methods](/quest/m3/ts-vec-rest.md) - `append`, `resize`, `split_off`, `try_reserve`, and `Vec::from(VecDeque)` translate - [A reversed zip's per-pair cost](/quest/m3/ts-zip-rev-overhead.md) - a reversed by-index zip costs per pair what a forward one does, or the gap is explained diff --git a/quest/m3/ts-str-searches.md b/quest/m3/ts-str-searches.md deleted file mode 100644 index 380ea2524..000000000 --- a/quest/m3/ts-str-searches.md +++ /dev/null @@ -1,24 +0,0 @@ -# [M] The rest of str's searches - -## Goal - -[rust2-ts](/ts/README.md) translates `str`'s pattern searches and text iterators still -refused, each by every pattern std takes, searching in std's order from each end, proven by -differential tests against native Rust. - -## Plan - -Found translating the [std calls moq's main added to the model](https://github.com/moq-dev/rust2/pull/434), -by a census of a crate calling each by a `char`. These refuse as unsupported calls: - -- `find`, `strip_prefix`, `strip_suffix`, `trim_matches`, and `replace`; -- the iterators `rsplit`, `rsplit_terminator`, `splitn`, `rsplitn`, `split_inclusive`, - `matches`, `rmatches`, and `rmatch_indices`; -- `char_indices`, `lines`, and `split_whitespace`. - -The runtime's `Searcher` in `rt/str.ts` already searches from both ends and `Split` holds -std's `allow_trailing_empty`, so most map onto them as `split`, `split_terminator`, and -`rsplit_once` do. A predicate's calls are visible, so each must call it on the chars std's -does, in order. No consumer calls them yet; they are planned here as part of std. - -Public API: the translator's output. diff --git a/ts/fixtures/lang/caller.ts b/ts/fixtures/lang/caller.ts index 102771c8d..b403579a5 100644 --- a/ts/fixtures/lang/caller.ts +++ b/ts/fixtures/lang/caller.ts @@ -952,4 +952,27 @@ const sortCases = [ ...Array.from({ length: 20 * 5 }, (_, i) => Uint8Array.of(...op("sorts::btrees"), i % 20, Math.floor(i / 20), 2, 9)), ]; -export const cases: Uint8Array[] = [...loops, ...durations, ...ints(), ...utf8, ...floats, ...formats, ...parsed, ...singlesCases, ...singlesFormats, ...singlesParsed, ...dyns, ...cells, ...shared, ...locks, ...guards, ...maps, ...mappedLocks, ...relocks, ...tries, ...mutexMaps, ...printed, ...downgrades, ...leaks, ...placeCompares, ...rwlocks, ...onces, ...bounds, ...unsafeCells, ...edits, ...subslices, ...consumers, ...closures, ...elements, ...ranges, ...reducers, ...sliceEdits, ...drains, ...iters, ...splitEnds, ...dequeRanges, ...hinted, ...peekedOthers, ...hints, ...reserves, ...setOps, ...zeros, ...writes, ...floatsMulAdds, ...singlesMulAdds, ...unlikeEqs, ...ownNes, ...rangeFroms, ...compares, ...unlikeCompares, ...rangeMethods, ...wraps(), ...refOrders, ...saturates(), ...methods(), ...separated, ...asciiCases, ...gets, ...capacityCases, ...ringsCases, ...remadeCases, ...sortCases, ...endsCases]; +/** + * `searches::searches` of each search and pattern, by chars, needles, and counts its first + * byte picks: an empty needle, one, two, and three chars, and counts from 0 to 4. Of no + * text, a separator alone, twice, and at either end, runs a two-char needle overlaps in, + * chars of each UTF-8 width, and digits the closure matches, read from either end. + */ +const searchesOp = op("searches::searches"); +const searchesCases = [0x00, 0x12, 0x22, 0x31, 0x4e, 0x57].flatMap((pick) => + [[], [0], [0, 0], [0, 2], [2, 0], [0, 2, 0], [2, 2, 2], [2, 2, 2, 2], [14, 7, 14], [0x80, 2, 0x80], [0x82, 0x8e, 0x07, 0x83]].flatMap((text) => + Array.from({ length: 85 }, (_, kind) => Uint8Array.of(...searchesOp, kind, pick, ...text)), + ), +); + +/** + * `searches::texts` of each iterator and the trims, of no text, a line end of each kind + * alone, between lines and doubled, a `\r` without a `\n`, and whitespace of each UTF-8 + * width between the chars JS's `\s` alone counts, read from either end. + */ +const textsOp = op("searches::texts"); +const textsCases = [[], [0], [1, 0], [2, 1, 0, 2], [2, 0, 0, 2], [0, 2], [2, 1], [1, 1, 0], [3, 2, 3], [6, 7, 8, 9, 2, 10, 2, 11, 12, 13, 2, 14, 15, 4, 5], [0x83, 2, 0x8d, 0x0a, 0x84]].flatMap( + (text) => Array.from({ length: 4 }, (_, kind) => Uint8Array.of(...textsOp, kind, ...text)), +); + +export const cases: Uint8Array[] = [...loops, ...durations, ...ints(), ...utf8, ...floats, ...formats, ...parsed, ...singlesCases, ...singlesFormats, ...singlesParsed, ...dyns, ...cells, ...shared, ...locks, ...guards, ...maps, ...mappedLocks, ...relocks, ...tries, ...mutexMaps, ...printed, ...downgrades, ...leaks, ...placeCompares, ...rwlocks, ...onces, ...bounds, ...unsafeCells, ...edits, ...subslices, ...consumers, ...closures, ...elements, ...ranges, ...reducers, ...sliceEdits, ...drains, ...iters, ...splitEnds, ...dequeRanges, ...hinted, ...peekedOthers, ...hints, ...reserves, ...setOps, ...zeros, ...writes, ...floatsMulAdds, ...singlesMulAdds, ...unlikeEqs, ...ownNes, ...rangeFroms, ...compares, ...unlikeCompares, ...rangeMethods, ...wraps(), ...refOrders, ...saturates(), ...methods(), ...separated, ...asciiCases, ...gets, ...capacityCases, ...ringsCases, ...remadeCases, ...sortCases, ...endsCases, ...searchesCases, ...textsCases]; diff --git a/ts/fixtures/lang/expected/harness.ts b/ts/fixtures/lang/expected/harness.ts index 281ec6ef6..8b91942a9 100644 --- a/ts/fixtures/lang/expected/harness.ts +++ b/ts/fixtures/lang/expected/harness.ts @@ -55,6 +55,7 @@ import { results as results_results } from "./results.ts"; import { returns } from "./returns.ts"; import { slices as rings_slices } from "./rings.ts"; import { u8s as saturates_u8s, u16s as saturates_u16s, u32s as saturates_u32s, u64s as saturates_u64s, u128s as saturates_u128s, usizes as saturates_usizes, i8s as saturates_i8s, i16s as saturates_i16s, i32s as saturates_i32s, i64s as saturates_i64s, i128s as saturates_i128s, isizes as saturates_isizes } from "./saturates.ts"; +import { searches, texts } from "./searches.ts"; import { separated } from "./separated.ts"; import { copies as shapes_copies, order as shapes_order, discriminants, loops, patterns, uninhabited, closures as shapes_closures, library, flows } from "./shapes.ts"; import { singles, mulAdds as singles_mulAdds, formats as singles_formats, parses as singles_parses } from "./singles.ts"; @@ -324,7 +325,7 @@ export function cases(): [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) sorts_btrees(a0165, a1165.data, a1165.start, a1165.length, a2165); }] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["dyns::pointers", (_2212: rt.u8, data112: rt.ByteSlice, out113: rt.ByteVec): undefined => { pointers(data112.data, data112.start, data112.length, out113); - }] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined]]; + }] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["searches::searches", searches as (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["searches::texts", texts as (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined]]; } /** Run one case. */ diff --git a/ts/fixtures/lang/expected/searches.ts b/ts/fixtures/lang/expected/searches.ts new file mode 100644 index 000000000..38131d108 --- /dev/null +++ b/ts/fixtures/lang/expected/searches.ts @@ -0,0 +1,3884 @@ +// Generated by rust2-ts. Do not edit. + +import * as rt from "./rt.ts"; +import { mapOr$1ttssgs as option_mapOr$1ttssgs } from "./core/option.ts"; +import { put as fmt_put } from "./fmt.ts"; +import { text as strs_text } from "./strs.ts"; + +export function put$searches_Item_ref_str(self: string, out: rt.ByteVec): void { + fmt_put(out, self); +} + +export function put$searches_Item_tuple2_usize_ref_str(self: [rt.usize, string], out: rt.ByteVec): void { + rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.u32ToBeBytes(self[0] as rt.u32))); + fmt_put(out, self[1]); +} + +export function put$searches_Item_tuple2_usize_char(self: [rt.usize, rt.char], out: rt.ByteVec): void { + rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.u32ToBeBytes(self[0] as rt.u32))); + rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.u32ToBeBytes(self[1] as rt.u32))); +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_Matches_array2_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_Matches_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_Matches_ref_slice_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_Matches_ref_str(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_Matches_searches_searches_closure1(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RMatches_array2_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RMatches_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RMatches_ref_slice_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RMatches_ref_str(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RMatches_searches_searches_closure1(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RSplitN_array2_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RSplitN_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RSplitN_ref_slice_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RSplitN_ref_str(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RSplitN_searches_searches_closure1(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RSplitTerminator_array2_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RSplitTerminator_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RSplitTerminator_ref_slice_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RSplitTerminator_ref_str(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RSplitTerminator_searches_searches_closure1(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RSplit_array2_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RSplit_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RSplit_ref_slice_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RSplit_ref_str(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_RSplit_searches_searches_closure1(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_SplitInclusive_array2_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_SplitInclusive_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_SplitInclusive_ref_slice_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_SplitInclusive_ref_str(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_SplitInclusive_searches_searches_closure1(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_SplitN_array2_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_SplitN_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_SplitN_ref_slice_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_SplitN_ref_str(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_SplitN_searches_searches_closure1(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_SplitTerminator_array2_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_SplitTerminator_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_SplitTerminator_ref_slice_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_SplitTerminator_ref_str(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_SplitTerminator_searches_searches_closure1(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_Split_array2_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_Split_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_Split_ref_slice_char(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_Split_ref_str(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$ref_str_str_Split_searches_searches_closure1(it: rt.Iter, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter | undefined = undefined; + while (true) { + const _5: string | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: string | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$tuple2_usize_ref_str_str_MatchIndices_array2_char(it: rt.Iter<[rt.usize, string]>, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter<[rt.usize, string]> | undefined = undefined; + while (true) { + const _5: [rt.usize, string] | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_tuple2_usize_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter<[rt.usize, string]> = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: [rt.usize, string] | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$tuple2_usize_ref_str_str_MatchIndices_char(it: rt.Iter<[rt.usize, string]>, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter<[rt.usize, string]> | undefined = undefined; + while (true) { + const _5: [rt.usize, string] | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_tuple2_usize_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter<[rt.usize, string]> = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: [rt.usize, string] | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$tuple2_usize_ref_str_str_MatchIndices_ref_slice_char(it: rt.Iter<[rt.usize, string]>, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter<[rt.usize, string]> | undefined = undefined; + while (true) { + const _5: [rt.usize, string] | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_tuple2_usize_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter<[rt.usize, string]> = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: [rt.usize, string] | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$tuple2_usize_ref_str_str_MatchIndices_ref_str(it: rt.Iter<[rt.usize, string]>, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter<[rt.usize, string]> | undefined = undefined; + while (true) { + const _5: [rt.usize, string] | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_tuple2_usize_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter<[rt.usize, string]> = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: [rt.usize, string] | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$tuple2_usize_ref_str_str_MatchIndices_searches_searches_closure1(it: rt.Iter<[rt.usize, string]>, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter<[rt.usize, string]> | undefined = undefined; + while (true) { + const _5: [rt.usize, string] | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_tuple2_usize_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter<[rt.usize, string]> = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: [rt.usize, string] | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$tuple2_usize_ref_str_str_RMatchIndices_array2_char(it: rt.Iter<[rt.usize, string]>, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter<[rt.usize, string]> | undefined = undefined; + while (true) { + const _5: [rt.usize, string] | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_tuple2_usize_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter<[rt.usize, string]> = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: [rt.usize, string] | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$tuple2_usize_ref_str_str_RMatchIndices_char(it: rt.Iter<[rt.usize, string]>, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter<[rt.usize, string]> | undefined = undefined; + while (true) { + const _5: [rt.usize, string] | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_tuple2_usize_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter<[rt.usize, string]> = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: [rt.usize, string] | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$tuple2_usize_ref_str_str_RMatchIndices_ref_slice_char(it: rt.Iter<[rt.usize, string]>, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter<[rt.usize, string]> | undefined = undefined; + while (true) { + const _5: [rt.usize, string] | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_tuple2_usize_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter<[rt.usize, string]> = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: [rt.usize, string] | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$tuple2_usize_ref_str_str_RMatchIndices_ref_str(it: rt.Iter<[rt.usize, string]>, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter<[rt.usize, string]> | undefined = undefined; + while (true) { + const _5: [rt.usize, string] | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_tuple2_usize_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter<[rt.usize, string]> = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: [rt.usize, string] | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_24, out); + } +} + +/** + * `it` read to its end from the front, then how many it gave, then a clone made after the + * first, read to its end. + */ +export function front$tuple2_usize_ref_str_str_RMatchIndices_searches_searches_closure1(it: rt.Iter<[rt.usize, string]>, out: rt.ByteVec): void { + let n: rt.i32 = 0; + let copy: rt.Iter<[rt.usize, string]> | undefined = undefined; + while (true) { + const _5: [rt.usize, string] | rt.Done = it.next(); + if (_5 !== rt.DONE) { + put$searches_Item_tuple2_usize_ref_str(_5, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.i32Add(n, 1); + } else { + break; + } + } + rt.byteVecPush(out, n & 0xff); + const iter: rt.Iter<[rt.usize, string]> = rt.iterFlatten(rt.iterOption(copy)); + while (true) { + const _24: [rt.usize, string] | rt.Done = iter.next(); + if (_24 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_24, out); + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_Lines(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_Matches_array2_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_Matches_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_Matches_ref_slice_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_Matches_searches_searches_closure1(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_RMatches_array2_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_RMatches_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_RMatches_ref_slice_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_RMatches_searches_searches_closure1(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_RSplitTerminator_array2_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_RSplitTerminator_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_RSplitTerminator_ref_slice_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_RSplitTerminator_searches_searches_closure1(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_RSplit_array2_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_RSplit_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_RSplit_ref_slice_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_RSplit_searches_searches_closure1(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_SplitInclusive_array2_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_SplitInclusive_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_SplitInclusive_ref_slice_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_SplitInclusive_searches_searches_closure1(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_SplitTerminator_array2_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_SplitTerminator_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_SplitTerminator_ref_slice_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_SplitTerminator_searches_searches_closure1(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_SplitWhitespace(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_Split_array2_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_Split_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_Split_ref_slice_char(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$ref_str_str_Split_searches_searches_closure1(it: rt.Iter, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: string | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter = rt.iterRev(copy); + while (true) { + const _35: string | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$tuple2_usize_char_str_CharIndices(it: rt.Iter<[rt.usize, rt.char]>, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: [rt.usize, rt.char] | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter<[rt.usize, rt.char]> | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_tuple2_usize_char(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter<[rt.usize, rt.char]> = rt.iterRev(copy); + while (true) { + const _35: [rt.usize, rt.char] | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_char(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$tuple2_usize_ref_str_str_MatchIndices_array2_char(it: rt.Iter<[rt.usize, string]>, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: [rt.usize, string] | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter<[rt.usize, string]> | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_tuple2_usize_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter<[rt.usize, string]> = rt.iterRev(copy); + while (true) { + const _35: [rt.usize, string] | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$tuple2_usize_ref_str_str_MatchIndices_char(it: rt.Iter<[rt.usize, string]>, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: [rt.usize, string] | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter<[rt.usize, string]> | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_tuple2_usize_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter<[rt.usize, string]> = rt.iterRev(copy); + while (true) { + const _35: [rt.usize, string] | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$tuple2_usize_ref_str_str_MatchIndices_ref_slice_char(it: rt.Iter<[rt.usize, string]>, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: [rt.usize, string] | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter<[rt.usize, string]> | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_tuple2_usize_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter<[rt.usize, string]> = rt.iterRev(copy); + while (true) { + const _35: [rt.usize, string] | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$tuple2_usize_ref_str_str_MatchIndices_searches_searches_closure1(it: rt.Iter<[rt.usize, string]>, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: [rt.usize, string] | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter<[rt.usize, string]> | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_tuple2_usize_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter<[rt.usize, string]> = rt.iterRev(copy); + while (true) { + const _35: [rt.usize, string] | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$tuple2_usize_ref_str_str_RMatchIndices_array2_char(it: rt.Iter<[rt.usize, string]>, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: [rt.usize, string] | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter<[rt.usize, string]> | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_tuple2_usize_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter<[rt.usize, string]> = rt.iterRev(copy); + while (true) { + const _35: [rt.usize, string] | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$tuple2_usize_ref_str_str_RMatchIndices_char(it: rt.Iter<[rt.usize, string]>, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: [rt.usize, string] | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter<[rt.usize, string]> | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_tuple2_usize_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter<[rt.usize, string]> = rt.iterRev(copy); + while (true) { + const _35: [rt.usize, string] | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$tuple2_usize_ref_str_str_RMatchIndices_ref_slice_char(it: rt.Iter<[rt.usize, string]>, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: [rt.usize, string] | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter<[rt.usize, string]> | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_tuple2_usize_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter<[rt.usize, string]> = rt.iterRev(copy); + while (true) { + const _35: [rt.usize, string] | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_35, out); + } + } + return; + } + } +} + +/** + * `it` read to its end, each step from the end the high bit of `data`'s byte picks, then + * how many it gave, then a clone made after the first, read from the back. + */ +export function both$tuple2_usize_ref_str_str_RMatchIndices_searches_searches_closure1(it: rt.Iter<[rt.usize, string]>, data: rt.ByteSlice, out: rt.ByteVec): void { + let back!: boolean; + let _15!: [rt.usize, string] | undefined; + let n: rt.usize = 0; + let copy = undefined as rt.Iter<[rt.usize, string]> | undefined; + while (true) { + const _7: rt.u8 | undefined = rt.byteSliceGet(data, n); + b1: { + if (_7 !== undefined) { + if ((_7 & 128) !== 0) { + back = true; + break b1; + } + } + back = false; + } + if (!back) { + _15 = rt.iterToOption(it.next()); + } else { + _15 = rt.iterToOption(it.nextBack()); + } + if (_15 !== undefined) { + put$searches_Item_tuple2_usize_ref_str(_15, out); + if (n === 0) { + copy = it.clone(); + } + n = rt.usizeAdd(n, 1); + } else { + rt.byteVecPush(out, n & 0xff); + if (copy !== undefined) { + const iter: rt.Iter<[rt.usize, string]> = rt.iterRev(copy); + while (true) { + const _35: [rt.usize, string] | rt.Done = iter.next(); + if (_35 === rt.DONE) { + break; + } + put$searches_Item_tuple2_usize_ref_str(_35, out); + } + } + return; + } + } +} + +export function putOption(out: rt.ByteVec, s: string | undefined): void { + if (s === undefined) { + rt.byteVecPush(out, 254); + } else { + fmt_put(out, s); + } +} + +export function putOffset(out: rt.ByteVec, i: rt.usize | undefined): void { + if (i === undefined) { + rt.byteVecPush(out, 254); + } else { + rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.u32ToBeBytes(i as rt.u32))); + } +} + +/** + * One search, `kind % 17` picking which, by the pattern `kind / 17 % 5` picks, of text of + * chars of every UTF-8 width from all but the first byte. That byte picks the chars a + * pattern of chars matches, a `&str` pattern of up to three chars from the text, empty a + * quarter of the time, and `splitn`'s and `replacen`'s count. + */ +export function searches(kind: rt.u8, data: rt.ByteSlice, out: rt.ByteVec): void { + const _6: [rt.u8, rt.ByteSlice] = option_mapOr$1ttssgs((data.length !== 0 ? [data.data[data.start], new rt.ByteSlice(data.data, data.start + 1, data.length - 1)] as [rt.u8, rt.ByteSlice] : undefined) as [rt.u8, rt.ByteSlice] | undefined, [0, data] as [rt.u8, rt.ByteSlice], (_2: [rt.u8, rt.ByteSlice]): [rt.u8, rt.ByteSlice] => { + return [_2[0], _2[1]] as [rt.u8, rt.ByteSlice]; + }); + const pick: rt.u8 = _6[0]; + const s: string = strs_text(_6[1]); + const alphabet: rt.char[] = rt.iterToArray(rt.strChars(strs_text(rt.byteSliceFrom(Uint8Array.of(rt.u8Rem(pick, 16), rt.u8Div(pick, 16))))), "next", 4); + const _25: rt.char = alphabet[rt.idx(alphabet, 0)]; + const _24: [rt.char, rt.char] = [_25, alphabet[rt.idx(alphabet, 1)]]; + const c: rt.char = _25; + const d: rt.char = _24[1]; + const n: rt.usize = rt.u8Rem(pick, 5) as rt.usize; + const m: rt.u8 = rt.u8Rem(kind, 17); + const _37: rt.char[] = []; + const seen: rt.RefCell = new rt.RefCell(_37); + const p: (a0: rt.char) => boolean = (x2: rt.char): boolean => { + const _62: rt.RefCell = rt.refCellBorrowMut(seen); + _62.value.push(x2); + rt.refMutRelease(_62); + if (!(x2 === c)) { + return rt.isAsciiDigit(x2); + } + return true; + }; + const _42: rt.u8 = rt.u8Rem(rt.u8Div(kind, 17), 5); + if (_42 === 0) { + const _50: string = s; + const part4 = _6[1]; + if (m === 9) { + fmt_put(out, rt.strTrimMatches(_50, String.fromCodePoint(c))); + } else if (m === 10) { + both$ref_str_str_Split_char(rt.strSplit(_50, String.fromCodePoint(c)), part4, out); + } else if (m === 11) { + both$ref_str_str_RSplit_char(rt.strRsplit(_50, String.fromCodePoint(c)), part4, out); + } else if (m === 12) { + both$ref_str_str_SplitTerminator_char(rt.strSplitTerminator(_50, String.fromCodePoint(c)), part4, out); + } else if (m === 13) { + both$ref_str_str_RSplitTerminator_char(rt.strRsplitTerminator(_50, String.fromCodePoint(c)), part4, out); + } else if (m === 14) { + both$ref_str_str_SplitInclusive_char(rt.strSplitInclusive(_50, String.fromCodePoint(c)), part4, out); + } else if (m === 15) { + both$ref_str_str_Matches_char(rt.strMatches(_50, String.fromCodePoint(c)), part4, out); + both$ref_str_str_RMatches_char(rt.strRmatches(_50, String.fromCodePoint(c)), part4, out); + } else if (m === 16) { + both$tuple2_usize_ref_str_str_MatchIndices_char(rt.strMatchIndices(_50, String.fromCodePoint(c)), part4, out); + both$tuple2_usize_ref_str_str_RMatchIndices_char(rt.strRmatchIndices(_50, String.fromCodePoint(c)), part4, out); + } else if (m === 0) { + putOffset(out, rt.strFind(_50, String.fromCodePoint(c))); + putOffset(out, rt.strRfind(_50, String.fromCodePoint(c))); + } else if (m === 1) { + putOption(out, rt.strStripPrefix(_50, String.fromCodePoint(c))); + putOption(out, rt.strStripSuffix(_50, String.fromCodePoint(c))); + } else if (m === 2) { + fmt_put(out, rt.strReplace(_50, String.fromCodePoint(c), "<>")); + fmt_put(out, rt.strReplace(_50, String.fromCodePoint(c), "é", n)); + } else if (m === 3) { + front$ref_str_str_Split_char(rt.strSplit(_50, String.fromCodePoint(c)), out); + front$ref_str_str_RSplit_char(rt.strRsplit(_50, String.fromCodePoint(c)), out); + } else if (m === 4) { + front$ref_str_str_SplitTerminator_char(rt.strSplitTerminator(_50, String.fromCodePoint(c)), out); + front$ref_str_str_RSplitTerminator_char(rt.strRsplitTerminator(_50, String.fromCodePoint(c)), out); + } else if (m === 5) { + front$ref_str_str_SplitN_char(rt.strSplitn(_50, n, String.fromCodePoint(c)), out); + front$ref_str_str_RSplitN_char(rt.strRsplitn(_50, n, String.fromCodePoint(c)), out); + } else if (m === 6) { + front$ref_str_str_SplitInclusive_char(rt.strSplitInclusive(_50, String.fromCodePoint(c)), out); + } else if (m === 7) { + front$ref_str_str_Matches_char(rt.strMatches(_50, String.fromCodePoint(c)), out); + front$ref_str_str_RMatches_char(rt.strRmatches(_50, String.fromCodePoint(c)), out); + } else { + front$tuple2_usize_ref_str_str_MatchIndices_char(rt.strMatchIndices(_50, String.fromCodePoint(c)), out); + front$tuple2_usize_ref_str_str_RMatchIndices_char(rt.strRmatchIndices(_50, String.fromCodePoint(c)), out); + } + } else if (_42 === 1) { + const needle: string = rt.stringExtendChars("", rt.iterTake(rt.iterSkip(rt.strChars(s), rt.u8Div(pick, 64) as rt.usize), rt.u8Rem(rt.u8Div(pick, 16), 4) as rt.usize)); + const _127: rt.u8 = rt.u8Rem(m, 9); + if (_127 === 0) { + putOffset(out, rt.strFind(s, needle)); + putOffset(out, rt.strRfind(s, needle)); + } else if (_127 === 1) { + putOption(out, rt.strStripPrefix(s, needle)); + putOption(out, rt.strStripSuffix(s, needle)); + } else if (_127 === 2) { + fmt_put(out, rt.strReplace(s, needle, "<>")); + fmt_put(out, rt.strReplace(s, needle, "é", n)); + } else if (_127 === 3) { + front$ref_str_str_Split_ref_str(rt.strSplit(s, needle), out); + front$ref_str_str_RSplit_ref_str(rt.strRsplit(s, needle), out); + } else if (_127 === 4) { + front$ref_str_str_SplitTerminator_ref_str(rt.strSplitTerminator(s, needle), out); + front$ref_str_str_RSplitTerminator_ref_str(rt.strRsplitTerminator(s, needle), out); + } else if (_127 === 5) { + front$ref_str_str_SplitN_ref_str(rt.strSplitn(s, n, needle), out); + front$ref_str_str_RSplitN_ref_str(rt.strRsplitn(s, n, needle), out); + } else if (_127 === 6) { + front$ref_str_str_SplitInclusive_ref_str(rt.strSplitInclusive(s, needle), out); + } else if (_127 === 7) { + front$ref_str_str_Matches_ref_str(rt.strMatches(s, needle), out); + front$ref_str_str_RMatches_ref_str(rt.strRmatches(s, needle), out); + } else { + front$tuple2_usize_ref_str_str_MatchIndices_ref_str(rt.strMatchIndices(s, needle), out); + front$tuple2_usize_ref_str_str_RMatchIndices_ref_str(rt.strRmatchIndices(s, needle), out); + } + } else if (_42 === 2) { + const _206: string = s; + const part3 = _6[1]; + if (m === 9) { + const _211: rt.char[] = [c, d]; + fmt_put(out, rt.strTrimMatches(_206, rt.patternChars(rt.sliceRange(_211, 0)))); + } else if (m === 10) { + const _215: rt.char[] = [c, d]; + both$ref_str_str_Split_ref_slice_char(rt.strSplit(_206, rt.patternChars(rt.sliceRange(_215, 0))), part3, out); + } else if (m === 11) { + const _219: rt.char[] = [c, d]; + both$ref_str_str_RSplit_ref_slice_char(rt.strRsplit(_206, rt.patternChars(rt.sliceRange(_219, 0))), part3, out); + } else if (m === 12) { + const _223: rt.char[] = [c, d]; + both$ref_str_str_SplitTerminator_ref_slice_char(rt.strSplitTerminator(_206, rt.patternChars(rt.sliceRange(_223, 0))), part3, out); + } else if (m === 13) { + const _227: rt.char[] = [c, d]; + both$ref_str_str_RSplitTerminator_ref_slice_char(rt.strRsplitTerminator(_206, rt.patternChars(rt.sliceRange(_227, 0))), part3, out); + } else if (m === 14) { + const _231: rt.char[] = [c, d]; + both$ref_str_str_SplitInclusive_ref_slice_char(rt.strSplitInclusive(_206, rt.patternChars(rt.sliceRange(_231, 0))), part3, out); + } else if (m === 15) { + const _236: rt.char[] = [c, d]; + both$ref_str_str_Matches_ref_slice_char(rt.strMatches(_206, rt.patternChars(rt.sliceRange(_236, 0))), part3, out); + const _241: rt.char[] = [c, d]; + both$ref_str_str_RMatches_ref_slice_char(rt.strRmatches(_206, rt.patternChars(rt.sliceRange(_241, 0))), part3, out); + } else if (m === 16) { + const _246: rt.char[] = [c, d]; + both$tuple2_usize_ref_str_str_MatchIndices_ref_slice_char(rt.strMatchIndices(_206, rt.patternChars(rt.sliceRange(_246, 0))), part3, out); + const _251: rt.char[] = [c, d]; + both$tuple2_usize_ref_str_str_RMatchIndices_ref_slice_char(rt.strRmatchIndices(_206, rt.patternChars(rt.sliceRange(_251, 0))), part3, out); + } else if (m === 0) { + const _259: rt.char[] = [c, d]; + putOffset(out, rt.strFind(_206, rt.patternChars(rt.sliceRange(_259, 0)))); + const _264: rt.char[] = [c, d]; + putOffset(out, rt.strRfind(_206, rt.patternChars(rt.sliceRange(_264, 0)))); + } else if (m === 1) { + const _269: rt.char[] = [c, d]; + putOption(out, rt.strStripPrefix(_206, rt.patternChars(rt.sliceRange(_269, 0)))); + const _274: rt.char[] = [c, d]; + putOption(out, rt.strStripSuffix(_206, rt.patternChars(rt.sliceRange(_274, 0)))); + } else if (m === 2) { + const _281: rt.char[] = [c, d]; + fmt_put(out, rt.strReplace(_206, rt.patternChars(rt.sliceRange(_281, 0)), "<>")); + const _289: rt.char[] = [c, d]; + fmt_put(out, rt.strReplace(_206, rt.patternChars(rt.sliceRange(_289, 0)), "é", n)); + } else if (m === 3) { + const _295: rt.char[] = [c, d]; + front$ref_str_str_Split_ref_slice_char(rt.strSplit(_206, rt.patternChars(rt.sliceRange(_295, 0))), out); + const _300: rt.char[] = [c, d]; + front$ref_str_str_RSplit_ref_slice_char(rt.strRsplit(_206, rt.patternChars(rt.sliceRange(_300, 0))), out); + } else if (m === 4) { + const _305: rt.char[] = [c, d]; + front$ref_str_str_SplitTerminator_ref_slice_char(rt.strSplitTerminator(_206, rt.patternChars(rt.sliceRange(_305, 0))), out); + const _310: rt.char[] = [c, d]; + front$ref_str_str_RSplitTerminator_ref_slice_char(rt.strRsplitTerminator(_206, rt.patternChars(rt.sliceRange(_310, 0))), out); + } else if (m === 5) { + const _315: rt.char[] = [c, d]; + front$ref_str_str_SplitN_ref_slice_char(rt.strSplitn(_206, n, rt.patternChars(rt.sliceRange(_315, 0))), out); + const _320: rt.char[] = [c, d]; + front$ref_str_str_RSplitN_ref_slice_char(rt.strRsplitn(_206, n, rt.patternChars(rt.sliceRange(_320, 0))), out); + } else if (m === 6) { + const _324: rt.char[] = [c, d]; + front$ref_str_str_SplitInclusive_ref_slice_char(rt.strSplitInclusive(_206, rt.patternChars(rt.sliceRange(_324, 0))), out); + } else if (m === 7) { + const _329: rt.char[] = [c, d]; + front$ref_str_str_Matches_ref_slice_char(rt.strMatches(_206, rt.patternChars(rt.sliceRange(_329, 0))), out); + const _334: rt.char[] = [c, d]; + front$ref_str_str_RMatches_ref_slice_char(rt.strRmatches(_206, rt.patternChars(rt.sliceRange(_334, 0))), out); + } else { + const _339: rt.char[] = [c, d]; + front$tuple2_usize_ref_str_str_MatchIndices_ref_slice_char(rt.strMatchIndices(_206, rt.patternChars(rt.sliceRange(_339, 0))), out); + const _344: rt.char[] = [c, d]; + front$tuple2_usize_ref_str_str_RMatchIndices_ref_slice_char(rt.strRmatchIndices(_206, rt.patternChars(rt.sliceRange(_344, 0))), out); + } + } else if (_42 === 3) { + const _349: string = s; + const part2 = _6[1]; + if (m === 9) { + fmt_put(out, rt.strTrimMatches(_349, rt.patternChars([c, d]))); + } else if (m === 10) { + both$ref_str_str_Split_array2_char(rt.strSplit(_349, rt.patternChars([c, d])), part2, out); + } else if (m === 11) { + both$ref_str_str_RSplit_array2_char(rt.strRsplit(_349, rt.patternChars([c, d])), part2, out); + } else if (m === 12) { + both$ref_str_str_SplitTerminator_array2_char(rt.strSplitTerminator(_349, rt.patternChars([c, d])), part2, out); + } else if (m === 13) { + both$ref_str_str_RSplitTerminator_array2_char(rt.strRsplitTerminator(_349, rt.patternChars([c, d])), part2, out); + } else if (m === 14) { + both$ref_str_str_SplitInclusive_array2_char(rt.strSplitInclusive(_349, rt.patternChars([c, d])), part2, out); + } else if (m === 15) { + both$ref_str_str_Matches_array2_char(rt.strMatches(_349, rt.patternChars([c, d])), part2, out); + both$ref_str_str_RMatches_array2_char(rt.strRmatches(_349, rt.patternChars([c, d])), part2, out); + } else if (m === 16) { + both$tuple2_usize_ref_str_str_MatchIndices_array2_char(rt.strMatchIndices(_349, rt.patternChars([c, d])), part2, out); + both$tuple2_usize_ref_str_str_RMatchIndices_array2_char(rt.strRmatchIndices(_349, rt.patternChars([c, d])), part2, out); + } else if (m === 0) { + putOffset(out, rt.strFind(_349, rt.patternChars([c, d]))); + putOffset(out, rt.strRfind(_349, rt.patternChars([c, d]))); + } else if (m === 1) { + putOption(out, rt.strStripPrefix(_349, rt.patternChars([c, d]))); + putOption(out, rt.strStripSuffix(_349, rt.patternChars([c, d]))); + } else if (m === 2) { + fmt_put(out, rt.strReplace(_349, rt.patternChars([c, d]), "<>")); + fmt_put(out, rt.strReplace(_349, rt.patternChars([c, d]), "é", n)); + } else if (m === 3) { + front$ref_str_str_Split_array2_char(rt.strSplit(_349, rt.patternChars([c, d])), out); + front$ref_str_str_RSplit_array2_char(rt.strRsplit(_349, rt.patternChars([c, d])), out); + } else if (m === 4) { + front$ref_str_str_SplitTerminator_array2_char(rt.strSplitTerminator(_349, rt.patternChars([c, d])), out); + front$ref_str_str_RSplitTerminator_array2_char(rt.strRsplitTerminator(_349, rt.patternChars([c, d])), out); + } else if (m === 5) { + front$ref_str_str_SplitN_array2_char(rt.strSplitn(_349, n, rt.patternChars([c, d])), out); + front$ref_str_str_RSplitN_array2_char(rt.strRsplitn(_349, n, rt.patternChars([c, d])), out); + } else if (m === 6) { + front$ref_str_str_SplitInclusive_array2_char(rt.strSplitInclusive(_349, rt.patternChars([c, d])), out); + } else if (m === 7) { + front$ref_str_str_Matches_array2_char(rt.strMatches(_349, rt.patternChars([c, d])), out); + front$ref_str_str_RMatches_array2_char(rt.strRmatches(_349, rt.patternChars([c, d])), out); + } else { + front$tuple2_usize_ref_str_str_MatchIndices_array2_char(rt.strMatchIndices(_349, rt.patternChars([c, d])), out); + front$tuple2_usize_ref_str_str_RMatchIndices_array2_char(rt.strRmatchIndices(_349, rt.patternChars([c, d])), out); + } + } else { + const _438: string = s; + const part = _6[1]; + if (m === 9) { + fmt_put(out, rt.strTrimMatches(_438, p)); + } else if (m === 10) { + both$ref_str_str_Split_searches_searches_closure1(rt.strSplit(_438, p), part, out); + } else if (m === 11) { + both$ref_str_str_RSplit_searches_searches_closure1(rt.strRsplit(_438, p), part, out); + } else if (m === 12) { + both$ref_str_str_SplitTerminator_searches_searches_closure1(rt.strSplitTerminator(_438, p), part, out); + } else if (m === 13) { + both$ref_str_str_RSplitTerminator_searches_searches_closure1(rt.strRsplitTerminator(_438, p), part, out); + } else if (m === 14) { + both$ref_str_str_SplitInclusive_searches_searches_closure1(rt.strSplitInclusive(_438, p), part, out); + } else if (m === 15) { + both$ref_str_str_Matches_searches_searches_closure1(rt.strMatches(_438, p), part, out); + both$ref_str_str_RMatches_searches_searches_closure1(rt.strRmatches(_438, p), part, out); + } else if (m === 16) { + both$tuple2_usize_ref_str_str_MatchIndices_searches_searches_closure1(rt.strMatchIndices(_438, p), part, out); + both$tuple2_usize_ref_str_str_RMatchIndices_searches_searches_closure1(rt.strRmatchIndices(_438, p), part, out); + } else if (m === 0) { + putOffset(out, rt.strFind(_438, p)); + putOffset(out, rt.strRfind(_438, p)); + } else if (m === 1) { + putOption(out, rt.strStripPrefix(_438, p)); + putOption(out, rt.strStripSuffix(_438, p)); + } else if (m === 2) { + fmt_put(out, rt.strReplace(_438, p, "<>")); + fmt_put(out, rt.strReplace(_438, p, "é", n)); + } else if (m === 3) { + front$ref_str_str_Split_searches_searches_closure1(rt.strSplit(_438, p), out); + front$ref_str_str_RSplit_searches_searches_closure1(rt.strRsplit(_438, p), out); + } else if (m === 4) { + front$ref_str_str_SplitTerminator_searches_searches_closure1(rt.strSplitTerminator(_438, p), out); + front$ref_str_str_RSplitTerminator_searches_searches_closure1(rt.strRsplitTerminator(_438, p), out); + } else if (m === 5) { + front$ref_str_str_SplitN_searches_searches_closure1(rt.strSplitn(_438, n, p), out); + front$ref_str_str_RSplitN_searches_searches_closure1(rt.strRsplitn(_438, n, p), out); + } else if (m === 6) { + front$ref_str_str_SplitInclusive_searches_searches_closure1(rt.strSplitInclusive(_438, p), out); + } else if (m === 7) { + front$ref_str_str_Matches_searches_searches_closure1(rt.strMatches(_438, p), out); + front$ref_str_str_RMatches_searches_searches_closure1(rt.strRmatches(_438, p), out); + } else { + front$tuple2_usize_ref_str_str_MatchIndices_searches_searches_closure1(rt.strMatchIndices(_438, p), out); + front$tuple2_usize_ref_str_str_RMatchIndices_searches_searches_closure1(rt.strRmatchIndices(_438, p), out); + } + } + const _501: rt.RefCell = rt.refCellBorrow(seen); + const iter: rt.Iter = rt.iterSlice(_501.value); + while (true) { + const _504: rt.char | rt.Done = iter.next(); + if (_504 === rt.DONE) { + break; + } + rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.u32ToBeBytes(_504 as rt.u32))); + } + rt.refRelease(_501); +} + +/** + * `str`'s text iterators and trims, `kind % 4` picking which, of text of `SPACES` by the + * low bits of each byte, read from the end each byte's high bit picks. + */ +export function texts(kind: rt.u8, data: rt.ByteSlice, out: rt.ByteVec): void { + const s: string = rt.stringExtendChars("", rt.iterMap(rt.iterSlice(rt.byteSliceView(data)), (_2: rt.u8): rt.char => { + const _52: rt.usize = rt.u8Rem(_2, 16) as rt.usize; + if (!(_52 < 16)) { + rt.panic("index out of bounds: the len is " + 16 + " but the index is " + _52); + } + return [10, 13, 97, 32, 9, 11, 133, 160, 5760, 8202, 8203, 8232, 12288, 65279, 233, 128512][_52]; + })); + const _7: rt.u8 = rt.u8Rem(kind, 4); + if (_7 === 0) { + both$tuple2_usize_char_str_CharIndices(rt.strCharIndices(s), data, out); + } else if (_7 === 1) { + both$ref_str_str_Lines(rt.strLines(s), data, out); + } else if (_7 === 2) { + both$ref_str_str_SplitWhitespace(rt.strSplitWhitespace(s), data, out); + } else { + fmt_put(out, rt.strTrimMatches(s, rt.charIsWhitespace)); + fmt_put(out, rt.strTrimStartMatches(s, rt.charIsWhitespace)); + fmt_put(out, rt.strTrimEndMatches(s, rt.charIsWhitespace)); + for (const _37 of rt.iterToArray(rt.iterMap(rt.strChars(s), (a0: rt.char): boolean => { + return rt.charIsWhitespace(a0); + }), "next", 1)) { + rt.byteVecPush(out, _37 ? 1 : 0); + } + } +} + +//# sourceMappingURL=searches.ts.map diff --git a/ts/fixtures/lang/src/harness.rs b/ts/fixtures/lang/src/harness.rs index c99cd5da2..3d09a565a 100644 --- a/ts/fixtures/lang/src/harness.rs +++ b/ts/fixtures/lang/src/harness.rs @@ -6,7 +6,7 @@ use crate::{ collections, combinators, conversions, counts, cows, cycles, defaults, durations, dyns, edits, elements, ends, errors, fields, floats, fmt, folds, generics, hashes, heap, hints, holds, ints, iters, joins, keys, lengths, lists, locals, locks, manual, methods, nested, objects, orders, pointers, refs, results, returns, rings, saturates, - separated, shapes, singles, slices, sorts, splits, statics, strs, tuples, utf8, wrappers, wraps, zeros, + searches, separated, shapes, singles, slices, sorts, splits, statics, strs, tuples, utf8, wrappers, wraps, zeros, }; /// The native side's entry: [`run`], except that a case starting with 0xff prints a @@ -309,6 +309,8 @@ fn cases() -> Vec<(&'static str, Case)> { ("sorts::disorders", sorts::disorders), ("sorts::btrees", sorts::btrees), ("dyns::pointers", |_, data, out| dyns::pointers(data, out)), + ("searches::searches", searches::searches), + ("searches::texts", searches::texts), ] } diff --git a/ts/fixtures/lang/src/lib.rs b/ts/fixtures/lang/src/lib.rs index 16662d3cb..d83547fda 100644 --- a/ts/fixtures/lang/src/lib.rs +++ b/ts/fixtures/lang/src/lib.rs @@ -97,6 +97,7 @@ mod results; mod returns; mod rings; mod saturates; +mod searches; mod separated; mod shapes; mod singles; diff --git a/ts/fixtures/lang/src/searches.rs b/ts/fixtures/lang/src/searches.rs new file mode 100644 index 000000000..b82734e30 --- /dev/null +++ b/ts/fixtures/lang/src/searches.rs @@ -0,0 +1,222 @@ +//! `str`'s searches by each kind of pattern std takes, a `char`, a `&str`, a `&[char]`, a +//! `[char; 2]`, and a closure, read from the front, the back, or both, and `str`'s text +//! iterators over whitespace and line ends of every UTF-8 width. Each iterator is cloned +//! after its first item and the clone read to its end. The closure logs each char it is +//! called with, so which chars std's searches test, and in what order, is output too. + +use std::cell::RefCell; + +use crate::fmt::put; +use crate::strs::text; + +/// An item of a search, put in the output. +trait Item { + fn put(self, out: &mut Vec); +} + +impl Item for &str { + fn put(self, out: &mut Vec) { + put(out, self); + } +} + +impl Item for (usize, &str) { + fn put(self, out: &mut Vec) { + out.extend_from_slice(&(self.0 as u32).to_be_bytes()); + put(out, self.1); + } +} + +impl Item for (usize, char) { + fn put(self, out: &mut Vec) { + out.extend_from_slice(&(self.0 as u32).to_be_bytes()); + out.extend_from_slice(&u32::from(self.1).to_be_bytes()); + } +} + +/// `it` read to its end from the front, then how many it gave, then a clone made after the +/// first, read to its end. +fn front + Clone>(mut it: I, out: &mut Vec) { + let mut n = 0; + let mut copy = None; + while let Some(item) = it.next() { + item.put(out); + if n == 0 { + copy = Some(it.clone()); + } + n += 1; + } + out.push(n as u8); + for item in copy.into_iter().flatten() { + item.put(out); + } +} + +/// `it` read to its end, each step from the end the high bit of `data`'s byte picks, then +/// how many it gave, then a clone made after the first, read from the back. +fn both + Clone>(mut it: I, data: &[u8], out: &mut Vec) { + let mut n = 0; + let mut copy = None; + loop { + let back = matches!(data.get(n), Some(&b) if b & 0x80 != 0); + let Some(item) = (if back { it.next_back() } else { it.next() }) else { + break; + }; + item.put(out); + if n == 0 { + copy = Some(it.clone()); + } + n += 1; + } + out.push(n as u8); + if let Some(copy) = copy { + for item in copy.rev() { + item.put(out); + } + } +} + +fn put_option(out: &mut Vec, s: Option<&str>) { + match s { + Some(s) => put(out, s), + None => out.push(0xfe), + } +} + +fn put_offset(out: &mut Vec, i: Option) { + match i { + Some(i) => out.extend_from_slice(&(i as u32).to_be_bytes()), + None => out.push(0xfe), + } +} + +/// Every search std takes `$p` in, a pattern any searcher may take, by `$m`: from the front, +/// and from the back where the searcher reads from there. +macro_rules! searches { + ($m:expr, $n:expr, $s:expr, $p:expr, $out:expr) => {{ + let (s, out): (&str, &mut Vec) = ($s, $out); + match $m { + 0 => { + put_offset(out, s.find($p)); + put_offset(out, s.rfind($p)); + } + 1 => { + put_option(out, s.strip_prefix($p)); + put_option(out, s.strip_suffix($p)); + } + 2 => { + put(out, &s.replace($p, "<>")); + put(out, &s.replacen($p, "é", $n)); + } + 3 => { + front(s.split($p), out); + front(s.rsplit($p), out); + } + 4 => { + front(s.split_terminator($p), out); + front(s.rsplit_terminator($p), out); + } + 5 => { + front(s.splitn($n, $p), out); + front(s.rsplitn($n, $p), out); + } + 6 => front(s.split_inclusive($p), out), + 7 => { + front(s.matches($p), out); + front(s.rmatches($p), out); + } + _ => { + front(s.match_indices($p), out); + front(s.rmatch_indices($p), out); + } + } + }}; +} + +/// `searches!`, and the searches std takes `$p` in from both ends at once, a pattern of +/// chars, by `$m`. +macro_rules! searches_both { + ($m:expr, $n:expr, $s:expr, $data:expr, $p:expr, $out:expr) => {{ + let (s, data, out): (&str, &[u8], &mut Vec) = ($s, $data, $out); + match $m { + 9 => put(out, s.trim_matches($p)), + 10 => both(s.split($p), data, out), + 11 => both(s.rsplit($p), data, out), + 12 => both(s.split_terminator($p), data, out), + 13 => both(s.rsplit_terminator($p), data, out), + 14 => both(s.split_inclusive($p), data, out), + 15 => { + both(s.matches($p), data, out); + both(s.rmatches($p), data, out); + } + 16 => { + both(s.match_indices($p), data, out); + both(s.rmatch_indices($p), data, out); + } + m => searches!(m, $n, s, $p, out), + } + }}; +} + +/// One search, `kind % 17` picking which, by the pattern `kind / 17 % 5` picks, of text of +/// chars of every UTF-8 width from all but the first byte. That byte picks the chars a +/// pattern of chars matches, a `&str` pattern of up to three chars from the text, empty a +/// quarter of the time, and `splitn`'s and `replacen`'s count. +pub fn searches(kind: u8, data: &[u8], out: &mut Vec) { + let (pick, data) = data.split_first().map_or((0, data), |(&b, rest)| (b, rest)); + let s = text(data); + let alphabet: Vec = text(&[pick % 16, pick / 16]).chars().collect(); + let (c, d) = (alphabet[0], alphabet[1]); + let n = usize::from(pick % 5); + let m = kind % 17; + let seen = RefCell::new(Vec::new()); + let p = |x: char| { + seen.borrow_mut().push(x); + x == c || x.is_ascii_digit() + }; + match kind / 17 % 5 { + 0 => searches_both!(m, n, &s, data, c, out), + 1 => { + // A `&str`, which std searches from one end only. + let needle: String = s + .chars() + .skip(usize::from(pick / 64)) + .take(usize::from(pick / 16 % 4)) + .collect(); + searches!(m % 9, n, &s, needle.as_str(), out) + } + 2 => searches_both!(m, n, &s, data, &[c, d][..], out), + 3 => searches_both!(m, n, &s, data, [c, d], out), + _ => searches_both!(m, n, &s, data, p, out), + } + for &x in seen.borrow().iter() { + out.extend_from_slice(&u32::from(x).to_be_bytes()); + } +} + +/// Line ends, whitespace of each UTF-8 width, and chars that are neither, `\u{200b}` and +/// `\u{feff}` among them, which JS's `\s` counts as whitespace. +const SPACES: [char; 16] = [ + '\n', '\r', 'a', ' ', '\t', '\u{b}', '\u{85}', '\u{a0}', '\u{1680}', '\u{200a}', '\u{200b}', '\u{2028}', + '\u{3000}', '\u{feff}', 'é', '😀', +]; + +/// `str`'s text iterators and trims, `kind % 4` picking which, of text of `SPACES` by the +/// low bits of each byte, read from the end each byte's high bit picks. +pub fn texts(kind: u8, data: &[u8], out: &mut Vec) { + let s: String = data.iter().map(|&b| SPACES[usize::from(b % 16)]).collect(); + match kind % 4 { + 0 => both(s.char_indices(), data, out), + 1 => both(s.lines(), data, out), + 2 => both(s.split_whitespace(), data, out), + _ => { + put(out, s.trim()); + put(out, s.trim_start()); + put(out, s.trim_end()); + let spaces: Vec = s.chars().map(char::is_whitespace).collect(); + for space in spaces { + out.push(space as u8); + } + } + } +} diff --git a/ts/runtime/rt/str.ts b/ts/runtime/rt/str.ts index 6672a1836..8adee06b7 100644 --- a/ts/runtime/rt/str.ts +++ b/ts/runtime/rt/str.ts @@ -9,7 +9,7 @@ import { fmtCharDebug, type Place, panic, panicFmt, stringLen } from "../rt.ts"; import { type Bounds, boundsRange, type Part } from "./collections.ts"; import type { char, u8, usize } from "./int.ts"; -import { type Clones, DONE, type Done, Iter, iterForEach, iterSlice, type RangeInclusive, type SizeHint } from "./iter.ts"; +import { type Clones, DONE, type Done, Iter, iterFilter, iterForEach, iterMap, iterRev, iterSlice, type RangeInclusive, type SizeHint } from "./iter.ts"; import { drop as dispose } from "./task.ts"; const encoder = /* @__PURE__ */ new TextEncoder(); @@ -228,6 +228,50 @@ class Chars extends Iter { } } +/** `str::char_indices`. */ +export function strCharIndices(s: string): Iter<[usize, char]> { + return new CharIndices(new Chars(s)); +} + +class CharIndices extends Iter<[usize, char]> { + readonly #chars: Chars; + // The bytes before the front, and before the back once it first moves. + #front = 0; + #back = -1; + + constructor(chars: Chars) { + super(); + this.#chars = chars; + } + + next(): [usize, char] | Done { + const c = this.#chars.next(); + if (c === DONE) return DONE; + const at = this.#front; + this.#front += charLen(c); + return [at as usize, c]; + } + + override nextBack(): [usize, char] | Done { + if (this.#back < 0) this.#back = this.#front + stringLen(this.#chars.rest()); + const c = this.#chars.nextBack(); + if (c === DONE) return DONE; + this.#back -= charLen(c); + return [this.#back as usize, c]; + } + + override sizeHint(): SizeHint { + return this.#chars.sizeHint(); + } + + override clone(): Iter<[usize, char]> { + const it = new CharIndices(this.#chars.clone() as Chars); + it.#front = this.#front; + it.#back = this.#back; + return it; + } +} + /** * std's searcher of a pattern in `s` between `front` and `back`, in code units. Each step * finds the next match from one end, `start` to `end`, and moves that end past it. A @@ -238,8 +282,10 @@ class Searcher { readonly #p: Pattern; #front = 0; #back: number; - // An empty pattern matches before each char and after the last, as std's does. + // An empty pattern matches before each char and after the last, as std's does, from + // whichever end it searches. #matched = false; + #matchedBack = false; start = 0; end = 0; @@ -255,6 +301,7 @@ class Searcher { m.#front = this.#front; m.#back = this.#back; m.#matched = this.#matched; + m.#matchedBack = this.#matchedBack; m.start = this.start; m.end = this.end; return m; @@ -298,6 +345,15 @@ class Searcher { nextMatchBack(): boolean { const { s } = this; const p = this.#p; + if (p === "") { + if (this.#matchedBack) { + if (this.#back <= this.#front) return false; + this.#back = before(s, this.#back); + } + this.#matchedBack = true; + this.start = this.end = this.#back; + return true; + } if (typeof p === "string") { const from = this.#back - p.length; const i = from < this.#front ? -1 : s.lastIndexOf(p, from); @@ -327,28 +383,80 @@ export function strSplit(s: string, p: Pattern): Iter { return new Split(new Searcher(s, p), true); } +/** `str::rsplit`: `split` from the back. */ +export function strRsplit(s: string, p: Pattern): Iter { + return iterRev(strSplit(s, p)); +} + /** `str::split_terminator`: `split`, without the empty part after a last match. */ export function strSplitTerminator(s: string, p: Pattern): Iter { return new Split(new Searcher(s, p), false); } +/** `str::rsplit_terminator`: `split_terminator` from the back. */ +export function strRsplitTerminator(s: string, p: Pattern): Iter { + return iterRev(strSplitTerminator(s, p)); +} + +/** `str::splitn`: `split`, whose `n`th part is the rest. */ +export function strSplitn(s: string, n: usize, p: Pattern): Iter { + return new Split(new Searcher(s, p), true, false, n); +} + +/** `str::rsplitn`: `splitn` from the back. */ +export function strRsplitn(s: string, n: usize, p: Pattern): Iter { + return iterRev(strSplitn(s, n, p)); +} + +/** `str::split_inclusive`: `split_terminator`, each part ending with the match after it. */ +export function strSplitInclusive(s: string, p: Pattern): Iter { + return new Split(new Searcher(s, p), false, true); +} + +/** `str::lines`: the parts ending with `\n`, without it or a `\r` before it. */ +export function strLines(s: string): Iter { + return iterMap(strSplitInclusive(s, "\n"), (line) => { + if (!line.endsWith("\n")) return line; + return line.slice(0, line.endsWith("\r\n") ? -2 : -1); + }); +} + +/** `str::split_whitespace`: the parts between Unicode whitespace, but empty ones. */ +export function strSplitWhitespace(s: string): Iter { + return iterFilter(strSplit(s, charIsWhitespace), (part) => part !== ""); +} + +/** `char::is_whitespace`: Unicode's `White_Space`. */ +export function charIsWhitespace(c: char): boolean { + if (c <= 0x20) return c === 0x20 || (c >= 0x09 && c <= 0x0d); + if (c < 0x85) return false; + return c === 0x85 || c === 0xa0 || c === 0x1680 || (c >= 0x2000 && c <= 0x200a) || c === 0x2028 || c === 0x2029 || c === 0x202f || c === 0x205f || c === 0x3000; +} + +/** std's `SplitInternal`, and with a count, `SplitNInternal`. */ class Split extends Iter { readonly #m: Searcher; #start = 0; #end: number; // Whether an empty last part is yielded, which `nextBack` sets once it has passed it. #trailing: boolean; + // Whether a part keeps the match that ends it. + readonly #inclusive: boolean; + // The parts left before the rest is the last, as `splitn` counts them. + #count: number; #finished = false; - constructor(m: Searcher, trailing: boolean) { + constructor(m: Searcher, trailing: boolean, inclusive = false, count = Infinity) { super(); this.#m = m; this.#end = m.s.length; this.#trailing = trailing; + this.#inclusive = inclusive; + this.#count = count; } override clone(h?: Clones): Iter { - const it = new Split(this.#m.clone(h), this.#trailing); + const it = new Split(this.#m.clone(h), this.#trailing, this.#inclusive, this.#count); it.#start = this.#start; it.#end = this.#end; it.#finished = this.#finished; @@ -356,35 +464,80 @@ class Split extends Iter { } next(): string | Done { + if (this.#count === 0) return DONE; + if (--this.#count === 0) return this.#rest(); if (this.#finished) return DONE; const m = this.#m; - if (m.nextMatch()) { - const part = m.s.slice(this.#start, m.start); - this.#start = m.end; - return part; - } - this.#finished = true; - return this.#trailing || this.#start < this.#end ? m.s.slice(this.#start, this.#end) : DONE; + if (!m.nextMatch()) return this.#rest(); + const part = m.s.slice(this.#start, this.#inclusive ? m.end : m.start); + this.#start = m.end; + return part; } override nextBack(): string | Done { + if (this.#count === 0) return DONE; + if (--this.#count === 0) return this.#rest(); + return this.#back(); + } + + #back(): string | Done { if (this.#finished) return DONE; if (!this.#trailing) { // The last part, unless it is empty, as std's does. this.#trailing = true; - const part = this.nextBack(); + const part = this.#back(); if (part !== DONE && part !== "") return part; if (this.#finished) return DONE; } const m = this.#m; if (m.nextMatchBack()) { const part = m.s.slice(m.end, this.#end); - this.#end = m.start; + this.#end = this.#inclusive ? m.end : m.start; return part; } this.#finished = true; return m.s.slice(this.#start, this.#end); } + + /** std's `get_end`: what is left, once, unless it is an empty last part `trailing` drops. */ + #rest(): string | Done { + if (this.#finished) return DONE; + this.#finished = true; + return this.#trailing || this.#start < this.#end ? this.#m.s.slice(this.#start, this.#end) : DONE; + } +} + +/** `str::matches`. */ +export function strMatches(s: string, p: Pattern): Iter { + return new Matches(new Searcher(s, p)); +} + +/** `str::rmatches`: `matches` from the back. */ +export function strRmatches(s: string, p: Pattern): Iter { + return iterRev(strMatches(s, p)); +} + +class Matches extends Iter { + readonly #m: Searcher; + + constructor(m: Searcher) { + super(); + this.#m = m; + } + + override clone(h?: Clones): Iter { + return new Matches(this.#m.clone(h)); + } + + next(): string | Done { + const m = this.#m; + return m.nextMatch() ? m.s.slice(m.start, m.end) : DONE; + } + + override nextBack(): string | Done { + const m = this.#m; + return m.nextMatchBack() ? m.s.slice(m.start, m.end) : DONE; + } } /** `str::match_indices`: each match, after its offset in UTF-8 bytes. */ @@ -392,6 +545,11 @@ export function strMatchIndices(s: string, p: Pattern): Iter<[usize, string]> { return new MatchIndices(new Searcher(s, p)); } +/** `str::rmatch_indices`: `match_indices` from the back. */ +export function strRmatchIndices(s: string, p: Pattern): Iter<[usize, string]> { + return iterRev(strMatchIndices(s, p)); +} + class MatchIndices extends Iter<[usize, string]> { readonly #m: Searcher; // Where the last match from each end starts, in code units and in bytes. The back's @@ -479,6 +637,59 @@ export function strTrimEndMatches(s: string, p: Pattern): string { return s.slice(0, end); } +/** + * `str::trim_matches`: without the matches at either end. A predicate is called from the + * front up to the first char it rejects, then from the back up to that char, as std's is. + */ +export function strTrimMatches(s: string, p: Pattern): string { + if (typeof p === "string") return strTrimEndMatches(strTrimStartMatches(s, p), p); + let start = 0; + while (start < s.length && p(s.codePointAt(start) as char)) start += (s.codePointAt(start) as number) > 0xffff ? 2 : 1; + // The char it rejected, which the back stops after. + const floor = start < s.length ? start + ((s.codePointAt(start) as number) > 0xffff ? 2 : 1) : start; + let end = s.length; + while (end > floor) { + const i = before(s, end); + if (!p(s.codePointAt(i) as char)) break; + end = i; + } + return s.slice(start, end); +} + +/** `str::strip_prefix`: what follows a match at the start, which a predicate tests the first char for. */ +export function strStripPrefix(s: string, p: Pattern): string | undefined { + if (typeof p === "string") return s.startsWith(p) ? s.slice(p.length) : undefined; + if (s.length === 0) return undefined; + const c = s.codePointAt(0) as number; + return p(c as char) ? s.slice(c > 0xffff ? 2 : 1) : undefined; +} + +/** `str::strip_suffix`: what precedes a match at the end, which a predicate tests the last char for. */ +export function strStripSuffix(s: string, p: Pattern): string | undefined { + if (typeof p === "string") return s.endsWith(p) ? s.slice(0, s.length - p.length) : undefined; + if (s.length === 0) return undefined; + const i = before(s, s.length); + return p(s.codePointAt(i) as char) ? s.slice(0, i) : undefined; +} + +/** `str::find`: the first match's offset in UTF-8 bytes. */ +export function strFind(s: string, p: Pattern): usize | undefined { + const m = new Searcher(s, p); + return m.nextMatch() ? (utf8Len(s, 0, m.start) as usize) : undefined; +} + +/** `str::replace`, and `replacen` of the first `n` matches. */ +export function strReplace(s: string, p: Pattern, to: string, n = Infinity): string { + const m = new Searcher(s, p); + let out = ""; + let last = 0; + for (let i = 0; i < n && m.nextMatch(); i++) { + out += s.slice(last, m.start) + to; + last = m.end; + } + return out + s.slice(last); +} + /** `str::rfind`: the last match's offset in UTF-8 bytes. */ export function strRfind(s: string, p: Pattern): usize | undefined { const m = new Searcher(s, p); diff --git a/ts/src/lower/iter.rs b/ts/src/lower/iter.rs index 950f51806..a6f8392c4 100644 --- a/ts/src/lower/iter.rs +++ b/ts/src/lower/iter.rs @@ -1046,7 +1046,11 @@ fn clones<'tcx>(b: &mut Body<'_, '_, 'tcx>, ty: Ty<'tcx>, span: Span) -> Option< "iter", "Iter" | "Windows" | "Chunks" | "ChunksExact" | "RChunks" | "RChunksExact", ] - | ["str", "iter", "Chars" | "Bytes"] + | [ + "str", + "iter", + "Chars" | "CharIndices" | "Bytes" | "Lines" | "SplitWhitespace", + ] | ["ascii", "EscapeDefault"] | ["slice", "ascii", "EscapeAscii"] | ["option", "Iter"] @@ -1077,11 +1081,18 @@ fn clones<'tcx>(b: &mut Body<'_, '_, 'tcx>, ty: Ty<'tcx>, span: Span) -> Option< | ["collections", "vec_deque", "into_iter", "IntoIter"] | ["collections", "linked_list", "IntoIter"] | ["collections", "binary_heap", "IntoIter"] => parts(vec![("v", value(b, arg(0)?))]), - // A closure's searcher clones the closure; another holds what it searches for. - ["str", "iter", "Split" | "SplitTerminator" | "MatchIndices"] => match arg(0)?.kind() { - ty::Closure(..) => parts(vec![("f", value(b, arg(0)?))]), - _ => Expr::undefined(), - }, + // A closure's searcher clones the closure; another holds what it searches for. One + // from the back is `rt.iterRev` of one from the front. + [ + "str", + "iter", + "Split" | "SplitTerminator" | "SplitN" | "SplitInclusive" | "Matches" | "MatchIndices", + ] => searcher(b, arg(0)?, span), + [ + "str", + "iter", + "RSplit" | "RSplitTerminator" | "RSplitN" | "RMatches" | "RMatchIndices", + ] => parts(vec![("i", searcher(b, arg(0)?, span))]), // A slice's parts by a closure clone the closure. ["slice", "iter", "Split" | "SplitInclusive" | "RSplit"] => parts(vec![("f", value(b, arg(1)?))]), // Its closure is what `rt.iterFrom` reads by. @@ -1122,6 +1133,14 @@ fn clones<'tcx>(b: &mut Body<'_, '_, 'tcx>, ty: Ty<'tcx>, span: Span) -> Option< }) } +/// What clones a `str` search's searcher of `pattern`: its closure, if it is one. +fn searcher<'tcx>(b: &mut Body<'_, '_, 'tcx>, pattern: Ty<'tcx>, span: Span) -> Expr { + match pattern.kind() { + ty::Closure(..) => parts(vec![("f", super::collections::clone_fn(b, pattern, span))]), + _ => Expr::undefined(), + } +} + /// An `rt.Clones` of `parts` but those that clone as themselves, or `undefined` if all do. fn parts(parts: Vec<(&str, Expr)>) -> Expr { let parts: Vec<(Key, Expr)> = (parts.into_iter()) diff --git a/ts/src/lower/library.rs b/ts/src/lower/library.rs index 4a0ab4100..1bba257ac 100644 --- a/ts/src/lower/library.rs +++ b/ts/src/lower/library.rs @@ -2321,11 +2321,31 @@ fn mapping<'tcx>( ("str", "bytes") => Expr::rt("strBytes", args), ("str", "is_char_boundary") => Expr::rt("strIsCharBoundary", args), // Searches by a pattern. - ("str", "split" | "split_terminator" | "match_indices" | "contains" | "starts_with" | "ends_with") - | ("str", "rfind" | "split_once" | "rsplit_once" | "trim_start_matches" | "trim_end_matches") => { + ("str", "split" | "rsplit" | "split_terminator" | "rsplit_terminator" | "split_inclusive") + | ("str", "matches" | "rmatches" | "match_indices" | "rmatch_indices" | "split_once" | "rsplit_once") + | ("str", "find" | "rfind" | "contains" | "starts_with" | "ends_with" | "strip_prefix" | "strip_suffix") + | ("str", "trim_matches" | "trim_start_matches" | "trim_end_matches") => { let [s, p] = <[Expr; 2]>::try_from(args).ok()?; Expr::rt_of("str", &super::camel(&name)).call(vec![s, pattern(b.t, targ(gargs, 0), p)?]) } + ("str", "splitn" | "rsplitn") => { + let [s, n, p] = <[Expr; 3]>::try_from(args).ok()?; + Expr::rt_of("str", &name).call(vec![s, n, pattern(b.t, targ(gargs, 0), p)?]) + } + // `replacen`'s count follows what replaces each match. + ("str", "replace" | "replacen") => { + let mut args = args.into_iter(); + let (s, p) = (args.next()?, args.next()?); + let rest = args.collect::>(); + Expr::rt("strReplace", [vec![s, pattern(b.t, targ(gargs, 0), p)?], rest].concat()) + } + // Searches by whitespace, as std's are by `char::is_whitespace`. + ("char", "is_whitespace") => Expr::rt("charIsWhitespace", args), + ("str", "trim" | "trim_start" | "trim_end") => { + let f = format!("{}_matches", name); + Expr::rt_of("str", &super::camel(&f)).call(vec![args.pop()?, Expr::Rt("charIsWhitespace".into())]) + } + ("str", "char_indices" | "lines" | "split_whitespace") => Expr::rt_of("str", &super::camel(&name)).call(args), // A slice of strings concatenated, or joined by a `&str`. ("slice", "concat" | "join") if string(tcx, targ(gargs, 0).peel_refs()) && targ(gargs, 1).peel_refs().is_str() =>