DzLox

:)
git clone https://git.sr.ht/~ashymad/DzLox
Log | Files | Refs | Submodules | LICENSE

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 }