hash.zig (2488B)
1 const Obj = @import("gc.zig").GC.Obj; 2 const Value = @import("value.zig").Value; 3 4 pub fn hash_append_t(T: type) fn (u32, T) u32 { 5 return switch (T) { 6 []const u8, []u8 => struct { 7 pub fn fun(old: u32, val: T) u32 { 8 var ret = old; 9 for (val) |char| { 10 ret = (ret ^ char) *% 16777619; 11 } 12 return ret; 13 } 14 }.fun, 15 f64 => struct { 16 pub fn fun(old: u32, val: T) u32 { 17 const vali: *const u64 = @ptrCast(&val); 18 const int = vali.* & 0xfffffffffffff000; 19 const ptr: [*]const u8 = @ptrCast(&int); 20 return hash_append_t([]const u8)(old, ptr[0..@sizeOf(T)]); 21 } 22 }.fun, 23 bool => struct { 24 pub fn fun(old: u32, val: T) u32 { 25 return hash_append_t([]const u8)(old, if (val) "\xff" else "\x00"); 26 } 27 }.fun, 28 else => @compileError("hash_append_t(" ++ @typeName(T) ++ "): Unsupported type"), 29 }; 30 } 31 32 pub fn hash_append(ret: u32, val: anytype) u32 { 33 return hash_append_t(@TypeOf(val))(ret, val); 34 } 35 36 pub fn hash_t(T: type) fn (T) u32 { 37 return switch (T) { 38 *Obj.String, *const Obj.String => struct { 39 pub fn fun(val: T) u32 { 40 return val.hash; 41 } 42 }.fun, 43 *Obj, *const Obj => struct { 44 pub fn fun(val: T) u32 { 45 return switch (val.type) { 46 .String => hash_append_t([]const u8)(hash(val.cast(.String) catch unreachable), "\x01"), 47 inline else => |tag| @panic("hash_t(Obj." ++ @tagName(tag) ++ "): Unsupported type"), 48 }; 49 } 50 }.fun, 51 Value => struct { 52 pub fn fun(val: T) u32 { 53 return switch(val) { 54 .number => |v| hash_append_t([]const u8)(hash(v), "\x01"), 55 .char => |v| hash_t([]const u8)(&[_]u8{v, 2}), 56 .bool => |v| hash_append_t([]const u8)(hash(v), "\x03"), 57 .nil => hash_t([]const u8)("\x04"), 58 .obj => |v| hash_append_t([]const u8)(hash(v), "\x05"), 59 }; 60 } 61 }.fun, 62 else => struct { 63 pub fn fun(val: T) u32 { 64 return hash_append_t(T)(2166136261, val); 65 } 66 }.fun, 67 }; 68 } 69 70 pub fn hash(val: anytype) u32 { 71 return hash_t(@TypeOf(val))(val); 72 }