| ... | ... | @@ -182,6 +182,45 @@ pub const Parser = struct { |
| 182 | 182 | return std.mem.eql(u8, a, b); |
| 183 | 183 | } |
| 184 | 184 | }; |
| 185 | |
| 186 | /// Similar to addStr but lets you change the tag so that new index types can be aliases and use the same intern storage |
| 187 | pub fn AddStrGeneric(comptime tag: u8) type { |
| 188 | return struct { |
| 189 | pub fn add(p: *Parser, alloc: std.mem.Allocator, str: string) !usize { |
| 190 | const adapter: Adapter = .{ .p = p }; |
| 191 | const res = try p.strings_map.getOrPutAdapted(alloc, str, adapter); |
| 192 | if (res.found_existing) return res.value_ptr.*; |
| 193 | errdefer p.strings_map.orderedRemoveAt(res.index); |
| 194 | const r = p.data.items.len; |
| 195 | const l = str.len; |
| 196 | try p.data.ensureUnusedCapacity(alloc, 1 + 4 + l); |
| 197 | p.data.appendAssumeCapacity(tag); |
| 198 | p.data.appendSliceAssumeCapacity(&std.mem.toBytes(@as(u32, @intCast(l)))); |
| 199 | p.data.appendSliceAssumeCapacity(str); |
| 200 | res.value_ptr.* = r; |
| 201 | return r; |
| 202 | } |
| 203 | |
| 204 | const Adapter = struct { |
| 205 | p: *const Parser, |
| 206 | |
| 207 | pub fn hash(ctx: @This(), a: string) u32 { |
| 208 | _ = ctx; |
| 209 | var hasher = std.hash.Wyhash.init(0); |
| 210 | hasher.update(a); |
| 211 | return @truncate(hasher.final()); |
| 212 | } |
| 213 | |
| 214 | pub fn eql(ctx: @This(), a: string, _: string, b_index: usize) bool { |
| 215 | const i = ctx.p.strings_map.values()[b_index]; |
| 216 | std.debug.assert(ctx.p.data.items[i] == tag); |
| 217 | const l: u32 = @bitCast(ctx.p.data.items[i..][1..][0..4].*); |
| 218 | const b = ctx.p.data.items[i..][1..][4..][0..l]; |
| 219 | return std.mem.eql(u8, a, b); |
| 220 | } |
| 221 | }; |
| 222 | }; |
| 223 | } |
| 185 | 224 | }; |
| 186 | 225 | |
| 187 | 226 | pub fn Mixin(comptime T: type) type { |