silo:std.bytes

Source src/silo:std.bytes

1##! `Bytes` — contiguous byte sequence.
2##!
3##! `Bytes` is a newtype over `(Vec Byte)` with its own dispatch
4##! identity; every method lives directly on `:impl Bytes`.
5##!
6##! Seq-hierarchy impls (`Foldable`, `Mappable`, `Filterable`,
7##! `Chainable`, `Zippable`) and `Concat` arrive alongside the wider
8##! Seq wiring.
9
10:use
11  :open core AnyInt AnyUInt Bool Byte Bytes Option Result Str Vec
12:end
13
14:impl Bytes
15  # si[impl stdlib.bytes.len]
16  ## Number of bytes in the sequence. O(1).
17  .len ( Bytes -> AnyInt )
18    bytes-len-intrinsic ;
19
20  # si[impl stdlib.bytes.is-empty]
21  ## True iff the sequence has zero bytes.
22  .is-empty ( Bytes -> Bool )
23    bytes-is-empty-intrinsic ;
24
25  # si[impl stdlib.bytes.get]
26  ## Byte at `index` (0-based) as `(Option AnyUInt)`; `None` if out of bounds.
27  .get ( AnyInt Bytes -> (Option AnyUInt) )
28    bytes-get-intrinsic ;
29
30  # si[impl stdlib.bytes.slice]
31  ## Half-open slice [start, end) as a new `Bytes`. Out-of-range or
32  ## inverted bounds yield an empty `Bytes`.
33  .slice ( AnyInt AnyInt Bytes -> Bytes )
34    bytes-slice-intrinsic ;
35
36  # si[impl stdlib.bytes.to-hex]
37  ## Lowercase hex (two chars per byte) — always valid ASCII.
38  .to-hex ( Bytes -> Str )
39    bytes-to-hex-intrinsic ;
40
41  # si[impl stdlib.bytes.to-base64]
42  ## Standard Base64 (RFC 4648) with `=` padding.
43  .to-base64 ( Bytes -> Str )
44    bytes-to-base64-intrinsic ;
45
46  # si[impl stdlib.bytes.to-str]
47  ## Validate as UTF-8 and return `Ok str` / `Err message`.
48  .to-str ( Bytes -> (Result Str Str) )
49    bytes-to-str-intrinsic ;
50
51  # si[impl stdlib.bytes.concat]
52  ## Append `b` to `a` (same as `.chain` in the spec).
53  .concat ( Bytes Bytes -> Bytes )
54    bytes-concat-intrinsic ;
55
56  # si[impl stdlib.bytes.from-be-bytes]
57  ## Decode a big-endian integer from the bytes. Length MUST be 1, 2, 4, or 8.
58  .from-be-bytes ( Bytes -> AnyInt )
59    bytes-from-be-intrinsic ;
60
61  # si[impl stdlib.bytes.from-le-bytes]
62  ## Decode a little-endian integer from the bytes. Length MUST be 1, 2, 4, or 8.
63  .from-le-bytes ( Bytes -> AnyInt )
64    bytes-from-le-intrinsic ;
65
66  # si[impl stdlib.bytes.from-str+1]
67  ## `(Bytes .from-str)` — `Str` → `Bytes`. Always succeeds because every
68  ## `Str` is valid UTF-8, and valid UTF-8 is a valid byte sequence.
69  ## Qualified dispatch: `"abc" (Bytes .from-str)`.
70  .from-str ( Str -> Bytes )
71    bytes-from-str-intrinsic ;
72
73  # si[impl stdlib.bytes.from-hex+1]
74  ## `(Bytes .from-hex)` — decode a lowercase-or-uppercase hex string into
75  ## `Bytes`. Returns `Err` with a message on odd length or non-hex
76  ## characters. Qualified dispatch: `"cafe" (Bytes .from-hex)`.
77  .from-hex ( Str -> (Result Bytes Str) )
78    bytes-from-hex-intrinsic ;
79
80  # si[impl stdlib.bytes.from-base64+1]
81  ## `(Bytes .from-base64)` — decode a RFC 4648 standard Base64 string
82  ## into `Bytes`. Qualified dispatch: `"aGVsbG8=" (Bytes .from-base64)`.
83  .from-base64 ( Str -> (Result Bytes Str) )
84    bytes-from-base64-intrinsic ;
85:end
86
87:impl (Int range)
88  # si[impl stdlib.bytes.to-be-bytes+1]
89  ## `.to-be-bytes` — encode an integer as an 8-byte big-endian sequence
90  ## (Rust's `i64::to_be_bytes`). Dispatches on the integer's type.
91  .to-be-bytes ( (Int range) -> Bytes )
92    int-to-be-bytes-intrinsic ;
93
94  # si[impl stdlib.bytes.to-le-bytes+1]
95  ## `.to-le-bytes` — encode an integer as an 8-byte little-endian
96  ## sequence (Rust's `i64::to_le_bytes`).
97  .to-le-bytes ( (Int range) -> Bytes )
98    int-to-le-bytes-intrinsic ;
99:end