Same thing as StringTable in Zig's src/Wasm.zig
pub const StringTable = struct
pub const StringTable = struct {
data: std.ArrayList(u8) = .empty,
map: std.HashMapUnmanaged(u32, void, std.hash_map.StringIndexContext, std.hash_map.default_max_load_percentage) = .empty,
pub fn deinit(self: *StringTable, allocator: Allocator) void {
self.data.deinit(allocator);
self.map.deinit(allocator);
}
pub fn put(self: *StringTable, allocator: Allocator, value: []const u8) !u32 {
const result = try self.map.getOrPutContextAdapted(
allocator,
value,
std.hash_map.StringIndexAdapter{ .bytes = &self.data },
.{ .bytes = &self.data },
);
if (result.found_existing) {
return result.key_ptr.*;
}
try self.data.ensureUnusedCapacity(allocator, value.len + 1);
const offset: u32 = @intCast(self.data.items.len);
self.data.appendSliceAssumeCapacity(value);
self.data.appendAssumeCapacity(0);
result.key_ptr.* = offset;
return offset;
}
pub fn get(self: StringTable, offset: u32) []const u8 {
std.debug.assert(offset < self.data.items.len);
return std.mem.sliceTo(@as([*:0]const u8, @ptrCast(self.data.items.ptr + offset)), 0);
}
pub fn getOffset(self: *StringTable, value: []const u8) ?u32 {
return self.map.getKeyAdapted(
value,
std.hash_map.StringIndexAdapter{ .bytes = &self.data },
);
}
}