Type Function Hashed [src]

Provides a Writer implementation based on calling Hasher.update, sending all data also to an underlying Writer. When using this, the underlying writer is best unbuffered because all writes are passed on directly to it. This implementation makes suboptimal buffering decisions due to being generic. A better solution will involve creating a writer for each hash function, where the splat buffer can be tailored to the hash implementation details. Contrast with Hashing which terminates the stream pipeline.

Prototype

pub fn Hashed(comptime Hasher: type) type

Parameters

Hasher: type

Source

pub fn Hashed(comptime Hasher: type) type { return struct { out: *Writer, hasher: Hasher, writer: Writer, pub fn init(out: *Writer, buffer: []u8) @This() { return .initHasher(out, .{}, buffer); } pub fn initHasher(out: *Writer, hasher: Hasher, buffer: []u8) @This() { return .{ .out = out, .hasher = hasher, .writer = .{ .buffer = buffer, .vtable = &.{ .drain = @This().drain }, }, }; } fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize { const this: *@This() = @alignCast(@fieldParentPtr("writer", w)); const aux = w.buffered(); const aux_n = try this.out.writeSplatHeader(aux, data, splat); if (aux_n < w.end) { this.hasher.update(w.buffer[0..aux_n]); const remaining = w.buffer[aux_n..w.end]; @memmove(w.buffer[0..remaining.len], remaining); w.end = remaining.len; return 0; } this.hasher.update(aux); const n = aux_n - w.end; w.end = 0; var remaining: usize = n; for (data[0 .. data.len - 1]) |slice| { if (remaining <= slice.len) { this.hasher.update(slice[0..remaining]); return n; } remaining -= slice.len; this.hasher.update(slice); } const pattern = data[data.len - 1]; assert(remaining <= splat * pattern.len); switch (pattern.len) { 0 => { assert(remaining == 0); }, 1 => { var buffer: [64]u8 = undefined; @memset(&buffer, pattern[0]); while (remaining > 0) { const update_len = @min(remaining, buffer.len); this.hasher.update(buffer[0..update_len]); remaining -= update_len; } }, else => { while (remaining > 0) { const update_len = @min(remaining, pattern.len); this.hasher.update(pattern[0..update_len]); remaining -= update_len; } }, } return n; } }; }