// bytes — slice operations over []u8. export fn equal(a: []u8, b: []u8) bool = { let i: i32 = 0; for (i < a.len) { if (i >= b.len) { return false; }; if (a[i] != b[i]) { return false; }; i += 1; }; return i == b.len; }; // indexbyte — first index of byte `c` in `s`. Hare-shaped optional: // (i32 | void). void variant indicates "not found". export fn indexbyte(s: []u8, c: u8) (i32 | void) = { let i: i32 = 0; for (i < s.len) { if (s[i] == c) { return i; }; i += 1; }; return; }; // rindexbyte — last index of byte `c` in `s`. Mirrors Hare's // bytes::rindex for the byte case. export fn rindexbyte(s: []u8, c: u8) (i32 | void) = { let i: i32 = s.len - 1; for (i >= 0) { if (s[i] == c) { return i; }; i -= 1; }; return; }; // index — first index of `sub` in `s`. Mirrors Hare's bytes::index // (the []u8 needle variant; the u8 needle stays as indexbyte until we // have union-arg dispatch). Empty `sub` matches at 0. export fn index(s: []u8, sub: []u8) (i32 | void) = { if (sub.len == 0) { return 0; }; if (sub.len > s.len) { return; }; let last: i32 = s.len - sub.len; let i: i32 = 0; for (i <= last) { let j: i32 = 0; let ok: bool = true; for (j < sub.len) { if (s[i + j] != sub[j]) { ok = false; j = sub.len; } else { j += 1; }; }; if (ok) { return i; }; i += 1; }; return; }; // rindex — last index of `sub` in `s`. Mirrors Hare's bytes::rindex // for the slice case. export fn rindex(s: []u8, sub: []u8) (i32 | void) = { if (sub.len == 0) { return s.len; }; if (sub.len > s.len) { return; }; let i: i32 = s.len - sub.len; for (i >= 0) { let j: i32 = 0; let ok: bool = true; for (j < sub.len) { if (s[i + j] != sub[j]) { ok = false; j = sub.len; } else { j += 1; }; }; if (ok) { return i; }; i -= 1; }; return; }; // contains — true iff `sub` appears in `s`. Mirrors Hare's // bytes::contains for the slice case. export fn contains(s: []u8, sub: []u8) bool = { let r: (i32 | void) = index(s, sub); match (r) { case let i: i32 => return true; case void => return false; }; return false; }; // hasprefix — `s` starts with `pre`. Mirrors Hare's bytes::hasprefix. export fn hasprefix(s: []u8, pre: []u8) bool = { if (pre.len > s.len) { return false; }; let i: i32 = 0; for (i < pre.len) { if (s[i] != pre[i]) { return false; }; i += 1; }; return true; }; // hassuffix — `s` ends with `suf`. Mirrors Hare's bytes::hassuffix. export fn hassuffix(s: []u8, suf: []u8) bool = { if (suf.len > s.len) { return false; }; let off: i32 = s.len - suf.len; let i: i32 = 0; for (i < suf.len) { if (s[off + i] != suf[i]) { return false; }; i += 1; }; return true; }; // reverse — in-place reverse of `s`. Mirrors Hare's bytes::reverse. export fn reverse(s: []u8) void = { let i: i32 = 0; let j: i32 = s.len - 1; for (i < j) { let t: u8 = s[i]; s[i] = s[j]; s[j] = t; i += 1; j -= 1; }; }; // zero — set every byte of `s` to 0. Mirrors Hare's bytes::zero. export fn zero(s: []u8) void = { let i: i32 = 0; for (i < s.len) { s[i] = 0u8; i += 1; }; };