pub fn final(self: *XxHash3) u64 self: *XxHash3750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776 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: [block_bytes]u8 = undefined;
// Digest the last block on the Accumulator copy.
return accumulator_copy.digest(self.total_len, last_block: {
if (self.buffered >= block_bytes) {
const block_count = ((self.buffered - 1) / block_bytes) * block_bytes;
accumulator_copy.consume(std.mem.bytesAsSlice(InputBlock, self.buffer[0..block_count]));
break :last_block @ptrCast(self.buffer[self.buffered - block_bytes ..][0..block_bytes]);
} else {
const remaining = block_bytes - 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);
}
});
}