Source
pub fn final(self: *XxHash3) u64 {
std.debug.assert(self.buffered <= self.total_len);
std.debug.assert(self.buffered <= self.buffer.len);
// Use Oneshot hashing for smaller sizes as it doesn't use Accumulator like hashLong.
if (self.total_len <= 240) {
return hash(self.accumulator.seed, self.buffer[0..self.total_len]);
}
// Make a copy of the Accumulator state in case `self` needs to update() / be used later.
var accumulator_copy = self.accumulator;
var last_block_copy: [@sizeOf(Block)]u8 = undefined;
// Digest the last block onthe Accumulator copy.
return accumulator_copy.digest(self.total_len, last_block: {
if (self.buffered >= @sizeOf(Block)) {
const block_count = ((self.buffered - 1) / @sizeOf(Block)) * @sizeOf(Block);
accumulator_copy.consume(std.mem.bytesAsSlice(Block, self.buffer[0..block_count]));
break :last_block @ptrCast(self.buffer[self.buffered - @sizeOf(Block) ..][0..@sizeOf(Block)]);
} else {
const remaining = @sizeOf(Block) - self.buffered;
@memcpy(last_block_copy[0..remaining], self.buffer[self.buffer.len - remaining ..][0..remaining]);
@memcpy(last_block_copy[remaining..][0..self.buffered], self.buffer[0..self.buffered]);
break :last_block @ptrCast(&last_block_copy);
}
});
}