summaryrefslogtreecommitdiff
path: root/src/libzisp/value/sstr.zig
diff options
context:
space:
mode:
authorTaylan Kammer <taylan.kammer@gmail.com>2025-02-17 22:31:16 +0100
committerTaylan Kammer <taylan.kammer@gmail.com>2025-02-17 22:31:16 +0100
commita81412ea9d85dd1d5d4a065cbf61c1080420860e (patch)
treee04f53d434f554c6cb7c6ce7cea9ef99167a039f /src/libzisp/value/sstr.zig
parent704411d750dd07da5d2c710807a4dceb671ec8e2 (diff)
update
Diffstat (limited to 'src/libzisp/value/sstr.zig')
-rw-r--r--src/libzisp/value/sstr.zig64
1 files changed, 63 insertions, 1 deletions
diff --git a/src/libzisp/value/sstr.zig b/src/libzisp/value/sstr.zig
index 3c0755d..c2b2859 100644
--- a/src/libzisp/value/sstr.zig
+++ b/src/libzisp/value/sstr.zig
@@ -1,3 +1,65 @@
+const std = @import("std");
+
const Value = @import("../value.zig").Value;
-// stub
+// Zig API
+
+pub fn check(v: Value) bool {
+ return v.isPacked() and
+ !v.sstr.fixnum and
+ !v.sstr.ptr and
+ v.sstr.tag == .sstr;
+}
+
+pub fn assert(v: Value) void {
+ if (!check(v)) {
+ v.dump();
+ @panic("not sstr");
+ }
+}
+
+// For now, ignore encoding, just treat it as []u8.
+
+pub fn isValidSstr(s: []const u8) bool {
+ if (s.len > 6) {
+ return false;
+ }
+ for (s) |c| {
+ if (c == 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+fn assertValidSstr(s: []const u8) void {
+ if (!isValidSstr(s)) {
+ std.debug.print("invalid sstr: {s}", .{s});
+ @panic("invalid sstr");
+ }
+}
+
+// Different ways of doing the following have been tested, including manual
+// shifting and bit masking, but memcpy always wins easily according to our
+// micro-benchmarks, both under ReleaseSafe and under ReleaseFast.
+
+pub fn pack(s: []const u8) Value {
+ assertValidSstr(s);
+ var v = Value{ .sstr = .{ .value = 0 } };
+ const dest: [*]u8 = @ptrCast(&v.sstr.value);
+ @memcpy(dest, s);
+ return v;
+}
+
+// It's tempting to inline for here to eliminate the if statement or prevent
+// need of @truncate but all alternatives were a little slower.
+
+pub fn unpack(v: Value) struct { [6]u8, u3 } {
+ var s: [6]u8 = undefined;
+ const src: *const [6]u8 = @ptrCast(&v.sstr.value);
+ @memcpy(&s, src);
+ for (0..6) |i| {
+ if (s[i] == 0) return .{ s, @truncate(i) };
+ }
+ return .{ s, 6 };
+}