Module Bytes

type Bytes = Bytes

A primitive type representing a sequence of 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 either {
  .empty!,
  .ready iterative@attempt choice {
    .byte => Try<e, (Byte) self>,
    .close => Try<e, !>,
    .minMax(Bytes.Pattern, Bytes.Pattern) => Try<e, either {
      .fail self@attempt,
      .match(Bytes, Bytes) self,
    }>,
    .minMaxEnd(Bytes.Pattern, Bytes.Pattern) => Try<e, either {
      .fail self@attempt,
      .match(Bytes, Bytes)!,
    }>,
    .remainder => Try<e, Bytes>,
  },
}

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

Cases:

  • .empty! — input is cleanly exhausted.
  • .ready parser — input is available, or the underlying source has failed. In the latter case, every parser operation returns .err.

Parser operations:

  • .close — close the parser.
  • .remainder — consume the parser and return all remaining bytes.
  • .byte — read the next byte.
  • .minMax(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, or .fail if no match (parser position unchanged).
  • .minMaxEnd(prefix, suffix) — like .minMax, 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 => Try<e, !>,
  .read => Try<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 => Try<e, !>,
  .flush => Try<e, self>,
  .write(Bytes) => Try<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.Parse : [Bytes] Bytes.Parser<either {}>

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

dec Bytes.PipeReader : <e>[[Bytes.Writer<!>] Try<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 Try<e, !> to propagate errors to the reader.

Bytes.PipeReader([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).

dec Bytes.Replace : [Bytes, Bytes, Bytes] Bytes

Replaces non-overlapping occurrences of a byte sequence with another byte sequence.

Bytes.Replace("red blue red", "red", "green")
// = "green blue green"

Replaces non-overlapping pattern matches using a replacement function.

Bytes.ReplacePattern("a12b345", .repeat1.one.range(<<48>>, <<57>>)!, box [_] "#")
// = "a#b#"