feature. See also
. The project being documented here (as the example) is the Zig library itself.
siphash.SipHash
fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) type
File
Code
fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) type {
assert(T == u64 or T == u128);
assert(c_rounds > 0 and d_rounds > 0);
return struct {
const State = SipHashStateless(T, c_rounds, d_rounds);
const Self = @This();
pub const key_length = 16;
pub const mac_length = @sizeOf(T);
pub const block_length = 8;
state: State,
buf: [8]u8,
buf_len: usize,
pub fn init(key: *const [key_length]u8) Self {
return Self{
.state = State.init(key),
.buf = undefined,
.buf_len = 0,
};
}
pub fn update(self: *Self, b: []const u8) void {
var off: usize = 0;
if (self.buf_len != 0 and self.buf_len + b.len >= 8) {
off += 8 - self.buf_len;
@memcpy(self.buf[self.buf_len..][0..off], b[0..off]);
self.state.update(self.buf[0..]);
self.buf_len = 0;
}
const remain_len = b.len - off;
const aligned_len = remain_len - (remain_len % 8);
self.state.update(b[off .. off + aligned_len]);
const b_slice = b[off + aligned_len ..];
@memcpy(self.buf[self.buf_len..][0..b_slice.len], b_slice);
self.buf_len += @as(u8, @intCast(b_slice.len));
}
pub fn peek(self: Self) [mac_length]u8 {
var copy = self;
return copy.finalResult();
}
pub fn final(self: *Self, out: *[mac_length]u8) void {
mem.writeInt(T, out, self.state.final(self.buf[0..self.buf_len]), .little);
}
pub fn finalResult(self: *Self) [mac_length]u8 {
var result: [mac_length]u8 = undefined;
self.final(&result);
return result;
}
pub fn create(out: *[mac_length]u8, msg: []const u8, key: *const [key_length]u8) void {
var ctx = Self.init(key);
ctx.update(msg);
ctx.final(out);
}
pub fn finalInt(self: *Self) T {
return self.state.final(self.buf[0..self.buf_len]);
}
pub fn toInt(msg: []const u8, key: *const [key_length]u8) T {
return State.hash(msg, key);
}
};
}