Grip.Char: a UTF-8 / Char layer above the byte core #
Consumers that think in Char rather than UInt8 use these combinators. Each
decodes one UTF-8 scalar from the ByteArray and advances by its byte width, so the
fast path stays byte-level: there is no String allocation and no intermediate
decode of the whole input.
satisfyChar/anyChar/char are conditional (they consume at least one byte on
success). The if q < q' clamp in each run makes the always-consume witness hold
without reasoning about the decoder's width, mirroring GParser.fix. The decoder
decodeUtf8 and the byte-level literal matcher matchBytes are exposed for grammars
that mix levels; GParser.string matches a whole UTF-8 literal.
Decode one UTF-8 scalar starting at byte offset q, returning the Char and the
new offset q + width (width 1 to 4), or none on truncated or invalid input.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A successful decodeUtf8 ends within bounds: each branch that returns some (c, q + k)
first checks the byte at q + (k-1), so q + k ≤ arr.size.
Consume one Char satisfying p, or fail without consuming. Grade conditional.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Consume any one Char. Grade conditional.
Equations
- Grip.GParser.anyChar = Grip.GParser.satisfyChar fun (x : Char) => true
Instances For
Consume the specific Char c. Grade conditional.
Equations
- Grip.GParser.char c = Grip.GParser.satisfyChar fun (x : Char) => x == c
Instances For
Do the bytes of bs from index i match arr from offset q?
Equations
Instances For
A successful matchBytes starting at a real index (i < bs.size) ends within bounds:
each matched byte requires q < arr.size, so q + (bs.size - i) ≤ arr.size.
Match the UTF-8 bytes of the literal s, consuming them. Intended for a nonempty
literal (grade conditional); the if q < q' clamp fails an empty match.
Equations
- One or more equations did not get rendered due to their size.