mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
62 lines
2 KiB
Zig
62 lines
2 KiB
Zig
const std = @import("std");
|
|
|
|
fn hashMaybeSeed(comptime hash_fn: anytype, seed: anytype, buf: []const u8) @typeInfo(@TypeOf(hash_fn)).Fn.return_type.? {
|
|
const HashFn = @typeInfo(@TypeOf(hash_fn)).Fn;
|
|
if (HashFn.params.len > 1) {
|
|
if (@typeInfo(HashFn.params[0].type.?) == .Int) {
|
|
return hash_fn(@intCast(seed), buf);
|
|
} else {
|
|
return hash_fn(buf, @intCast(seed));
|
|
}
|
|
} else {
|
|
return hash_fn(buf);
|
|
}
|
|
}
|
|
|
|
fn initMaybeSeed(comptime Hash: anytype, seed: anytype) Hash {
|
|
const HashFn = @typeInfo(@TypeOf(Hash.init)).Fn;
|
|
if (HashFn.params.len == 1) {
|
|
return Hash.init(@intCast(seed));
|
|
} else {
|
|
return Hash.init();
|
|
}
|
|
}
|
|
|
|
// Returns a verification code, the same as used by SMHasher.
|
|
//
|
|
// Hash keys of the form {0}, {0,1}, {0,1,2}... up to N=255, using 256-N as seed.
|
|
// First four-bytes of the hash, interpreted as little-endian is the verification code.
|
|
pub fn smhasher(comptime hash_fn: anytype) u32 {
|
|
const HashFnTy = @typeInfo(@TypeOf(hash_fn)).Fn;
|
|
const HashResult = HashFnTy.return_type.?;
|
|
const hash_size = @sizeOf(HashResult);
|
|
|
|
var buf: [256]u8 = undefined;
|
|
var buf_all: [256 * hash_size]u8 = undefined;
|
|
|
|
for (0..256) |i| {
|
|
buf[i] = @intCast(i);
|
|
const h = hashMaybeSeed(hash_fn, 256 - i, buf[0..i]);
|
|
std.mem.writeInt(HashResult, buf_all[i * hash_size ..][0..hash_size], h, .little);
|
|
}
|
|
|
|
return @truncate(hashMaybeSeed(hash_fn, 0, buf_all[0..]));
|
|
}
|
|
|
|
pub fn iterativeApi(comptime Hash: anytype) !void {
|
|
// Sum(1..32) = 528
|
|
var buf: [528]u8 = [_]u8{0} ** 528;
|
|
var len: usize = 0;
|
|
const seed = 0;
|
|
|
|
var hasher = initMaybeSeed(Hash, seed);
|
|
for (1..32) |i| {
|
|
const r = hashMaybeSeed(Hash.hash, seed, buf[0 .. len + i]);
|
|
hasher.update(buf[len..][0..i]);
|
|
const f1 = hasher.final();
|
|
const f2 = hasher.final();
|
|
if (f1 != f2) return error.IterativeHashWasNotIdempotent;
|
|
if (f1 != r) return error.IterativeHashDidNotMatchDirect;
|
|
len += i;
|
|
}
|
|
}
|