Module Bytes

type Bytes.Builder = iterative choice {
  .add => [Bytes] self,
  .build => Bytes,
}

An incremental byte buffer builder. Add chunks with .add, then finalize with .build.

type Bytes.Parser<e> = recursive iterative@attempt choice {
  .byte => either {
    .byte (Byte) self,
    .end Result<e, !>,
  },
  .close => Result<e, !>,
  .match => [Bytes.Pattern, Bytes.Pattern] either {
    .end Result<e, !>,
    .fail self@attempt,
    .match (Bytes, Bytes) self,
  },
  .matchEnd => [Bytes.Pattern, Bytes.Pattern] either {
    .end Result<e, !>,
    .fail self@attempt,
    .match (Bytes, Bytes)!,
  },
  .remainder => Result<e, Bytes>,
}

A streaming byte parser, parameterized by an error type e. Works like String.Parser but operates on raw bytes.

Operations:

  • .close — close the parser.
  • .remainder — consume the parser and return all remaining bytes.
  • .byte — read the next byte. Returns .end or .byte(b).
  • .match(prefix, suffix) — find the leftmost split where prefix matches the left part and suffix matches the longest possible right part. Returns .match(prefix_bytes, suffix_bytes) on success, .fail if no match (parser position unchanged), or .end if input is empty.
  • .matchEnd(prefix, suffix) — like .match, but the suffix extends to the end of input. Terminates the parser on success.

Use .begin/.loop (from the recursive wrapper) to iterate over multiple matches.

type Bytes.Pattern = recursive either {
  .and List<self>,
  .bytes Bytes,
  .concat List<self>,
  .empty !,
  .max Nat,
  .min Nat,
  .non Byte.Class,
  .one Byte.Class,
  .or List<self>,
  .repeat self,
  .repeat1 self,
}

A pattern for matching within byte sequences.

Atomic patterns:

  • .empty! — matches empty bytes.
  • .bytes b — matches literal bytes.
  • .one class — matches a single byte of the given Byte.Class.
  • .non class — matches a single byte NOT in the given Byte.Class.
  • .min n — matches at least n bytes (any).
  • .max n — matches at most n bytes (any).

Combinators:

  • .repeat p — matches zero or more repetitions of pattern p.
  • .repeat1 p — matches one or more repetitions of pattern p.
  • .concat ps — matches a sequence of patterns in order.
  • .and ps — matches only if all patterns match the same input.
  • .or ps — matches if any of the patterns match.
type Bytes.Reader<e> = recursive choice {
  .close => Result<e, !>,
  .read => Result<e, either {
    .chunk (Bytes) self,
    .end !,
  }>,
}

A streaming byte reader, parameterized by an error type e.

  • .close — close the reader and return any error.
  • .read — read the next chunk. Returns .end when exhausted, or .chunk(bytes) with the next chunk of data.
type Bytes.Writer<e> = iterative choice {
  .close => Result<e, !>,
  .flush => Result<e, self>,
  .write => [Bytes] Result<e, self>,
}

A streaming byte writer, parameterized by an error type e.

  • .close — close the writer, flushing any pending data.
  • .flush — flush pending data without closing.
  • .write(bytes) — write a chunk of bytes.
dec Bytes.Length : [Bytes] Nat

Returns the length of a byte sequence.

dec Bytes.Parser : [Bytes] Bytes.Parser<either {}>

Creates a byte Parser from a byte sequence. The error type is either {} (impossible).

dec Bytes.PipeReader : [type e, [Bytes.Writer<!>] Result<e, !>] Bytes.Reader<e>

Creates a Reader from a function that writes to a Writer. The function receives a Writer<!> whose writes fail with ! if the reader's consumer closes early, signaling the writer to stop. The function returns Result<e, !> to propagate errors to the reader.

Bytes.PipeReader(type MyError, [w]
  catch ! => .ok! in
  do {
    w.write("hello").try
    w.close.try
  } in .ok!
)
dec Bytes.Reader : [Bytes] Bytes.Reader<either {}>

Creates a Reader from a byte sequence. The error type is either {} (impossible).