authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-05-09 16:59:13-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-01 16:35:29-07:00
log06b44a0afa849556f613fcc5939db99fec38883f
tree2ba6b36cc75c0480a7ccdd7ba5ec8344e1d7dee5
parentd603121dc355fee44b86a7fdf3666dce6e3ab677

update git fetching logic to new reader/writer API

- flatten std.crypto.hash.Sha1 and give it a writable interface that optimizes splats - flatten std.hash.crc and give it a writable interface that optimizes splats - remove old writer impls from std.crypto - add fs.File.Writer.moveToReader - add fs.File.Writer.seekTo - add std.io.Reader.Hashed and std.io.Writer.Hashed which are passthrough streams. Instead of passing through to null writer, use the writable interface implemented directly on hashers which doesn't have to account for passing through the data. - add std.io.BufferedWriter.writeSplatAll

28 files changed, 1190 insertions(+), 916 deletions(-)

lib/std/compress/flate.zig+5
...@@ -1,5 +1,10 @@...@@ -1,5 +1,10 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
22
3/// When decompressing, the output buffer is used as the history window, so
4/// less than this may result in failure to decompress streams that were
5/// compressed with a larger window.
6pub const max_window_len = 1 << 16;
7
3/// Deflate is a lossless data compression file format that uses a combination8/// Deflate is a lossless data compression file format that uses a combination
4/// of LZ77 and Huffman coding.9/// of LZ77 and Huffman coding.
5pub const deflate = @import("flate/deflate.zig");10pub const deflate = @import("flate/deflate.zig");
lib/std/compress/flate/inflate.zig+4
...@@ -403,6 +403,10 @@ pub fn Inflate(comptime container: Container, comptime Lookahead: type) type {...@@ -403,6 +403,10 @@ pub fn Inflate(comptime container: Container, comptime Lookahead: type) type {
403 },403 },
404 };404 };
405 }405 }
406
407 pub fn readable(self: *Self, buffer: []u8) std.io.BufferedReader {
408 return reader(self).buffered(buffer);
409 }
406 };410 };
407}411}
408412
lib/std/compress/zlib.zig+5
...@@ -2,6 +2,11 @@ const std = @import("../std.zig");...@@ -2,6 +2,11 @@ const std = @import("../std.zig");
2const deflate = @import("flate/deflate.zig");2const deflate = @import("flate/deflate.zig");
3const inflate = @import("flate/inflate.zig");3const inflate = @import("flate/inflate.zig");
44
5/// When decompressing, the output buffer is used as the history window, so
6/// less than this may result in failure to decompress streams that were
7/// compressed with a larger window.
8pub const max_window_len = std.compress.flate.max_window_len;
9
5/// Decompress compressed data from reader and write plain data to the writer.10/// Decompress compressed data from reader and write plain data to the writer.
6pub fn decompress(reader: *std.io.BufferedReader, writer: *std.io.BufferedWriter) !void {11pub fn decompress(reader: *std.io.BufferedReader, writer: *std.io.BufferedWriter) !void {
7 try inflate.decompress(.zlib, reader, writer);12 try inflate.decompress(.zlib, reader, writer);
lib/std/crypto.zig+3-3
...@@ -1,5 +1,7 @@...@@ -1,5 +1,7 @@
1//! Cryptography.1//! Cryptography.
22
3const std = @import("std.zig");
4const assert = std.debug.assert;
3const root = @import("root");5const root = @import("root");
46
5pub const timing_safe = @import("crypto/timing_safe.zig");7pub const timing_safe = @import("crypto/timing_safe.zig");
...@@ -119,7 +121,7 @@ pub const hash = struct {...@@ -119,7 +121,7 @@ pub const hash = struct {
119 pub const blake2 = @import("crypto/blake2.zig");121 pub const blake2 = @import("crypto/blake2.zig");
120 pub const Blake3 = @import("crypto/blake3.zig").Blake3;122 pub const Blake3 = @import("crypto/blake3.zig").Blake3;
121 pub const Md5 = @import("crypto/md5.zig").Md5;123 pub const Md5 = @import("crypto/md5.zig").Md5;
122 pub const Sha1 = @import("crypto/sha1.zig").Sha1;124 pub const Sha1 = @import("crypto/Sha1.zig");
123 pub const sha2 = @import("crypto/sha2.zig");125 pub const sha2 = @import("crypto/sha2.zig");
124 pub const sha3 = @import("crypto/sha3.zig");126 pub const sha3 = @import("crypto/sha3.zig");
125 pub const composition = @import("crypto/hash_composition.zig");127 pub const composition = @import("crypto/hash_composition.zig");
...@@ -217,8 +219,6 @@ pub const random = @import("crypto/tlcsprng.zig").interface;...@@ -217,8 +219,6 @@ pub const random = @import("crypto/tlcsprng.zig").interface;
217/// Encoding and decoding219/// Encoding and decoding
218pub const codecs = @import("crypto/codecs.zig");220pub const codecs = @import("crypto/codecs.zig");
219221
220const std = @import("std.zig");
221
222pub const errors = @import("crypto/errors.zig");222pub const errors = @import("crypto/errors.zig");
223223
224pub const tls = @import("crypto/tls.zig");224pub const tls = @import("crypto/tls.zig");
lib/std/crypto/Sha1.zig created+424
...@@ -0,0 +1,424 @@
1//! The SHA-1 function is now considered cryptographically broken.
2//! Namely, it is feasible to find multiple inputs producing the same hash.
3//! For a fast-performing, cryptographically secure hash function, see SHA512/256, BLAKE2 or BLAKE3.
4
5const Sha1 = @This();
6const std = @import("../std.zig");
7const mem = std.mem;
8const math = std.math;
9const assert = std.debug.assert;
10
11pub const block_length = 64;
12pub const digest_length = 20;
13pub const Options = struct {};
14
15s: [5]u32,
16/// Streaming Cache
17buf: [64]u8,
18buf_end: u8,
19total_len: u64,
20
21pub fn init(options: Options) Sha1 {
22 _ = options;
23 return .{
24 .s = [_]u32{
25 0x67452301,
26 0xEFCDAB89,
27 0x98BADCFE,
28 0x10325476,
29 0xC3D2E1F0,
30 },
31 .buf = undefined,
32 .buf_end = 0,
33 .total_len = 0,
34 };
35}
36
37pub fn hash(b: []const u8, out: *[digest_length]u8, options: Options) void {
38 var d = Sha1.init(options);
39 d.update(b);
40 d.final(out);
41}
42
43pub fn update(d: *Sha1, b: []const u8) void {
44 var off: usize = 0;
45
46 // Partial buffer exists from previous update. Copy into buffer then hash.
47 const unused_buf = d.buf[d.buf_end..];
48 if (unused_buf.len < d.buf.len and b.len >= unused_buf.len) {
49 @memcpy(unused_buf, b[0..unused_buf.len]);
50 off += unused_buf.len;
51 round(&d.s, &d.buf);
52 d.buf_end = 0;
53 }
54
55 // Full middle blocks.
56 while (off + 64 <= b.len) : (off += 64) {
57 round(&d.s, b[off..][0..64]);
58 }
59
60 // Copy any remainder for next pass.
61 const remainder = b[off..];
62 @memcpy(d.buf[d.buf_end..][0..remainder.len], remainder);
63 d.buf_end = @intCast(d.buf_end + remainder.len);
64 d.total_len += b.len;
65}
66
67pub fn peek(d: Sha1) [digest_length]u8 {
68 var copy = d;
69 return copy.finalResult();
70}
71
72pub fn final(d: *Sha1, out: *[digest_length]u8) void {
73 // The buffer here will never be completely full.
74 @memset(d.buf[d.buf_end..], 0);
75
76 // Append padding bits.
77 d.buf[d.buf_end] = 0x80;
78 d.buf_end += 1;
79
80 // > 448 mod 512 so need to add an extra round to wrap around.
81 if (64 - d.buf_end < 8) {
82 round(&d.s, d.buf[0..]);
83 @memset(d.buf[0..], 0);
84 }
85
86 // Append message length.
87 var i: usize = 1;
88 var len = d.total_len >> 5;
89 d.buf[63] = @as(u8, @intCast(d.total_len & 0x1f)) << 3;
90 while (i < 8) : (i += 1) {
91 d.buf[63 - i] = @as(u8, @intCast(len & 0xff));
92 len >>= 8;
93 }
94
95 round(&d.s, d.buf[0..]);
96
97 for (d.s, 0..) |s, j| {
98 mem.writeInt(u32, out[4 * j ..][0..4], s, .big);
99 }
100}
101
102pub fn finalResult(d: *Sha1) [digest_length]u8 {
103 var result: [digest_length]u8 = undefined;
104 d.final(&result);
105 return result;
106}
107
108pub fn round(d_s: *[5]u32, b: *const [64]u8) void {
109 var s: [16]u32 = undefined;
110
111 var v: [5]u32 = [_]u32{
112 d_s[0],
113 d_s[1],
114 d_s[2],
115 d_s[3],
116 d_s[4],
117 };
118
119 const round0a = comptime [_]RoundParam{
120 .abcdei(0, 1, 2, 3, 4, 0),
121 .abcdei(4, 0, 1, 2, 3, 1),
122 .abcdei(3, 4, 0, 1, 2, 2),
123 .abcdei(2, 3, 4, 0, 1, 3),
124 .abcdei(1, 2, 3, 4, 0, 4),
125 .abcdei(0, 1, 2, 3, 4, 5),
126 .abcdei(4, 0, 1, 2, 3, 6),
127 .abcdei(3, 4, 0, 1, 2, 7),
128 .abcdei(2, 3, 4, 0, 1, 8),
129 .abcdei(1, 2, 3, 4, 0, 9),
130 .abcdei(0, 1, 2, 3, 4, 10),
131 .abcdei(4, 0, 1, 2, 3, 11),
132 .abcdei(3, 4, 0, 1, 2, 12),
133 .abcdei(2, 3, 4, 0, 1, 13),
134 .abcdei(1, 2, 3, 4, 0, 14),
135 .abcdei(0, 1, 2, 3, 4, 15),
136 };
137 inline for (round0a) |r| {
138 s[r.i] = mem.readInt(u32, b[r.i * 4 ..][0..4], .big);
139
140 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], @as(u32, 5)) +% 0x5A827999 +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d]));
141 v[r.b] = math.rotl(u32, v[r.b], @as(u32, 30));
142 }
143
144 const round0b = comptime [_]RoundParam{
145 .abcdei(4, 0, 1, 2, 3, 16),
146 .abcdei(3, 4, 0, 1, 2, 17),
147 .abcdei(2, 3, 4, 0, 1, 18),
148 .abcdei(1, 2, 3, 4, 0, 19),
149 };
150 inline for (round0b) |r| {
151 const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf];
152 s[r.i & 0xf] = math.rotl(u32, t, @as(u32, 1));
153
154 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], @as(u32, 5)) +% 0x5A827999 +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d]));
155 v[r.b] = math.rotl(u32, v[r.b], @as(u32, 30));
156 }
157
158 const round1 = comptime [_]RoundParam{
159 .abcdei(0, 1, 2, 3, 4, 20),
160 .abcdei(4, 0, 1, 2, 3, 21),
161 .abcdei(3, 4, 0, 1, 2, 22),
162 .abcdei(2, 3, 4, 0, 1, 23),
163 .abcdei(1, 2, 3, 4, 0, 24),
164 .abcdei(0, 1, 2, 3, 4, 25),
165 .abcdei(4, 0, 1, 2, 3, 26),
166 .abcdei(3, 4, 0, 1, 2, 27),
167 .abcdei(2, 3, 4, 0, 1, 28),
168 .abcdei(1, 2, 3, 4, 0, 29),
169 .abcdei(0, 1, 2, 3, 4, 30),
170 .abcdei(4, 0, 1, 2, 3, 31),
171 .abcdei(3, 4, 0, 1, 2, 32),
172 .abcdei(2, 3, 4, 0, 1, 33),
173 .abcdei(1, 2, 3, 4, 0, 34),
174 .abcdei(0, 1, 2, 3, 4, 35),
175 .abcdei(4, 0, 1, 2, 3, 36),
176 .abcdei(3, 4, 0, 1, 2, 37),
177 .abcdei(2, 3, 4, 0, 1, 38),
178 .abcdei(1, 2, 3, 4, 0, 39),
179 };
180 inline for (round1) |r| {
181 const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf];
182 s[r.i & 0xf] = math.rotl(u32, t, @as(u32, 1));
183
184 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], @as(u32, 5)) +% 0x6ED9EBA1 +% s[r.i & 0xf] +% (v[r.b] ^ v[r.c] ^ v[r.d]);
185 v[r.b] = math.rotl(u32, v[r.b], @as(u32, 30));
186 }
187
188 const round2 = comptime [_]RoundParam{
189 .abcdei(0, 1, 2, 3, 4, 40),
190 .abcdei(4, 0, 1, 2, 3, 41),
191 .abcdei(3, 4, 0, 1, 2, 42),
192 .abcdei(2, 3, 4, 0, 1, 43),
193 .abcdei(1, 2, 3, 4, 0, 44),
194 .abcdei(0, 1, 2, 3, 4, 45),
195 .abcdei(4, 0, 1, 2, 3, 46),
196 .abcdei(3, 4, 0, 1, 2, 47),
197 .abcdei(2, 3, 4, 0, 1, 48),
198 .abcdei(1, 2, 3, 4, 0, 49),
199 .abcdei(0, 1, 2, 3, 4, 50),
200 .abcdei(4, 0, 1, 2, 3, 51),
201 .abcdei(3, 4, 0, 1, 2, 52),
202 .abcdei(2, 3, 4, 0, 1, 53),
203 .abcdei(1, 2, 3, 4, 0, 54),
204 .abcdei(0, 1, 2, 3, 4, 55),
205 .abcdei(4, 0, 1, 2, 3, 56),
206 .abcdei(3, 4, 0, 1, 2, 57),
207 .abcdei(2, 3, 4, 0, 1, 58),
208 .abcdei(1, 2, 3, 4, 0, 59),
209 };
210 inline for (round2) |r| {
211 const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf];
212 s[r.i & 0xf] = math.rotl(u32, t, @as(u32, 1));
213
214 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], @as(u32, 5)) +% 0x8F1BBCDC +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) ^ (v[r.b] & v[r.d]) ^ (v[r.c] & v[r.d]));
215 v[r.b] = math.rotl(u32, v[r.b], @as(u32, 30));
216 }
217
218 const round3 = comptime [_]RoundParam{
219 .abcdei(0, 1, 2, 3, 4, 60),
220 .abcdei(4, 0, 1, 2, 3, 61),
221 .abcdei(3, 4, 0, 1, 2, 62),
222 .abcdei(2, 3, 4, 0, 1, 63),
223 .abcdei(1, 2, 3, 4, 0, 64),
224 .abcdei(0, 1, 2, 3, 4, 65),
225 .abcdei(4, 0, 1, 2, 3, 66),
226 .abcdei(3, 4, 0, 1, 2, 67),
227 .abcdei(2, 3, 4, 0, 1, 68),
228 .abcdei(1, 2, 3, 4, 0, 69),
229 .abcdei(0, 1, 2, 3, 4, 70),
230 .abcdei(4, 0, 1, 2, 3, 71),
231 .abcdei(3, 4, 0, 1, 2, 72),
232 .abcdei(2, 3, 4, 0, 1, 73),
233 .abcdei(1, 2, 3, 4, 0, 74),
234 .abcdei(0, 1, 2, 3, 4, 75),
235 .abcdei(4, 0, 1, 2, 3, 76),
236 .abcdei(3, 4, 0, 1, 2, 77),
237 .abcdei(2, 3, 4, 0, 1, 78),
238 .abcdei(1, 2, 3, 4, 0, 79),
239 };
240 inline for (round3) |r| {
241 const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf];
242 s[r.i & 0xf] = math.rotl(u32, t, @as(u32, 1));
243
244 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], @as(u32, 5)) +% 0xCA62C1D6 +% s[r.i & 0xf] +% (v[r.b] ^ v[r.c] ^ v[r.d]);
245 v[r.b] = math.rotl(u32, v[r.b], @as(u32, 30));
246 }
247
248 d_s[0] +%= v[0];
249 d_s[1] +%= v[1];
250 d_s[2] +%= v[2];
251 d_s[3] +%= v[3];
252 d_s[4] +%= v[4];
253}
254
255pub fn writable(sha1: *Sha1, buffer: []u8) std.io.BufferedWriter {
256 return .{
257 .unbuffered_writer = .{
258 .context = sha1,
259 .vtable = &.{
260 .writeSplat = writeSplat,
261 .writeFile = std.io.Writer.unimplementedWriteFile,
262 },
263 },
264 .buffer = buffer,
265 };
266}
267
268fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {
269 const sha1: *Sha1 = @ptrCast(@alignCast(context));
270 const start_total = sha1.total_len;
271 if (sha1.buf_end == 0) {
272 try writeSplatAligned(sha1, data, splat);
273 const n: usize = @intCast(sha1.total_len - start_total);
274 if (n > 0) return n;
275 }
276 for (data[0 .. data.len - 1]) |slice| {
277 const copy_len = @min(slice.len, sha1.buf.len - sha1.buf_end);
278 @memcpy(sha1.buf[sha1.buf_end..][0..copy_len], slice[0..copy_len]);
279 sha1.total_len += copy_len;
280 if (sha1.buf.len - sha1.buf_end - copy_len == 0) {
281 round(&sha1.s, &sha1.buf);
282 sha1.buf_end = 0;
283 return @intCast(sha1.total_len - start_total);
284 }
285 sha1.buf_end = @intCast(sha1.buf_end + copy_len);
286 }
287 const slice = data[data.len - 1];
288 for (0..splat) |_| {
289 const copy_len = @min(slice.len, sha1.buf.len - sha1.buf_end);
290 @memcpy(sha1.buf[sha1.buf_end..][0..copy_len], slice[0..copy_len]);
291 sha1.total_len += copy_len;
292 if (sha1.buf.len - sha1.buf_end - copy_len == 0) {
293 round(&sha1.s, &sha1.buf);
294 sha1.buf_end = 0;
295 return @intCast(sha1.total_len - start_total);
296 }
297 sha1.buf_end = @intCast(sha1.buf_end + copy_len);
298 }
299 return @intCast(sha1.total_len - start_total);
300}
301
302fn writeSplatAligned(sha1: *Sha1, data: []const []const u8, splat: usize) std.io.Writer.Error!void {
303 assert(sha1.buf_end == 0);
304 for (data[0 .. data.len - 1]) |slice| {
305 var off: usize = 0;
306 while (off < slice.len) {
307 if (off + 64 > slice.len) {
308 sha1.total_len += off;
309 return;
310 }
311 round(&sha1.s, slice[off..][0..64]);
312 off += 64;
313 }
314 sha1.total_len += off;
315 }
316 const last = data[data.len - 1];
317 if (last.len * splat < 64) return;
318 if (last.len == 1) {
319 @memset(&sha1.buf, last[0]);
320 for (0..splat / 64) |_| round(&sha1.s, &sha1.buf);
321 sha1.total_len += (splat / 64) * 64;
322 return;
323 }
324 if (last.len >= 64) {
325 for (0..splat) |_| {
326 var off: usize = 0;
327 while (off < last.len) {
328 if (off + 64 > last.len) {
329 sha1.total_len += off;
330 return;
331 }
332 round(&sha1.s, last[off..][0..64]);
333 off += 64;
334 }
335 }
336 sha1.total_len += last.len * splat;
337 return;
338 }
339 // Opportunity: if last.len is less than 64, we could fill up the buffer
340 // with the pattern repeated then do rounds.
341}
342
343const RoundParam = struct {
344 a: usize,
345 b: usize,
346 c: usize,
347 d: usize,
348 e: usize,
349 i: u32,
350
351 fn abcdei(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam {
352 return .{
353 .a = a,
354 .b = b,
355 .c = c,
356 .d = d,
357 .e = e,
358 .i = i,
359 };
360 }
361};
362
363const htest = @import("test.zig");
364
365test "sha1 single" {
366 try htest.assertEqualHash(Sha1, "da39a3ee5e6b4b0d3255bfef95601890afd80709", "");
367 try htest.assertEqualHash(Sha1, "a9993e364706816aba3e25717850c26c9cd0d89d", "abc");
368 try htest.assertEqualHash(Sha1, "a49b2446a02c645bf419f995b67091253a04a259", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
369}
370
371test "sha1 streaming" {
372 var h = Sha1.init(.{});
373 var out: [20]u8 = undefined;
374
375 h.final(&out);
376 try htest.assertEqual("da39a3ee5e6b4b0d3255bfef95601890afd80709", out[0..]);
377
378 h = Sha1.init(.{});
379 h.update("abc");
380 h.final(&out);
381 try htest.assertEqual("a9993e364706816aba3e25717850c26c9cd0d89d", out[0..]);
382
383 h = Sha1.init(.{});
384 h.update("a");
385 h.update("b");
386 h.update("c");
387 h.final(&out);
388 try htest.assertEqual("a9993e364706816aba3e25717850c26c9cd0d89d", out[0..]);
389}
390
391test "sha1 aligned final" {
392 var block = [_]u8{0} ** Sha1.block_length;
393 var out: [Sha1.digest_length]u8 = undefined;
394
395 var h = Sha1.init(.{});
396 h.update(&block);
397 h.final(out[0..]);
398}
399
400test "splat" {
401 var vecs = [_][]const u8{
402 "hello",
403 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstuyyyyyyyyyyyyyyyyyyyyyyyyy",
404 "x",
405 };
406 const splat_len = 512;
407 const update_result = r: {
408 var sha1: Sha1 = .init(.{});
409 sha1.update(vecs[0]);
410 sha1.update(vecs[1]);
411 var buffer: [splat_len]u8 = undefined;
412 @memset(&buffer, vecs[2][0]);
413 sha1.update(&buffer);
414 break :r sha1.finalResult();
415 };
416 const stream_result = r: {
417 var sha1: Sha1 = .init(.{});
418 var bw = sha1.writable(&.{});
419 try bw.writeSplatAll(&vecs, splat_len);
420 try std.testing.expectEqual(vecs[0].len + vecs[1].len + vecs[2].len * splat_len, sha1.total_len);
421 break :r sha1.finalResult();
422 };
423 try std.testing.expectEqualSlices(u8, &update_result, &stream_result);
424}
lib/std/crypto/aegis.zig-12
...@@ -801,18 +801,6 @@ fn AegisMac(comptime T: type) type {...@@ -801,18 +801,6 @@ fn AegisMac(comptime T: type) type {
801 ctx.update(msg);801 ctx.update(msg);
802 ctx.final(out);802 ctx.final(out);
803 }803 }
804
805 pub const Error = error{};
806 pub const Writer = std.io.Writer(*Mac, Error, write);
807
808 fn write(self: *Mac, bytes: []const u8) Error!usize {
809 self.update(bytes);
810 return bytes.len;
811 }
812
813 pub fn writer(self: *Mac) Writer {
814 return .{ .context = self };
815 }
816 };804 };
817}805}
818806
lib/std/crypto/blake2.zig-12
...@@ -185,18 +185,6 @@ pub fn Blake2s(comptime out_bits: usize) type {...@@ -185,18 +185,6 @@ pub fn Blake2s(comptime out_bits: usize) type {
185 r.* ^= v[i] ^ v[i + 8];185 r.* ^= v[i] ^ v[i + 8];
186 }186 }
187 }187 }
188
189 pub const Error = error{};
190 pub const Writer = std.io.Writer(*Self, Error, write);
191
192 fn write(self: *Self, bytes: []const u8) Error!usize {
193 self.update(bytes);
194 return bytes.len;
195 }
196
197 pub fn writer(self: *Self) Writer {
198 return .{ .context = self };
199 }
200 };188 };
201}189}
202190
lib/std/crypto/blake3.zig-12
...@@ -474,18 +474,6 @@ pub const Blake3 = struct {...@@ -474,18 +474,6 @@ pub const Blake3 = struct {
474 }474 }
475 output.rootOutputBytes(out_slice);475 output.rootOutputBytes(out_slice);
476 }476 }
477
478 pub const Error = error{};
479 pub const Writer = std.io.Writer(*Blake3, Error, write);
480
481 fn write(self: *Blake3, bytes: []const u8) Error!usize {
482 self.update(bytes);
483 return bytes.len;
484 }
485
486 pub fn writer(self: *Blake3) Writer {
487 return .{ .context = self };
488 }
489};477};
490478
491// Use named type declarations to workaround crash with anonymous structs (issue #4373).479// Use named type declarations to workaround crash with anonymous structs (issue #4373).
lib/std/crypto/codecs/asn1.zig+8-15
...@@ -90,39 +90,32 @@ pub const Tag = struct {...@@ -90,39 +90,32 @@ pub const Tag = struct {
90 };90 };
91 }91 }
9292
93 pub fn encode(self: Tag, writer: anytype) @TypeOf(writer).Error!void {93 pub fn encode(self: Tag, writer: *std.io.BufferedWriter) std.io.Writer.Error!void {
94 var tag1 = FirstTag{94 var tag1: FirstTag = .{
95 .number = undefined,95 .number = undefined,
96 .constructed = self.constructed,96 .constructed = self.constructed,
97 .class = self.class,97 .class = self.class,
98 };98 };
99
100 var buffer: [3]u8 = undefined;
101 var stream = std.io.fixedBufferStream(&buffer);
102 var writer2 = stream.writer();
103
104 switch (@intFromEnum(self.number)) {99 switch (@intFromEnum(self.number)) {
105 0...std.math.maxInt(u5) => |n| {100 0...std.math.maxInt(u5) => |n| {
106 tag1.number = @intCast(n);101 tag1.number = @intCast(n);
107 writer2.writeByte(@bitCast(tag1)) catch unreachable;102 try writer.writeByte(@bitCast(tag1));
108 },103 },
109 std.math.maxInt(u5) + 1...std.math.maxInt(u7) => |n| {104 std.math.maxInt(u5) + 1...std.math.maxInt(u7) => |n| {
110 tag1.number = 15;105 tag1.number = 15;
111 const tag2 = NextTag{ .number = @intCast(n), .continues = false };106 const tag2 = NextTag{ .number = @intCast(n), .continues = false };
112 writer2.writeByte(@bitCast(tag1)) catch unreachable;107 try writer.writeByte(@bitCast(tag1));
113 writer2.writeByte(@bitCast(tag2)) catch unreachable;108 try writer.writeByte(@bitCast(tag2));
114 },109 },
115 else => |n| {110 else => |n| {
116 tag1.number = 15;111 tag1.number = 15;
117 const tag2 = NextTag{ .number = @intCast(n >> 7), .continues = true };112 const tag2 = NextTag{ .number = @intCast(n >> 7), .continues = true };
118 const tag3 = NextTag{ .number = @truncate(n), .continues = false };113 const tag3 = NextTag{ .number = @truncate(n), .continues = false };
119 writer2.writeByte(@bitCast(tag1)) catch unreachable;114 try writer.writeByte(@bitCast(tag1));
120 writer2.writeByte(@bitCast(tag2)) catch unreachable;115 try writer.writeByte(@bitCast(tag2));
121 writer2.writeByte(@bitCast(tag3)) catch unreachable;116 try writer.writeByte(@bitCast(tag3));
122 },117 },
123 }118 }
124
125 _ = try writer.write(stream.getWritten());
126 }119 }
127120
128 const FirstTag = packed struct(u8) { number: u5, constructed: bool, class: Tag.Class };121 const FirstTag = packed struct(u8) { number: u5, constructed: bool, class: Tag.Class };
lib/std/crypto/codecs/asn1/Oid.zig+24-13
...@@ -4,9 +4,12 @@...@@ -4,9 +4,12 @@
4//! organizations, or policy documents.4//! organizations, or policy documents.
5encoded: []const u8,5encoded: []const u8,
66
7pub const InitError = std.fmt.ParseIntError || error{MissingPrefix} || std.io.FixedBufferStream(u8).WriteError;7pub const EncodeError = error{
8 WriteFailed,
9 MissingPrefix,
10};
811
9pub fn fromDot(dot_notation: []const u8, out: []u8) InitError!Oid {12pub fn encode(dot_notation: []const u8, out: *std.io.BufferedWriter) EncodeError!void {
10 var split = std.mem.splitScalar(u8, dot_notation, '.');13 var split = std.mem.splitScalar(u8, dot_notation, '.');
11 const first_str = split.next() orelse return error.MissingPrefix;14 const first_str = split.next() orelse return error.MissingPrefix;
12 const second_str = split.next() orelse return error.MissingPrefix;15 const second_str = split.next() orelse return error.MissingPrefix;
...@@ -14,10 +17,7 @@ pub fn fromDot(dot_notation: []const u8, out: []u8) InitError!Oid {...@@ -14,10 +17,7 @@ pub fn fromDot(dot_notation: []const u8, out: []u8) InitError!Oid {
14 const first = try std.fmt.parseInt(u8, first_str, 10);17 const first = try std.fmt.parseInt(u8, first_str, 10);
15 const second = try std.fmt.parseInt(u8, second_str, 10);18 const second = try std.fmt.parseInt(u8, second_str, 10);
1619
17 var stream = std.io.fixedBufferStream(out);20 try out.writeByte(first * 40 + second);
18 var writer = stream.writer();
19
20 try writer.writeByte(first * 40 + second);
2121
22 var i: usize = 1;22 var i: usize = 1;
23 while (split.next()) |s| {23 while (split.next()) |s| {
...@@ -28,16 +28,26 @@ pub fn fromDot(dot_notation: []const u8, out: []u8) InitError!Oid {...@@ -28,16 +28,26 @@ pub fn fromDot(dot_notation: []const u8, out: []u8) InitError!Oid {
28 const place = std.math.pow(Arc, encoding_base, n_bytes - @as(Arc, @intCast(j)));28 const place = std.math.pow(Arc, encoding_base, n_bytes - @as(Arc, @intCast(j)));
29 const digit: u8 = @intCast(@divFloor(parsed, place));29 const digit: u8 = @intCast(@divFloor(parsed, place));
3030
31 try writer.writeByte(digit | 0x80);31 try out.writeByte(digit | 0x80);
32 parsed -= digit * place;32 parsed -= digit * place;
3333
34 i += 1;34 i += 1;
35 }35 }
36 try writer.writeByte(@intCast(parsed));36 try out.writeByte(@intCast(parsed));
37 i += 1;37 i += 1;
38 }38 }
39}
3940
40 return .{ .encoded = stream.getWritten() };41pub const InitError = std.fmt.ParseIntError || error{ MissingPrefix, BufferTooSmall };
42
43pub fn fromDot(dot_notation: []const u8, out: []u8) InitError!Oid {
44 var bw: std.io.BufferedWriter = undefined;
45 bw.initFixed(out);
46 encode(dot_notation, &bw) catch |err| switch (err) {
47 error.WriteFailed => return error.BufferTooSmall,
48 else => |e| return e,
49 };
50 return .{ .encoded = bw.getWritten() };
41}51}
4252
43test fromDot {53test fromDot {
...@@ -48,7 +58,7 @@ test fromDot {...@@ -48,7 +58,7 @@ test fromDot {
48 }58 }
49}59}
5060
51pub fn toDot(self: Oid, writer: anytype) @TypeOf(writer).Error!void {61pub fn toDot(self: Oid, writer: *std.io.BufferedWriter) std.io.Writer.Error!void {
52 const encoded = self.encoded;62 const encoded = self.encoded;
53 const first = @divTrunc(encoded[0], 40);63 const first = @divTrunc(encoded[0], 40);
54 const second = encoded[0] - first * 40;64 const second = encoded[0] - first * 40;
...@@ -80,9 +90,10 @@ test toDot {...@@ -80,9 +90,10 @@ test toDot {
80 var buf: [256]u8 = undefined;90 var buf: [256]u8 = undefined;
8191
82 for (test_cases) |t| {92 for (test_cases) |t| {
83 var stream = std.io.fixedBufferStream(&buf);93 var bw: std.io.BufferedWriter = undefined;
84 try toDot(Oid{ .encoded = t.encoded }, stream.writer());94 bw.initFixed(&buf);
85 try std.testing.expectEqualStrings(t.dot_notation, stream.getWritten());95 try toDot(Oid{ .encoded = t.encoded }, &bw);
96 try std.testing.expectEqualStrings(t.dot_notation, bw.getWritten());
86 }97 }
87}98}
8899
lib/std/crypto/phc_encoding.zig+5-3
...@@ -196,9 +196,11 @@ pub fn serialize(params: anytype, str: []u8) Error![]const u8 {...@@ -196,9 +196,11 @@ pub fn serialize(params: anytype, str: []u8) Error![]const u8 {
196196
197/// Compute the number of bytes required to serialize `params`197/// Compute the number of bytes required to serialize `params`
198pub fn calcSize(params: anytype) usize {198pub fn calcSize(params: anytype) usize {
199 var buf = io.countingWriter(io.null_writer);199 var null_writer: std.io.Writer.Null = .{};
200 serializeTo(params, buf.writer()) catch unreachable;200 var trash: [128]u8 = undefined;
201 return @as(usize, @intCast(buf.bytes_written));201 var bw = null_writer.writable(&trash);
202 serializeTo(params, &bw) catch unreachable;
203 return bw.count;
202}204}
203205
204fn serializeTo(params: anytype, out: *std.io.BufferedWriter) !void {206fn serializeTo(params: anytype, out: *std.io.BufferedWriter) !void {
lib/std/crypto/sha1.zig deleted-319
...@@ -1,319 +0,0 @@
1const std = @import("../std.zig");
2const mem = std.mem;
3const math = std.math;
4
5const RoundParam = struct {
6 a: usize,
7 b: usize,
8 c: usize,
9 d: usize,
10 e: usize,
11 i: u32,
12};
13
14fn roundParam(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam {
15 return RoundParam{
16 .a = a,
17 .b = b,
18 .c = c,
19 .d = d,
20 .e = e,
21 .i = i,
22 };
23}
24
25/// The SHA-1 function is now considered cryptographically broken.
26/// Namely, it is feasible to find multiple inputs producing the same hash.
27/// For a fast-performing, cryptographically secure hash function, see SHA512/256, BLAKE2 or BLAKE3.
28pub const Sha1 = struct {
29 const Self = @This();
30 pub const block_length = 64;
31 pub const digest_length = 20;
32 pub const Options = struct {};
33
34 s: [5]u32,
35 // Streaming Cache
36 buf: [64]u8 = undefined,
37 buf_len: u8 = 0,
38 total_len: u64 = 0,
39
40 pub fn init(options: Options) Self {
41 _ = options;
42 return Self{
43 .s = [_]u32{
44 0x67452301,
45 0xEFCDAB89,
46 0x98BADCFE,
47 0x10325476,
48 0xC3D2E1F0,
49 },
50 };
51 }
52
53 pub fn hash(b: []const u8, out: *[digest_length]u8, options: Options) void {
54 var d = Sha1.init(options);
55 d.update(b);
56 d.final(out);
57 }
58
59 pub fn update(d: *Self, b: []const u8) void {
60 var off: usize = 0;
61
62 // Partial buffer exists from previous update. Copy into buffer then hash.
63 if (d.buf_len != 0 and d.buf_len + b.len >= 64) {
64 off += 64 - d.buf_len;
65 @memcpy(d.buf[d.buf_len..][0..off], b[0..off]);
66
67 d.round(d.buf[0..]);
68 d.buf_len = 0;
69 }
70
71 // Full middle blocks.
72 while (off + 64 <= b.len) : (off += 64) {
73 d.round(b[off..][0..64]);
74 }
75
76 // Copy any remainder for next pass.
77 @memcpy(d.buf[d.buf_len..][0 .. b.len - off], b[off..]);
78 d.buf_len += @as(u8, @intCast(b[off..].len));
79
80 d.total_len += b.len;
81 }
82
83 pub fn peek(d: Self) [digest_length]u8 {
84 var copy = d;
85 return copy.finalResult();
86 }
87
88 pub fn final(d: *Self, out: *[digest_length]u8) void {
89 // The buffer here will never be completely full.
90 @memset(d.buf[d.buf_len..], 0);
91
92 // Append padding bits.
93 d.buf[d.buf_len] = 0x80;
94 d.buf_len += 1;
95
96 // > 448 mod 512 so need to add an extra round to wrap around.
97 if (64 - d.buf_len < 8) {
98 d.round(d.buf[0..]);
99 @memset(d.buf[0..], 0);
100 }
101
102 // Append message length.
103 var i: usize = 1;
104 var len = d.total_len >> 5;
105 d.buf[63] = @as(u8, @intCast(d.total_len & 0x1f)) << 3;
106 while (i < 8) : (i += 1) {
107 d.buf[63 - i] = @as(u8, @intCast(len & 0xff));
108 len >>= 8;
109 }
110
111 d.round(d.buf[0..]);
112
113 for (d.s, 0..) |s, j| {
114 mem.writeInt(u32, out[4 * j ..][0..4], s, .big);
115 }
116 }
117
118 pub fn finalResult(d: *Self) [digest_length]u8 {
119 var result: [digest_length]u8 = undefined;
120 d.final(&result);
121 return result;
122 }
123
124 fn round(d: *Self, b: *const [64]u8) void {
125 var s: [16]u32 = undefined;
126
127 var v: [5]u32 = [_]u32{
128 d.s[0],
129 d.s[1],
130 d.s[2],
131 d.s[3],
132 d.s[4],
133 };
134
135 const round0a = comptime [_]RoundParam{
136 roundParam(0, 1, 2, 3, 4, 0),
137 roundParam(4, 0, 1, 2, 3, 1),
138 roundParam(3, 4, 0, 1, 2, 2),
139 roundParam(2, 3, 4, 0, 1, 3),
140 roundParam(1, 2, 3, 4, 0, 4),
141 roundParam(0, 1, 2, 3, 4, 5),
142 roundParam(4, 0, 1, 2, 3, 6),
143 roundParam(3, 4, 0, 1, 2, 7),
144 roundParam(2, 3, 4, 0, 1, 8),
145 roundParam(1, 2, 3, 4, 0, 9),
146 roundParam(0, 1, 2, 3, 4, 10),
147 roundParam(4, 0, 1, 2, 3, 11),
148 roundParam(3, 4, 0, 1, 2, 12),
149 roundParam(2, 3, 4, 0, 1, 13),
150 roundParam(1, 2, 3, 4, 0, 14),
151 roundParam(0, 1, 2, 3, 4, 15),
152 };
153 inline for (round0a) |r| {
154 s[r.i] = mem.readInt(u32, b[r.i * 4 ..][0..4], .big);
155
156 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], @as(u32, 5)) +% 0x5A827999 +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d]));
157 v[r.b] = math.rotl(u32, v[r.b], @as(u32, 30));
158 }
159
160 const round0b = comptime [_]RoundParam{
161 roundParam(4, 0, 1, 2, 3, 16),
162 roundParam(3, 4, 0, 1, 2, 17),
163 roundParam(2, 3, 4, 0, 1, 18),
164 roundParam(1, 2, 3, 4, 0, 19),
165 };
166 inline for (round0b) |r| {
167 const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf];
168 s[r.i & 0xf] = math.rotl(u32, t, @as(u32, 1));
169
170 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], @as(u32, 5)) +% 0x5A827999 +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d]));
171 v[r.b] = math.rotl(u32, v[r.b], @as(u32, 30));
172 }
173
174 const round1 = comptime [_]RoundParam{
175 roundParam(0, 1, 2, 3, 4, 20),
176 roundParam(4, 0, 1, 2, 3, 21),
177 roundParam(3, 4, 0, 1, 2, 22),
178 roundParam(2, 3, 4, 0, 1, 23),
179 roundParam(1, 2, 3, 4, 0, 24),
180 roundParam(0, 1, 2, 3, 4, 25),
181 roundParam(4, 0, 1, 2, 3, 26),
182 roundParam(3, 4, 0, 1, 2, 27),
183 roundParam(2, 3, 4, 0, 1, 28),
184 roundParam(1, 2, 3, 4, 0, 29),
185 roundParam(0, 1, 2, 3, 4, 30),
186 roundParam(4, 0, 1, 2, 3, 31),
187 roundParam(3, 4, 0, 1, 2, 32),
188 roundParam(2, 3, 4, 0, 1, 33),
189 roundParam(1, 2, 3, 4, 0, 34),
190 roundParam(0, 1, 2, 3, 4, 35),
191 roundParam(4, 0, 1, 2, 3, 36),
192 roundParam(3, 4, 0, 1, 2, 37),
193 roundParam(2, 3, 4, 0, 1, 38),
194 roundParam(1, 2, 3, 4, 0, 39),
195 };
196 inline for (round1) |r| {
197 const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf];
198 s[r.i & 0xf] = math.rotl(u32, t, @as(u32, 1));
199
200 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], @as(u32, 5)) +% 0x6ED9EBA1 +% s[r.i & 0xf] +% (v[r.b] ^ v[r.c] ^ v[r.d]);
201 v[r.b] = math.rotl(u32, v[r.b], @as(u32, 30));
202 }
203
204 const round2 = comptime [_]RoundParam{
205 roundParam(0, 1, 2, 3, 4, 40),
206 roundParam(4, 0, 1, 2, 3, 41),
207 roundParam(3, 4, 0, 1, 2, 42),
208 roundParam(2, 3, 4, 0, 1, 43),
209 roundParam(1, 2, 3, 4, 0, 44),
210 roundParam(0, 1, 2, 3, 4, 45),
211 roundParam(4, 0, 1, 2, 3, 46),
212 roundParam(3, 4, 0, 1, 2, 47),
213 roundParam(2, 3, 4, 0, 1, 48),
214 roundParam(1, 2, 3, 4, 0, 49),
215 roundParam(0, 1, 2, 3, 4, 50),
216 roundParam(4, 0, 1, 2, 3, 51),
217 roundParam(3, 4, 0, 1, 2, 52),
218 roundParam(2, 3, 4, 0, 1, 53),
219 roundParam(1, 2, 3, 4, 0, 54),
220 roundParam(0, 1, 2, 3, 4, 55),
221 roundParam(4, 0, 1, 2, 3, 56),
222 roundParam(3, 4, 0, 1, 2, 57),
223 roundParam(2, 3, 4, 0, 1, 58),
224 roundParam(1, 2, 3, 4, 0, 59),
225 };
226 inline for (round2) |r| {
227 const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf];
228 s[r.i & 0xf] = math.rotl(u32, t, @as(u32, 1));
229
230 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], @as(u32, 5)) +% 0x8F1BBCDC +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) ^ (v[r.b] & v[r.d]) ^ (v[r.c] & v[r.d]));
231 v[r.b] = math.rotl(u32, v[r.b], @as(u32, 30));
232 }
233
234 const round3 = comptime [_]RoundParam{
235 roundParam(0, 1, 2, 3, 4, 60),
236 roundParam(4, 0, 1, 2, 3, 61),
237 roundParam(3, 4, 0, 1, 2, 62),
238 roundParam(2, 3, 4, 0, 1, 63),
239 roundParam(1, 2, 3, 4, 0, 64),
240 roundParam(0, 1, 2, 3, 4, 65),
241 roundParam(4, 0, 1, 2, 3, 66),
242 roundParam(3, 4, 0, 1, 2, 67),
243 roundParam(2, 3, 4, 0, 1, 68),
244 roundParam(1, 2, 3, 4, 0, 69),
245 roundParam(0, 1, 2, 3, 4, 70),
246 roundParam(4, 0, 1, 2, 3, 71),
247 roundParam(3, 4, 0, 1, 2, 72),
248 roundParam(2, 3, 4, 0, 1, 73),
249 roundParam(1, 2, 3, 4, 0, 74),
250 roundParam(0, 1, 2, 3, 4, 75),
251 roundParam(4, 0, 1, 2, 3, 76),
252 roundParam(3, 4, 0, 1, 2, 77),
253 roundParam(2, 3, 4, 0, 1, 78),
254 roundParam(1, 2, 3, 4, 0, 79),
255 };
256 inline for (round3) |r| {
257 const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf];
258 s[r.i & 0xf] = math.rotl(u32, t, @as(u32, 1));
259
260 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], @as(u32, 5)) +% 0xCA62C1D6 +% s[r.i & 0xf] +% (v[r.b] ^ v[r.c] ^ v[r.d]);
261 v[r.b] = math.rotl(u32, v[r.b], @as(u32, 30));
262 }
263
264 d.s[0] +%= v[0];
265 d.s[1] +%= v[1];
266 d.s[2] +%= v[2];
267 d.s[3] +%= v[3];
268 d.s[4] +%= v[4];
269 }
270
271 pub const Error = error{};
272 pub const Writer = std.io.Writer(*Self, Error, write);
273
274 fn write(self: *Self, bytes: []const u8) Error!usize {
275 self.update(bytes);
276 return bytes.len;
277 }
278
279 pub fn writer(self: *Self) Writer {
280 return .{ .context = self };
281 }
282};
283
284const htest = @import("test.zig");
285
286test "sha1 single" {
287 try htest.assertEqualHash(Sha1, "da39a3ee5e6b4b0d3255bfef95601890afd80709", "");
288 try htest.assertEqualHash(Sha1, "a9993e364706816aba3e25717850c26c9cd0d89d", "abc");
289 try htest.assertEqualHash(Sha1, "a49b2446a02c645bf419f995b67091253a04a259", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
290}
291
292test "sha1 streaming" {
293 var h = Sha1.init(.{});
294 var out: [20]u8 = undefined;
295
296 h.final(&out);
297 try htest.assertEqual("da39a3ee5e6b4b0d3255bfef95601890afd80709", out[0..]);
298
299 h = Sha1.init(.{});
300 h.update("abc");
301 h.final(&out);
302 try htest.assertEqual("a9993e364706816aba3e25717850c26c9cd0d89d", out[0..]);
303
304 h = Sha1.init(.{});
305 h.update("a");
306 h.update("b");
307 h.update("c");
308 h.final(&out);
309 try htest.assertEqual("a9993e364706816aba3e25717850c26c9cd0d89d", out[0..]);
310}
311
312test "sha1 aligned final" {
313 var block = [_]u8{0} ** Sha1.block_length;
314 var out: [Sha1.digest_length]u8 = undefined;
315
316 var h = Sha1.init(.{});
317 h.update(&block);
318 h.final(out[0..]);
319}
lib/std/crypto/sha2.zig+27-13
...@@ -95,14 +95,19 @@ fn Sha2x32(comptime iv: Iv32, digest_bits: comptime_int) type {...@@ -95,14 +95,19 @@ fn Sha2x32(comptime iv: Iv32, digest_bits: comptime_int) type {
95 pub const Options = struct {};95 pub const Options = struct {};
9696
97 s: [8]u32 align(16),97 s: [8]u32 align(16),
98 // Streaming Cache98 /// Streaming Cache
99 buf: [64]u8 = undefined,99 buf: [64]u8,
100 buf_len: u8 = 0,100 buf_len: u8,
101 total_len: u64 = 0,101 total_len: u64,
102102
103 pub fn init(options: Options) Self {103 pub fn init(options: Options) Self {
104 _ = options;104 _ = options;
105 return Self{ .s = iv };105 return .{
106 .s = iv,
107 .buf = undefined,
108 .buf_len = 0,
109 .total_len = 0,
110 };
106 }111 }
107112
108 pub fn hash(b: []const u8, out: *[digest_length]u8, options: Options) void {113 pub fn hash(b: []const u8, out: *[digest_length]u8, options: Options) void {
...@@ -377,16 +382,25 @@ fn Sha2x32(comptime iv: Iv32, digest_bits: comptime_int) type {...@@ -377,16 +382,25 @@ fn Sha2x32(comptime iv: Iv32, digest_bits: comptime_int) type {
377 for (&d.s, v) |*dv, vv| dv.* +%= vv;382 for (&d.s, v) |*dv, vv| dv.* +%= vv;
378 }383 }
379384
380 pub const Error = error{};385 pub fn writable(this: *@This(), buffer: []u8) std.io.BufferedWriter {
381 pub const Writer = std.io.Writer(*Self, Error, write);386 return .{
382387 .unbuffered_writer = .{
383 fn write(self: *Self, bytes: []const u8) Error!usize {388 .context = this,
384 self.update(bytes);389 .vtable = &.{
385 return bytes.len;390 .writeSplat = writeSplat,
391 .writeFile = std.io.Writer.unimplementedWriteFile,
392 },
393 },
394 .buffer = buffer,
395 };
386 }396 }
387397
388 pub fn writer(self: *Self) Writer {398 fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {
389 return .{ .context = self };399 const this: *@This() = @ptrCast(@alignCast(context));
400 const start_total = this.total_len;
401 for (data[0 .. data.len - 1]) |slice| this.update(slice);
402 for (0..splat) |_| this.update(data[data.len - 1]);
403 return @intCast(this.total_len - start_total);
390 }404 }
391 };405 };
392}406}
lib/std/crypto/sha3.zig-60
...@@ -80,18 +80,6 @@ pub fn Keccak(comptime f: u11, comptime output_bits: u11, comptime default_delim...@@ -80,18 +80,6 @@ pub fn Keccak(comptime f: u11, comptime output_bits: u11, comptime default_delim
80 self.st.pad();80 self.st.pad();
81 self.st.squeeze(out[0..]);81 self.st.squeeze(out[0..]);
82 }82 }
83
84 pub const Error = error{};
85 pub const Writer = std.io.Writer(*Self, Error, write);
86
87 fn write(self: *Self, bytes: []const u8) Error!usize {
88 self.update(bytes);
89 return bytes.len;
90 }
91
92 pub fn writer(self: *Self) Writer {
93 return .{ .context = self };
94 }
95 };83 };
96}84}
9785
...@@ -191,18 +179,6 @@ fn ShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime...@@ -191,18 +179,6 @@ fn ShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime
191 pub fn fillBlock(self: *Self) void {179 pub fn fillBlock(self: *Self) void {
192 self.st.fillBlock();180 self.st.fillBlock();
193 }181 }
194
195 pub const Error = error{};
196 pub const Writer = std.io.Writer(*Self, Error, write);
197
198 fn write(self: *Self, bytes: []const u8) Error!usize {
199 self.update(bytes);
200 return bytes.len;
201 }
202
203 pub fn writer(self: *Self) Writer {
204 return .{ .context = self };
205 }
206 };182 };
207}183}
208184
...@@ -284,18 +260,6 @@ fn CShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime...@@ -284,18 +260,6 @@ fn CShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime
284 pub fn fillBlock(self: *Self) void {260 pub fn fillBlock(self: *Self) void {
285 self.shaker.fillBlock();261 self.shaker.fillBlock();
286 }262 }
287
288 pub const Error = error{};
289 pub const Writer = std.io.Writer(*Self, Error, write);
290
291 fn write(self: *Self, bytes: []const u8) Error!usize {
292 self.update(bytes);
293 return bytes.len;
294 }
295
296 pub fn writer(self: *Self) Writer {
297 return .{ .context = self };
298 }
299 };263 };
300}264}
301265
...@@ -390,18 +354,6 @@ fn KMacLike(comptime security_level: u11, comptime default_delim: u8, comptime r...@@ -390,18 +354,6 @@ fn KMacLike(comptime security_level: u11, comptime default_delim: u8, comptime r
390 ctx.update(msg);354 ctx.update(msg);
391 ctx.final(out);355 ctx.final(out);
392 }356 }
393
394 pub const Error = error{};
395 pub const Writer = std.io.Writer(*Self, Error, write);
396
397 fn write(self: *Self, bytes: []const u8) Error!usize {
398 self.update(bytes);
399 return bytes.len;
400 }
401
402 pub fn writer(self: *Self) Writer {
403 return .{ .context = self };
404 }
405 };357 };
406}358}
407359
...@@ -482,18 +434,6 @@ fn TupleHashLike(comptime security_level: u11, comptime default_delim: u8, compt...@@ -482,18 +434,6 @@ fn TupleHashLike(comptime security_level: u11, comptime default_delim: u8, compt
482 }434 }
483 self.cshaker.squeeze(out);435 self.cshaker.squeeze(out);
484 }436 }
485
486 pub const Error = error{};
487 pub const Writer = std.io.Writer(*Self, Error, write);
488
489 fn write(self: *Self, bytes: []const u8) Error!usize {
490 self.update(bytes);
491 return bytes.len;
492 }
493
494 pub fn writer(self: *Self) Writer {
495 return .{ .context = self };
496 }
497 };437 };
498}438}
499439
lib/std/crypto/siphash.zig-42
...@@ -238,48 +238,6 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)...@@ -238,48 +238,6 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
238 pub fn toInt(msg: []const u8, key: *const [key_length]u8) T {238 pub fn toInt(msg: []const u8, key: *const [key_length]u8) T {
239 return State.hash(msg, key);239 return State.hash(msg, key);
240 }240 }
241
242 pub fn writer(self: *Self) std.io.Writer {
243 return .{
244 .context = self,
245 .vtable = &.{
246 .writeSplat = &writeSplat,
247 .writeFile = &writeFile,
248 },
249 };
250 }
251
252 fn writeSplat(ctx: ?*anyopaque, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {
253 const self: *Self = @alignCast(@ptrCast(ctx));
254 var len: usize = 0;
255 for (data[0 .. data.len - 1]) |slice| {
256 self.update(slice);
257 len += slice.len;
258 }
259 {
260 const slice = data[data.len - 1];
261 for (0..splat) |_| self.update(slice);
262 len += slice.len * splat;
263 }
264 return len;
265 }
266
267 fn writeFile(
268 ctx: ?*anyopaque,
269 file: std.fs.File,
270 offset: std.io.Writer.Offset,
271 limit: std.io.Writer.Limit,
272 headers_and_trailers: []const []const u8,
273 headers_len: usize,
274 ) std.io.Writer.Error!usize {
275 _ = ctx;
276 _ = file;
277 _ = offset;
278 _ = limit;
279 _ = headers_and_trailers;
280 _ = headers_len;
281 @panic("TODO");
282 }
283 };241 };
284}242}
285243
lib/std/debug/Dwarf.zig+1-1
...@@ -2176,7 +2176,7 @@ pub const ElfModule = struct {...@@ -2176,7 +2176,7 @@ pub const ElfModule = struct {
2176 parent_mapped_mem: ?[]align(std.heap.page_size_min) const u8,2176 parent_mapped_mem: ?[]align(std.heap.page_size_min) const u8,
2177 elf_filename: ?[]const u8,2177 elf_filename: ?[]const u8,
2178 ) LoadError!Dwarf.ElfModule {2178 ) LoadError!Dwarf.ElfModule {
2179 if (expected_crc) |crc| if (crc != std.hash.crc.Crc32.hash(mapped_mem)) return error.InvalidDebugInfo;2179 if (expected_crc) |crc| if (crc != std.hash.Crc32.hash(mapped_mem)) return error.InvalidDebugInfo;
21802180
2181 const hdr: *const elf.Ehdr = @ptrCast(&mapped_mem[0]);2181 const hdr: *const elf.Ehdr = @ptrCast(&mapped_mem[0]);
2182 if (!mem.eql(u8, hdr.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic;2182 if (!mem.eql(u8, hdr.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic;
lib/std/fs/File.zig+34
...@@ -934,6 +934,10 @@ pub const Reader = struct {...@@ -934,6 +934,10 @@ pub const Reader = struct {
934 };934 };
935 }935 }
936936
937 pub fn readable(r: *Reader, buffer: []u8) std.io.BufferedReader {
938 return interface(r).buffered(buffer);
939 }
940
937 pub fn getSize(r: *Reader) GetEndPosError!u64 {941 pub fn getSize(r: *Reader) GetEndPosError!u64 {
938 return r.size orelse {942 return r.size orelse {
939 if (r.size_err) |err| return err;943 if (r.size_err) |err| return err;
...@@ -1228,6 +1232,7 @@ pub const Writer = struct {...@@ -1228,6 +1232,7 @@ pub const Writer = struct {
1228 pos: u64 = 0,1232 pos: u64 = 0,
1229 sendfile_err: ?SendfileError = null,1233 sendfile_err: ?SendfileError = null,
1230 read_err: ?ReadError = null,1234 read_err: ?ReadError = null,
1235 seek_err: ?SeekError = null,
12311236
1232 pub const Mode = Reader.Mode;1237 pub const Mode = Reader.Mode;
12331238
...@@ -1250,6 +1255,20 @@ pub const Writer = struct {...@@ -1250,6 +1255,20 @@ pub const Writer = struct {
1250 };1255 };
1251 }1256 }
12521257
1258 pub fn writable(w: *Writer, buffer: []u8) std.io.BufferedWriter {
1259 return interface(w).buffered(buffer);
1260 }
1261
1262 pub fn moveToReader(w: *Writer) Reader {
1263 defer w.* = undefined;
1264 return .{
1265 .file = w.file,
1266 .mode = w.mode,
1267 .pos = w.pos,
1268 .seek_err = w.seek_err,
1269 };
1270 }
1271
1253 pub fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {1272 pub fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {
1254 const w: *Writer = @ptrCast(@alignCast(context));1273 const w: *Writer = @ptrCast(@alignCast(context));
1255 const handle = w.file.handle;1274 const handle = w.file.handle;
...@@ -1347,6 +1366,21 @@ pub const Writer = struct {...@@ -1347,6 +1366,21 @@ pub const Writer = struct {
1347 }1366 }
1348 return error.Unimplemented;1367 return error.Unimplemented;
1349 }1368 }
1369
1370 pub fn seekTo(w: *Writer, offset: u64) SeekError!void {
1371 if (w.seek_err) |err| return err;
1372 switch (w.mode) {
1373 .positional, .positional_reading => {
1374 w.pos = offset;
1375 },
1376 .streaming, .streaming_reading => {
1377 posix.lseek_SET(w.file.handle, offset) catch |err| {
1378 w.seek_err = err;
1379 return err;
1380 };
1381 },
1382 }
1383 }
1350};1384};
13511385
1352/// Defaults to positional reading; falls back to streaming.1386/// Defaults to positional reading; falls back to streaming.
lib/std/hash.zig+1-2
...@@ -6,9 +6,8 @@ pub const autoHash = auto_hash.autoHash;...@@ -6,9 +6,8 @@ pub const autoHash = auto_hash.autoHash;
6pub const autoHashStrat = auto_hash.hash;6pub const autoHashStrat = auto_hash.hash;
7pub const Strategy = auto_hash.HashStrategy;7pub const Strategy = auto_hash.HashStrategy;
88
9// pub for polynomials + generic crc32 construction
10pub const crc = @import("hash/crc.zig");9pub const crc = @import("hash/crc.zig");
11pub const Crc32 = crc.Crc32;10pub const Crc32 = crc.Crc32IsoHdlc;
1211
13const fnv = @import("hash/fnv.zig");12const fnv = @import("hash/fnv.zig");
14pub const Fnv1a_32 = fnv.Fnv1a_32;13pub const Fnv1a_32 = fnv.Fnv1a_32;
lib/std/hash/crc.zig+237-125
...@@ -1,19 +1,127 @@...@@ -1,19 +1,127 @@
1//! This file is auto-generated by tools/update_crc_catalog.zig.1const std = @import("../std.zig");
22
3const impl = @import("crc/impl.zig");3pub fn Generic(comptime W: type, comptime algorithm: Algorithm(W)) type {
44 return struct {
5pub const Crc = impl.Crc;5 const Self = @This();
6pub const Polynomial = impl.Polynomial;6 const I = if (@bitSizeOf(W) < 8) u8 else W;
7pub const Crc32WithPoly = impl.Crc32WithPoly;7 const lookup_table = blk: {
8pub const Crc32SmallWithPoly = impl.Crc32SmallWithPoly;8 @setEvalBranchQuota(2500);
99
10pub const Crc32 = Crc32IsoHdlc;10 const poly = if (algorithm.reflect_input)
11 @bitReverse(@as(I, algorithm.polynomial)) >> (@bitSizeOf(I) - @bitSizeOf(W))
12 else
13 @as(I, algorithm.polynomial) << (@bitSizeOf(I) - @bitSizeOf(W));
14
15 var table: [256]I = undefined;
16 for (&table, 0..) |*e, i| {
17 var crc: I = i;
18 if (algorithm.reflect_input) {
19 var j: usize = 0;
20 while (j < 8) : (j += 1) {
21 crc = (crc >> 1) ^ ((crc & 1) * poly);
22 }
23 } else {
24 crc <<= @bitSizeOf(I) - 8;
25 var j: usize = 0;
26 while (j < 8) : (j += 1) {
27 crc = (crc << 1) ^ (((crc >> (@bitSizeOf(I) - 1)) & 1) * poly);
28 }
29 }
30 e.* = crc;
31 }
32 break :blk table;
33 };
34
35 crc: I,
36
37 pub fn init() Self {
38 const initial = if (algorithm.reflect_input)
39 @bitReverse(@as(I, algorithm.initial)) >> (@bitSizeOf(I) - @bitSizeOf(W))
40 else
41 @as(I, algorithm.initial) << (@bitSizeOf(I) - @bitSizeOf(W));
42 return .{ .crc = initial };
43 }
44
45 inline fn tableEntry(index: I) I {
46 return lookup_table[@as(u8, @intCast(index & 0xFF))];
47 }
48
49 pub fn updateByte(self: *Self, byte: u8) void {
50 if (@bitSizeOf(I) <= 8) {
51 self.crc = tableEntry(self.crc ^ byte);
52 } else if (algorithm.reflect_input) {
53 const table_index = self.crc ^ byte;
54 self.crc = tableEntry(table_index) ^ (self.crc >> 8);
55 } else {
56 const table_index = (self.crc >> (@bitSizeOf(I) - 8)) ^ byte;
57 self.crc = tableEntry(table_index) ^ (self.crc << 8);
58 }
59 }
60
61 pub fn update(self: *Self, bytes: []const u8) void {
62 for (bytes) |byte| updateByte(self, byte);
63 }
64
65 pub fn final(self: Self) W {
66 var c = self.crc;
67 if (algorithm.reflect_input != algorithm.reflect_output) {
68 c = @bitReverse(c);
69 }
70 if (!algorithm.reflect_output) {
71 c >>= @bitSizeOf(I) - @bitSizeOf(W);
72 }
73 return @intCast(c ^ algorithm.xor_output);
74 }
75
76 pub fn hash(bytes: []const u8) W {
77 var c = Self.init();
78 c.update(bytes);
79 return c.final();
80 }
81
82 pub fn writable(self: *Self, buffer: []u8) std.io.BufferedWriter {
83 return .{
84 .unbuffered_writer = .{
85 .context = self,
86 .vtable = &.{
87 .writeSplat = writeSplat,
88 .writeFile = std.io.Writer.unimplementedWriteFile,
89 },
90 },
91 .buffer = buffer,
92 };
93 }
94
95 fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {
96 const self: *Self = @ptrCast(@alignCast(context));
97 var n: usize = 0;
98 for (data[0 .. data.len - 1]) |slice| {
99 self.update(slice);
100 n += slice.len;
101 }
102 const last = data[data.len - 1];
103 if (last.len == 1) {
104 for (0..splat) |_| self.updateByte(last[0]);
105 return n + splat;
106 } else {
107 for (0..splat) |_| self.update(last);
108 return n + last.len * splat;
109 }
110 }
111 };
112}
11113
12test {114pub fn Algorithm(comptime W: type) type {
13 _ = @import("crc/test.zig");115 return struct {
116 polynomial: W,
117 initial: W,
118 reflect_input: bool,
119 reflect_output: bool,
120 xor_output: W,
121 };
14}122}
15123
16pub const Crc3Gsm = Crc(u3, .{124pub const Crc3Gsm = Generic(u3, .{
17 .polynomial = 0x3,125 .polynomial = 0x3,
18 .initial = 0x0,126 .initial = 0x0,
19 .reflect_input = false,127 .reflect_input = false,
...@@ -21,7 +129,7 @@ pub const Crc3Gsm = Crc(u3, .{...@@ -21,7 +129,7 @@ pub const Crc3Gsm = Crc(u3, .{
21 .xor_output = 0x7,129 .xor_output = 0x7,
22});130});
23131
24pub const Crc3Rohc = Crc(u3, .{132pub const Crc3Rohc = Generic(u3, .{
25 .polynomial = 0x3,133 .polynomial = 0x3,
26 .initial = 0x7,134 .initial = 0x7,
27 .reflect_input = true,135 .reflect_input = true,
...@@ -29,7 +137,7 @@ pub const Crc3Rohc = Crc(u3, .{...@@ -29,7 +137,7 @@ pub const Crc3Rohc = Crc(u3, .{
29 .xor_output = 0x0,137 .xor_output = 0x0,
30});138});
31139
32pub const Crc4G704 = Crc(u4, .{140pub const Crc4G704 = Generic(u4, .{
33 .polynomial = 0x3,141 .polynomial = 0x3,
34 .initial = 0x0,142 .initial = 0x0,
35 .reflect_input = true,143 .reflect_input = true,
...@@ -37,7 +145,7 @@ pub const Crc4G704 = Crc(u4, .{...@@ -37,7 +145,7 @@ pub const Crc4G704 = Crc(u4, .{
37 .xor_output = 0x0,145 .xor_output = 0x0,
38});146});
39147
40pub const Crc4Interlaken = Crc(u4, .{148pub const Crc4Interlaken = Generic(u4, .{
41 .polynomial = 0x3,149 .polynomial = 0x3,
42 .initial = 0xf,150 .initial = 0xf,
43 .reflect_input = false,151 .reflect_input = false,
...@@ -45,7 +153,7 @@ pub const Crc4Interlaken = Crc(u4, .{...@@ -45,7 +153,7 @@ pub const Crc4Interlaken = Crc(u4, .{
45 .xor_output = 0xf,153 .xor_output = 0xf,
46});154});
47155
48pub const Crc5EpcC1g2 = Crc(u5, .{156pub const Crc5EpcC1g2 = Generic(u5, .{
49 .polynomial = 0x09,157 .polynomial = 0x09,
50 .initial = 0x09,158 .initial = 0x09,
51 .reflect_input = false,159 .reflect_input = false,
...@@ -53,7 +161,7 @@ pub const Crc5EpcC1g2 = Crc(u5, .{...@@ -53,7 +161,7 @@ pub const Crc5EpcC1g2 = Crc(u5, .{
53 .xor_output = 0x00,161 .xor_output = 0x00,
54});162});
55163
56pub const Crc5G704 = Crc(u5, .{164pub const Crc5G704 = Generic(u5, .{
57 .polynomial = 0x15,165 .polynomial = 0x15,
58 .initial = 0x00,166 .initial = 0x00,
59 .reflect_input = true,167 .reflect_input = true,
...@@ -61,7 +169,7 @@ pub const Crc5G704 = Crc(u5, .{...@@ -61,7 +169,7 @@ pub const Crc5G704 = Crc(u5, .{
61 .xor_output = 0x00,169 .xor_output = 0x00,
62});170});
63171
64pub const Crc5Usb = Crc(u5, .{172pub const Crc5Usb = Generic(u5, .{
65 .polynomial = 0x05,173 .polynomial = 0x05,
66 .initial = 0x1f,174 .initial = 0x1f,
67 .reflect_input = true,175 .reflect_input = true,
...@@ -69,7 +177,7 @@ pub const Crc5Usb = Crc(u5, .{...@@ -69,7 +177,7 @@ pub const Crc5Usb = Crc(u5, .{
69 .xor_output = 0x1f,177 .xor_output = 0x1f,
70});178});
71179
72pub const Crc6Cdma2000A = Crc(u6, .{180pub const Crc6Cdma2000A = Generic(u6, .{
73 .polynomial = 0x27,181 .polynomial = 0x27,
74 .initial = 0x3f,182 .initial = 0x3f,
75 .reflect_input = false,183 .reflect_input = false,
...@@ -77,7 +185,7 @@ pub const Crc6Cdma2000A = Crc(u6, .{...@@ -77,7 +185,7 @@ pub const Crc6Cdma2000A = Crc(u6, .{
77 .xor_output = 0x00,185 .xor_output = 0x00,
78});186});
79187
80pub const Crc6Cdma2000B = Crc(u6, .{188pub const Crc6Cdma2000B = Generic(u6, .{
81 .polynomial = 0x07,189 .polynomial = 0x07,
82 .initial = 0x3f,190 .initial = 0x3f,
83 .reflect_input = false,191 .reflect_input = false,
...@@ -85,7 +193,7 @@ pub const Crc6Cdma2000B = Crc(u6, .{...@@ -85,7 +193,7 @@ pub const Crc6Cdma2000B = Crc(u6, .{
85 .xor_output = 0x00,193 .xor_output = 0x00,
86});194});
87195
88pub const Crc6Darc = Crc(u6, .{196pub const Crc6Darc = Generic(u6, .{
89 .polynomial = 0x19,197 .polynomial = 0x19,
90 .initial = 0x00,198 .initial = 0x00,
91 .reflect_input = true,199 .reflect_input = true,
...@@ -93,7 +201,7 @@ pub const Crc6Darc = Crc(u6, .{...@@ -93,7 +201,7 @@ pub const Crc6Darc = Crc(u6, .{
93 .xor_output = 0x00,201 .xor_output = 0x00,
94});202});
95203
96pub const Crc6G704 = Crc(u6, .{204pub const Crc6G704 = Generic(u6, .{
97 .polynomial = 0x03,205 .polynomial = 0x03,
98 .initial = 0x00,206 .initial = 0x00,
99 .reflect_input = true,207 .reflect_input = true,
...@@ -101,7 +209,7 @@ pub const Crc6G704 = Crc(u6, .{...@@ -101,7 +209,7 @@ pub const Crc6G704 = Crc(u6, .{
101 .xor_output = 0x00,209 .xor_output = 0x00,
102});210});
103211
104pub const Crc6Gsm = Crc(u6, .{212pub const Crc6Gsm = Generic(u6, .{
105 .polynomial = 0x2f,213 .polynomial = 0x2f,
106 .initial = 0x00,214 .initial = 0x00,
107 .reflect_input = false,215 .reflect_input = false,
...@@ -109,7 +217,7 @@ pub const Crc6Gsm = Crc(u6, .{...@@ -109,7 +217,7 @@ pub const Crc6Gsm = Crc(u6, .{
109 .xor_output = 0x3f,217 .xor_output = 0x3f,
110});218});
111219
112pub const Crc7Mmc = Crc(u7, .{220pub const Crc7Mmc = Generic(u7, .{
113 .polynomial = 0x09,221 .polynomial = 0x09,
114 .initial = 0x00,222 .initial = 0x00,
115 .reflect_input = false,223 .reflect_input = false,
...@@ -117,7 +225,7 @@ pub const Crc7Mmc = Crc(u7, .{...@@ -117,7 +225,7 @@ pub const Crc7Mmc = Crc(u7, .{
117 .xor_output = 0x00,225 .xor_output = 0x00,
118});226});
119227
120pub const Crc7Rohc = Crc(u7, .{228pub const Crc7Rohc = Generic(u7, .{
121 .polynomial = 0x4f,229 .polynomial = 0x4f,
122 .initial = 0x7f,230 .initial = 0x7f,
123 .reflect_input = true,231 .reflect_input = true,
...@@ -125,7 +233,7 @@ pub const Crc7Rohc = Crc(u7, .{...@@ -125,7 +233,7 @@ pub const Crc7Rohc = Crc(u7, .{
125 .xor_output = 0x00,233 .xor_output = 0x00,
126});234});
127235
128pub const Crc7Umts = Crc(u7, .{236pub const Crc7Umts = Generic(u7, .{
129 .polynomial = 0x45,237 .polynomial = 0x45,
130 .initial = 0x00,238 .initial = 0x00,
131 .reflect_input = false,239 .reflect_input = false,
...@@ -133,7 +241,7 @@ pub const Crc7Umts = Crc(u7, .{...@@ -133,7 +241,7 @@ pub const Crc7Umts = Crc(u7, .{
133 .xor_output = 0x00,241 .xor_output = 0x00,
134});242});
135243
136pub const Crc8Autosar = Crc(u8, .{244pub const Crc8Autosar = Generic(u8, .{
137 .polynomial = 0x2f,245 .polynomial = 0x2f,
138 .initial = 0xff,246 .initial = 0xff,
139 .reflect_input = false,247 .reflect_input = false,
...@@ -141,7 +249,7 @@ pub const Crc8Autosar = Crc(u8, .{...@@ -141,7 +249,7 @@ pub const Crc8Autosar = Crc(u8, .{
141 .xor_output = 0xff,249 .xor_output = 0xff,
142});250});
143251
144pub const Crc8Bluetooth = Crc(u8, .{252pub const Crc8Bluetooth = Generic(u8, .{
145 .polynomial = 0xa7,253 .polynomial = 0xa7,
146 .initial = 0x00,254 .initial = 0x00,
147 .reflect_input = true,255 .reflect_input = true,
...@@ -149,7 +257,7 @@ pub const Crc8Bluetooth = Crc(u8, .{...@@ -149,7 +257,7 @@ pub const Crc8Bluetooth = Crc(u8, .{
149 .xor_output = 0x00,257 .xor_output = 0x00,
150});258});
151259
152pub const Crc8Cdma2000 = Crc(u8, .{260pub const Crc8Cdma2000 = Generic(u8, .{
153 .polynomial = 0x9b,261 .polynomial = 0x9b,
154 .initial = 0xff,262 .initial = 0xff,
155 .reflect_input = false,263 .reflect_input = false,
...@@ -157,7 +265,7 @@ pub const Crc8Cdma2000 = Crc(u8, .{...@@ -157,7 +265,7 @@ pub const Crc8Cdma2000 = Crc(u8, .{
157 .xor_output = 0x00,265 .xor_output = 0x00,
158});266});
159267
160pub const Crc8Darc = Crc(u8, .{268pub const Crc8Darc = Generic(u8, .{
161 .polynomial = 0x39,269 .polynomial = 0x39,
162 .initial = 0x00,270 .initial = 0x00,
163 .reflect_input = true,271 .reflect_input = true,
...@@ -165,7 +273,7 @@ pub const Crc8Darc = Crc(u8, .{...@@ -165,7 +273,7 @@ pub const Crc8Darc = Crc(u8, .{
165 .xor_output = 0x00,273 .xor_output = 0x00,
166});274});
167275
168pub const Crc8DvbS2 = Crc(u8, .{276pub const Crc8DvbS2 = Generic(u8, .{
169 .polynomial = 0xd5,277 .polynomial = 0xd5,
170 .initial = 0x00,278 .initial = 0x00,
171 .reflect_input = false,279 .reflect_input = false,
...@@ -173,7 +281,7 @@ pub const Crc8DvbS2 = Crc(u8, .{...@@ -173,7 +281,7 @@ pub const Crc8DvbS2 = Crc(u8, .{
173 .xor_output = 0x00,281 .xor_output = 0x00,
174});282});
175283
176pub const Crc8GsmA = Crc(u8, .{284pub const Crc8GsmA = Generic(u8, .{
177 .polynomial = 0x1d,285 .polynomial = 0x1d,
178 .initial = 0x00,286 .initial = 0x00,
179 .reflect_input = false,287 .reflect_input = false,
...@@ -181,7 +289,7 @@ pub const Crc8GsmA = Crc(u8, .{...@@ -181,7 +289,7 @@ pub const Crc8GsmA = Crc(u8, .{
181 .xor_output = 0x00,289 .xor_output = 0x00,
182});290});
183291
184pub const Crc8GsmB = Crc(u8, .{292pub const Crc8GsmB = Generic(u8, .{
185 .polynomial = 0x49,293 .polynomial = 0x49,
186 .initial = 0x00,294 .initial = 0x00,
187 .reflect_input = false,295 .reflect_input = false,
...@@ -189,7 +297,7 @@ pub const Crc8GsmB = Crc(u8, .{...@@ -189,7 +297,7 @@ pub const Crc8GsmB = Crc(u8, .{
189 .xor_output = 0xff,297 .xor_output = 0xff,
190});298});
191299
192pub const Crc8Hitag = Crc(u8, .{300pub const Crc8Hitag = Generic(u8, .{
193 .polynomial = 0x1d,301 .polynomial = 0x1d,
194 .initial = 0xff,302 .initial = 0xff,
195 .reflect_input = false,303 .reflect_input = false,
...@@ -197,7 +305,7 @@ pub const Crc8Hitag = Crc(u8, .{...@@ -197,7 +305,7 @@ pub const Crc8Hitag = Crc(u8, .{
197 .xor_output = 0x00,305 .xor_output = 0x00,
198});306});
199307
200pub const Crc8I4321 = Crc(u8, .{308pub const Crc8I4321 = Generic(u8, .{
201 .polynomial = 0x07,309 .polynomial = 0x07,
202 .initial = 0x00,310 .initial = 0x00,
203 .reflect_input = false,311 .reflect_input = false,
...@@ -205,7 +313,7 @@ pub const Crc8I4321 = Crc(u8, .{...@@ -205,7 +313,7 @@ pub const Crc8I4321 = Crc(u8, .{
205 .xor_output = 0x55,313 .xor_output = 0x55,
206});314});
207315
208pub const Crc8ICode = Crc(u8, .{316pub const Crc8ICode = Generic(u8, .{
209 .polynomial = 0x1d,317 .polynomial = 0x1d,
210 .initial = 0xfd,318 .initial = 0xfd,
211 .reflect_input = false,319 .reflect_input = false,
...@@ -213,7 +321,7 @@ pub const Crc8ICode = Crc(u8, .{...@@ -213,7 +321,7 @@ pub const Crc8ICode = Crc(u8, .{
213 .xor_output = 0x00,321 .xor_output = 0x00,
214});322});
215323
216pub const Crc8Lte = Crc(u8, .{324pub const Crc8Lte = Generic(u8, .{
217 .polynomial = 0x9b,325 .polynomial = 0x9b,
218 .initial = 0x00,326 .initial = 0x00,
219 .reflect_input = false,327 .reflect_input = false,
...@@ -221,7 +329,7 @@ pub const Crc8Lte = Crc(u8, .{...@@ -221,7 +329,7 @@ pub const Crc8Lte = Crc(u8, .{
221 .xor_output = 0x00,329 .xor_output = 0x00,
222});330});
223331
224pub const Crc8MaximDow = Crc(u8, .{332pub const Crc8MaximDow = Generic(u8, .{
225 .polynomial = 0x31,333 .polynomial = 0x31,
226 .initial = 0x00,334 .initial = 0x00,
227 .reflect_input = true,335 .reflect_input = true,
...@@ -229,7 +337,7 @@ pub const Crc8MaximDow = Crc(u8, .{...@@ -229,7 +337,7 @@ pub const Crc8MaximDow = Crc(u8, .{
229 .xor_output = 0x00,337 .xor_output = 0x00,
230});338});
231339
232pub const Crc8MifareMad = Crc(u8, .{340pub const Crc8MifareMad = Generic(u8, .{
233 .polynomial = 0x1d,341 .polynomial = 0x1d,
234 .initial = 0xc7,342 .initial = 0xc7,
235 .reflect_input = false,343 .reflect_input = false,
...@@ -237,7 +345,7 @@ pub const Crc8MifareMad = Crc(u8, .{...@@ -237,7 +345,7 @@ pub const Crc8MifareMad = Crc(u8, .{
237 .xor_output = 0x00,345 .xor_output = 0x00,
238});346});
239347
240pub const Crc8Nrsc5 = Crc(u8, .{348pub const Crc8Nrsc5 = Generic(u8, .{
241 .polynomial = 0x31,349 .polynomial = 0x31,
242 .initial = 0xff,350 .initial = 0xff,
243 .reflect_input = false,351 .reflect_input = false,
...@@ -245,7 +353,7 @@ pub const Crc8Nrsc5 = Crc(u8, .{...@@ -245,7 +353,7 @@ pub const Crc8Nrsc5 = Crc(u8, .{
245 .xor_output = 0x00,353 .xor_output = 0x00,
246});354});
247355
248pub const Crc8Opensafety = Crc(u8, .{356pub const Crc8Opensafety = Generic(u8, .{
249 .polynomial = 0x2f,357 .polynomial = 0x2f,
250 .initial = 0x00,358 .initial = 0x00,
251 .reflect_input = false,359 .reflect_input = false,
...@@ -253,7 +361,7 @@ pub const Crc8Opensafety = Crc(u8, .{...@@ -253,7 +361,7 @@ pub const Crc8Opensafety = Crc(u8, .{
253 .xor_output = 0x00,361 .xor_output = 0x00,
254});362});
255363
256pub const Crc8Rohc = Crc(u8, .{364pub const Crc8Rohc = Generic(u8, .{
257 .polynomial = 0x07,365 .polynomial = 0x07,
258 .initial = 0xff,366 .initial = 0xff,
259 .reflect_input = true,367 .reflect_input = true,
...@@ -261,7 +369,7 @@ pub const Crc8Rohc = Crc(u8, .{...@@ -261,7 +369,7 @@ pub const Crc8Rohc = Crc(u8, .{
261 .xor_output = 0x00,369 .xor_output = 0x00,
262});370});
263371
264pub const Crc8SaeJ1850 = Crc(u8, .{372pub const Crc8SaeJ1850 = Generic(u8, .{
265 .polynomial = 0x1d,373 .polynomial = 0x1d,
266 .initial = 0xff,374 .initial = 0xff,
267 .reflect_input = false,375 .reflect_input = false,
...@@ -269,7 +377,7 @@ pub const Crc8SaeJ1850 = Crc(u8, .{...@@ -269,7 +377,7 @@ pub const Crc8SaeJ1850 = Crc(u8, .{
269 .xor_output = 0xff,377 .xor_output = 0xff,
270});378});
271379
272pub const Crc8Smbus = Crc(u8, .{380pub const Crc8Smbus = Generic(u8, .{
273 .polynomial = 0x07,381 .polynomial = 0x07,
274 .initial = 0x00,382 .initial = 0x00,
275 .reflect_input = false,383 .reflect_input = false,
...@@ -277,7 +385,7 @@ pub const Crc8Smbus = Crc(u8, .{...@@ -277,7 +385,7 @@ pub const Crc8Smbus = Crc(u8, .{
277 .xor_output = 0x00,385 .xor_output = 0x00,
278});386});
279387
280pub const Crc8Tech3250 = Crc(u8, .{388pub const Crc8Tech3250 = Generic(u8, .{
281 .polynomial = 0x1d,389 .polynomial = 0x1d,
282 .initial = 0xff,390 .initial = 0xff,
283 .reflect_input = true,391 .reflect_input = true,
...@@ -285,7 +393,7 @@ pub const Crc8Tech3250 = Crc(u8, .{...@@ -285,7 +393,7 @@ pub const Crc8Tech3250 = Crc(u8, .{
285 .xor_output = 0x00,393 .xor_output = 0x00,
286});394});
287395
288pub const Crc8Wcdma = Crc(u8, .{396pub const Crc8Wcdma = Generic(u8, .{
289 .polynomial = 0x9b,397 .polynomial = 0x9b,
290 .initial = 0x00,398 .initial = 0x00,
291 .reflect_input = true,399 .reflect_input = true,
...@@ -293,7 +401,7 @@ pub const Crc8Wcdma = Crc(u8, .{...@@ -293,7 +401,7 @@ pub const Crc8Wcdma = Crc(u8, .{
293 .xor_output = 0x00,401 .xor_output = 0x00,
294});402});
295403
296pub const Crc10Atm = Crc(u10, .{404pub const Crc10Atm = Generic(u10, .{
297 .polynomial = 0x233,405 .polynomial = 0x233,
298 .initial = 0x000,406 .initial = 0x000,
299 .reflect_input = false,407 .reflect_input = false,
...@@ -301,7 +409,7 @@ pub const Crc10Atm = Crc(u10, .{...@@ -301,7 +409,7 @@ pub const Crc10Atm = Crc(u10, .{
301 .xor_output = 0x000,409 .xor_output = 0x000,
302});410});
303411
304pub const Crc10Cdma2000 = Crc(u10, .{412pub const Crc10Cdma2000 = Generic(u10, .{
305 .polynomial = 0x3d9,413 .polynomial = 0x3d9,
306 .initial = 0x3ff,414 .initial = 0x3ff,
307 .reflect_input = false,415 .reflect_input = false,
...@@ -309,7 +417,7 @@ pub const Crc10Cdma2000 = Crc(u10, .{...@@ -309,7 +417,7 @@ pub const Crc10Cdma2000 = Crc(u10, .{
309 .xor_output = 0x000,417 .xor_output = 0x000,
310});418});
311419
312pub const Crc10Gsm = Crc(u10, .{420pub const Crc10Gsm = Generic(u10, .{
313 .polynomial = 0x175,421 .polynomial = 0x175,
314 .initial = 0x000,422 .initial = 0x000,
315 .reflect_input = false,423 .reflect_input = false,
...@@ -317,7 +425,7 @@ pub const Crc10Gsm = Crc(u10, .{...@@ -317,7 +425,7 @@ pub const Crc10Gsm = Crc(u10, .{
317 .xor_output = 0x3ff,425 .xor_output = 0x3ff,
318});426});
319427
320pub const Crc11Flexray = Crc(u11, .{428pub const Crc11Flexray = Generic(u11, .{
321 .polynomial = 0x385,429 .polynomial = 0x385,
322 .initial = 0x01a,430 .initial = 0x01a,
323 .reflect_input = false,431 .reflect_input = false,
...@@ -325,7 +433,7 @@ pub const Crc11Flexray = Crc(u11, .{...@@ -325,7 +433,7 @@ pub const Crc11Flexray = Crc(u11, .{
325 .xor_output = 0x000,433 .xor_output = 0x000,
326});434});
327435
328pub const Crc11Umts = Crc(u11, .{436pub const Crc11Umts = Generic(u11, .{
329 .polynomial = 0x307,437 .polynomial = 0x307,
330 .initial = 0x000,438 .initial = 0x000,
331 .reflect_input = false,439 .reflect_input = false,
...@@ -333,7 +441,7 @@ pub const Crc11Umts = Crc(u11, .{...@@ -333,7 +441,7 @@ pub const Crc11Umts = Crc(u11, .{
333 .xor_output = 0x000,441 .xor_output = 0x000,
334});442});
335443
336pub const Crc12Cdma2000 = Crc(u12, .{444pub const Crc12Cdma2000 = Generic(u12, .{
337 .polynomial = 0xf13,445 .polynomial = 0xf13,
338 .initial = 0xfff,446 .initial = 0xfff,
339 .reflect_input = false,447 .reflect_input = false,
...@@ -341,7 +449,7 @@ pub const Crc12Cdma2000 = Crc(u12, .{...@@ -341,7 +449,7 @@ pub const Crc12Cdma2000 = Crc(u12, .{
341 .xor_output = 0x000,449 .xor_output = 0x000,
342});450});
343451
344pub const Crc12Dect = Crc(u12, .{452pub const Crc12Dect = Generic(u12, .{
345 .polynomial = 0x80f,453 .polynomial = 0x80f,
346 .initial = 0x000,454 .initial = 0x000,
347 .reflect_input = false,455 .reflect_input = false,
...@@ -349,7 +457,7 @@ pub const Crc12Dect = Crc(u12, .{...@@ -349,7 +457,7 @@ pub const Crc12Dect = Crc(u12, .{
349 .xor_output = 0x000,457 .xor_output = 0x000,
350});458});
351459
352pub const Crc12Gsm = Crc(u12, .{460pub const Crc12Gsm = Generic(u12, .{
353 .polynomial = 0xd31,461 .polynomial = 0xd31,
354 .initial = 0x000,462 .initial = 0x000,
355 .reflect_input = false,463 .reflect_input = false,
...@@ -357,7 +465,7 @@ pub const Crc12Gsm = Crc(u12, .{...@@ -357,7 +465,7 @@ pub const Crc12Gsm = Crc(u12, .{
357 .xor_output = 0xfff,465 .xor_output = 0xfff,
358});466});
359467
360pub const Crc12Umts = Crc(u12, .{468pub const Crc12Umts = Generic(u12, .{
361 .polynomial = 0x80f,469 .polynomial = 0x80f,
362 .initial = 0x000,470 .initial = 0x000,
363 .reflect_input = false,471 .reflect_input = false,
...@@ -365,7 +473,7 @@ pub const Crc12Umts = Crc(u12, .{...@@ -365,7 +473,7 @@ pub const Crc12Umts = Crc(u12, .{
365 .xor_output = 0x000,473 .xor_output = 0x000,
366});474});
367475
368pub const Crc13Bbc = Crc(u13, .{476pub const Crc13Bbc = Generic(u13, .{
369 .polynomial = 0x1cf5,477 .polynomial = 0x1cf5,
370 .initial = 0x0000,478 .initial = 0x0000,
371 .reflect_input = false,479 .reflect_input = false,
...@@ -373,7 +481,7 @@ pub const Crc13Bbc = Crc(u13, .{...@@ -373,7 +481,7 @@ pub const Crc13Bbc = Crc(u13, .{
373 .xor_output = 0x0000,481 .xor_output = 0x0000,
374});482});
375483
376pub const Crc14Darc = Crc(u14, .{484pub const Crc14Darc = Generic(u14, .{
377 .polynomial = 0x0805,485 .polynomial = 0x0805,
378 .initial = 0x0000,486 .initial = 0x0000,
379 .reflect_input = true,487 .reflect_input = true,
...@@ -381,7 +489,7 @@ pub const Crc14Darc = Crc(u14, .{...@@ -381,7 +489,7 @@ pub const Crc14Darc = Crc(u14, .{
381 .xor_output = 0x0000,489 .xor_output = 0x0000,
382});490});
383491
384pub const Crc14Gsm = Crc(u14, .{492pub const Crc14Gsm = Generic(u14, .{
385 .polynomial = 0x202d,493 .polynomial = 0x202d,
386 .initial = 0x0000,494 .initial = 0x0000,
387 .reflect_input = false,495 .reflect_input = false,
...@@ -389,7 +497,7 @@ pub const Crc14Gsm = Crc(u14, .{...@@ -389,7 +497,7 @@ pub const Crc14Gsm = Crc(u14, .{
389 .xor_output = 0x3fff,497 .xor_output = 0x3fff,
390});498});
391499
392pub const Crc15Can = Crc(u15, .{500pub const Crc15Can = Generic(u15, .{
393 .polynomial = 0x4599,501 .polynomial = 0x4599,
394 .initial = 0x0000,502 .initial = 0x0000,
395 .reflect_input = false,503 .reflect_input = false,
...@@ -397,7 +505,7 @@ pub const Crc15Can = Crc(u15, .{...@@ -397,7 +505,7 @@ pub const Crc15Can = Crc(u15, .{
397 .xor_output = 0x0000,505 .xor_output = 0x0000,
398});506});
399507
400pub const Crc15Mpt1327 = Crc(u15, .{508pub const Crc15Mpt1327 = Generic(u15, .{
401 .polynomial = 0x6815,509 .polynomial = 0x6815,
402 .initial = 0x0000,510 .initial = 0x0000,
403 .reflect_input = false,511 .reflect_input = false,
...@@ -405,7 +513,7 @@ pub const Crc15Mpt1327 = Crc(u15, .{...@@ -405,7 +513,7 @@ pub const Crc15Mpt1327 = Crc(u15, .{
405 .xor_output = 0x0001,513 .xor_output = 0x0001,
406});514});
407515
408pub const Crc16Arc = Crc(u16, .{516pub const Crc16Arc = Generic(u16, .{
409 .polynomial = 0x8005,517 .polynomial = 0x8005,
410 .initial = 0x0000,518 .initial = 0x0000,
411 .reflect_input = true,519 .reflect_input = true,
...@@ -413,7 +521,7 @@ pub const Crc16Arc = Crc(u16, .{...@@ -413,7 +521,7 @@ pub const Crc16Arc = Crc(u16, .{
413 .xor_output = 0x0000,521 .xor_output = 0x0000,
414});522});
415523
416pub const Crc16Cdma2000 = Crc(u16, .{524pub const Crc16Cdma2000 = Generic(u16, .{
417 .polynomial = 0xc867,525 .polynomial = 0xc867,
418 .initial = 0xffff,526 .initial = 0xffff,
419 .reflect_input = false,527 .reflect_input = false,
...@@ -421,7 +529,7 @@ pub const Crc16Cdma2000 = Crc(u16, .{...@@ -421,7 +529,7 @@ pub const Crc16Cdma2000 = Crc(u16, .{
421 .xor_output = 0x0000,529 .xor_output = 0x0000,
422});530});
423531
424pub const Crc16Cms = Crc(u16, .{532pub const Crc16Cms = Generic(u16, .{
425 .polynomial = 0x8005,533 .polynomial = 0x8005,
426 .initial = 0xffff,534 .initial = 0xffff,
427 .reflect_input = false,535 .reflect_input = false,
...@@ -429,7 +537,7 @@ pub const Crc16Cms = Crc(u16, .{...@@ -429,7 +537,7 @@ pub const Crc16Cms = Crc(u16, .{
429 .xor_output = 0x0000,537 .xor_output = 0x0000,
430});538});
431539
432pub const Crc16Dds110 = Crc(u16, .{540pub const Crc16Dds110 = Generic(u16, .{
433 .polynomial = 0x8005,541 .polynomial = 0x8005,
434 .initial = 0x800d,542 .initial = 0x800d,
435 .reflect_input = false,543 .reflect_input = false,
...@@ -437,7 +545,7 @@ pub const Crc16Dds110 = Crc(u16, .{...@@ -437,7 +545,7 @@ pub const Crc16Dds110 = Crc(u16, .{
437 .xor_output = 0x0000,545 .xor_output = 0x0000,
438});546});
439547
440pub const Crc16DectR = Crc(u16, .{548pub const Crc16DectR = Generic(u16, .{
441 .polynomial = 0x0589,549 .polynomial = 0x0589,
442 .initial = 0x0000,550 .initial = 0x0000,
443 .reflect_input = false,551 .reflect_input = false,
...@@ -445,7 +553,7 @@ pub const Crc16DectR = Crc(u16, .{...@@ -445,7 +553,7 @@ pub const Crc16DectR = Crc(u16, .{
445 .xor_output = 0x0001,553 .xor_output = 0x0001,
446});554});
447555
448pub const Crc16DectX = Crc(u16, .{556pub const Crc16DectX = Generic(u16, .{
449 .polynomial = 0x0589,557 .polynomial = 0x0589,
450 .initial = 0x0000,558 .initial = 0x0000,
451 .reflect_input = false,559 .reflect_input = false,
...@@ -453,7 +561,7 @@ pub const Crc16DectX = Crc(u16, .{...@@ -453,7 +561,7 @@ pub const Crc16DectX = Crc(u16, .{
453 .xor_output = 0x0000,561 .xor_output = 0x0000,
454});562});
455563
456pub const Crc16Dnp = Crc(u16, .{564pub const Crc16Dnp = Generic(u16, .{
457 .polynomial = 0x3d65,565 .polynomial = 0x3d65,
458 .initial = 0x0000,566 .initial = 0x0000,
459 .reflect_input = true,567 .reflect_input = true,
...@@ -461,7 +569,7 @@ pub const Crc16Dnp = Crc(u16, .{...@@ -461,7 +569,7 @@ pub const Crc16Dnp = Crc(u16, .{
461 .xor_output = 0xffff,569 .xor_output = 0xffff,
462});570});
463571
464pub const Crc16En13757 = Crc(u16, .{572pub const Crc16En13757 = Generic(u16, .{
465 .polynomial = 0x3d65,573 .polynomial = 0x3d65,
466 .initial = 0x0000,574 .initial = 0x0000,
467 .reflect_input = false,575 .reflect_input = false,
...@@ -469,7 +577,7 @@ pub const Crc16En13757 = Crc(u16, .{...@@ -469,7 +577,7 @@ pub const Crc16En13757 = Crc(u16, .{
469 .xor_output = 0xffff,577 .xor_output = 0xffff,
470});578});
471579
472pub const Crc16Genibus = Crc(u16, .{580pub const Crc16Genibus = Generic(u16, .{
473 .polynomial = 0x1021,581 .polynomial = 0x1021,
474 .initial = 0xffff,582 .initial = 0xffff,
475 .reflect_input = false,583 .reflect_input = false,
...@@ -477,7 +585,7 @@ pub const Crc16Genibus = Crc(u16, .{...@@ -477,7 +585,7 @@ pub const Crc16Genibus = Crc(u16, .{
477 .xor_output = 0xffff,585 .xor_output = 0xffff,
478});586});
479587
480pub const Crc16Gsm = Crc(u16, .{588pub const Crc16Gsm = Generic(u16, .{
481 .polynomial = 0x1021,589 .polynomial = 0x1021,
482 .initial = 0x0000,590 .initial = 0x0000,
483 .reflect_input = false,591 .reflect_input = false,
...@@ -485,7 +593,7 @@ pub const Crc16Gsm = Crc(u16, .{...@@ -485,7 +593,7 @@ pub const Crc16Gsm = Crc(u16, .{
485 .xor_output = 0xffff,593 .xor_output = 0xffff,
486});594});
487595
488pub const Crc16Ibm3740 = Crc(u16, .{596pub const Crc16Ibm3740 = Generic(u16, .{
489 .polynomial = 0x1021,597 .polynomial = 0x1021,
490 .initial = 0xffff,598 .initial = 0xffff,
491 .reflect_input = false,599 .reflect_input = false,
...@@ -493,7 +601,7 @@ pub const Crc16Ibm3740 = Crc(u16, .{...@@ -493,7 +601,7 @@ pub const Crc16Ibm3740 = Crc(u16, .{
493 .xor_output = 0x0000,601 .xor_output = 0x0000,
494});602});
495603
496pub const Crc16IbmSdlc = Crc(u16, .{604pub const Crc16IbmSdlc = Generic(u16, .{
497 .polynomial = 0x1021,605 .polynomial = 0x1021,
498 .initial = 0xffff,606 .initial = 0xffff,
499 .reflect_input = true,607 .reflect_input = true,
...@@ -501,7 +609,7 @@ pub const Crc16IbmSdlc = Crc(u16, .{...@@ -501,7 +609,7 @@ pub const Crc16IbmSdlc = Crc(u16, .{
501 .xor_output = 0xffff,609 .xor_output = 0xffff,
502});610});
503611
504pub const Crc16IsoIec144433A = Crc(u16, .{612pub const Crc16IsoIec144433A = Generic(u16, .{
505 .polynomial = 0x1021,613 .polynomial = 0x1021,
506 .initial = 0xc6c6,614 .initial = 0xc6c6,
507 .reflect_input = true,615 .reflect_input = true,
...@@ -509,7 +617,7 @@ pub const Crc16IsoIec144433A = Crc(u16, .{...@@ -509,7 +617,7 @@ pub const Crc16IsoIec144433A = Crc(u16, .{
509 .xor_output = 0x0000,617 .xor_output = 0x0000,
510});618});
511619
512pub const Crc16Kermit = Crc(u16, .{620pub const Crc16Kermit = Generic(u16, .{
513 .polynomial = 0x1021,621 .polynomial = 0x1021,
514 .initial = 0x0000,622 .initial = 0x0000,
515 .reflect_input = true,623 .reflect_input = true,
...@@ -517,7 +625,7 @@ pub const Crc16Kermit = Crc(u16, .{...@@ -517,7 +625,7 @@ pub const Crc16Kermit = Crc(u16, .{
517 .xor_output = 0x0000,625 .xor_output = 0x0000,
518});626});
519627
520pub const Crc16Lj1200 = Crc(u16, .{628pub const Crc16Lj1200 = Generic(u16, .{
521 .polynomial = 0x6f63,629 .polynomial = 0x6f63,
522 .initial = 0x0000,630 .initial = 0x0000,
523 .reflect_input = false,631 .reflect_input = false,
...@@ -525,7 +633,7 @@ pub const Crc16Lj1200 = Crc(u16, .{...@@ -525,7 +633,7 @@ pub const Crc16Lj1200 = Crc(u16, .{
525 .xor_output = 0x0000,633 .xor_output = 0x0000,
526});634});
527635
528pub const Crc16M17 = Crc(u16, .{636pub const Crc16M17 = Generic(u16, .{
529 .polynomial = 0x5935,637 .polynomial = 0x5935,
530 .initial = 0xffff,638 .initial = 0xffff,
531 .reflect_input = false,639 .reflect_input = false,
...@@ -533,7 +641,7 @@ pub const Crc16M17 = Crc(u16, .{...@@ -533,7 +641,7 @@ pub const Crc16M17 = Crc(u16, .{
533 .xor_output = 0x0000,641 .xor_output = 0x0000,
534});642});
535643
536pub const Crc16MaximDow = Crc(u16, .{644pub const Crc16MaximDow = Generic(u16, .{
537 .polynomial = 0x8005,645 .polynomial = 0x8005,
538 .initial = 0x0000,646 .initial = 0x0000,
539 .reflect_input = true,647 .reflect_input = true,
...@@ -541,7 +649,7 @@ pub const Crc16MaximDow = Crc(u16, .{...@@ -541,7 +649,7 @@ pub const Crc16MaximDow = Crc(u16, .{
541 .xor_output = 0xffff,649 .xor_output = 0xffff,
542});650});
543651
544pub const Crc16Mcrf4xx = Crc(u16, .{652pub const Crc16Mcrf4xx = Generic(u16, .{
545 .polynomial = 0x1021,653 .polynomial = 0x1021,
546 .initial = 0xffff,654 .initial = 0xffff,
547 .reflect_input = true,655 .reflect_input = true,
...@@ -549,7 +657,7 @@ pub const Crc16Mcrf4xx = Crc(u16, .{...@@ -549,7 +657,7 @@ pub const Crc16Mcrf4xx = Crc(u16, .{
549 .xor_output = 0x0000,657 .xor_output = 0x0000,
550});658});
551659
552pub const Crc16Modbus = Crc(u16, .{660pub const Crc16Modbus = Generic(u16, .{
553 .polynomial = 0x8005,661 .polynomial = 0x8005,
554 .initial = 0xffff,662 .initial = 0xffff,
555 .reflect_input = true,663 .reflect_input = true,
...@@ -557,7 +665,7 @@ pub const Crc16Modbus = Crc(u16, .{...@@ -557,7 +665,7 @@ pub const Crc16Modbus = Crc(u16, .{
557 .xor_output = 0x0000,665 .xor_output = 0x0000,
558});666});
559667
560pub const Crc16Nrsc5 = Crc(u16, .{668pub const Crc16Nrsc5 = Generic(u16, .{
561 .polynomial = 0x080b,669 .polynomial = 0x080b,
562 .initial = 0xffff,670 .initial = 0xffff,
563 .reflect_input = true,671 .reflect_input = true,
...@@ -565,7 +673,7 @@ pub const Crc16Nrsc5 = Crc(u16, .{...@@ -565,7 +673,7 @@ pub const Crc16Nrsc5 = Crc(u16, .{
565 .xor_output = 0x0000,673 .xor_output = 0x0000,
566});674});
567675
568pub const Crc16OpensafetyA = Crc(u16, .{676pub const Crc16OpensafetyA = Generic(u16, .{
569 .polynomial = 0x5935,677 .polynomial = 0x5935,
570 .initial = 0x0000,678 .initial = 0x0000,
571 .reflect_input = false,679 .reflect_input = false,
...@@ -573,7 +681,7 @@ pub const Crc16OpensafetyA = Crc(u16, .{...@@ -573,7 +681,7 @@ pub const Crc16OpensafetyA = Crc(u16, .{
573 .xor_output = 0x0000,681 .xor_output = 0x0000,
574});682});
575683
576pub const Crc16OpensafetyB = Crc(u16, .{684pub const Crc16OpensafetyB = Generic(u16, .{
577 .polynomial = 0x755b,685 .polynomial = 0x755b,
578 .initial = 0x0000,686 .initial = 0x0000,
579 .reflect_input = false,687 .reflect_input = false,
...@@ -581,7 +689,7 @@ pub const Crc16OpensafetyB = Crc(u16, .{...@@ -581,7 +689,7 @@ pub const Crc16OpensafetyB = Crc(u16, .{
581 .xor_output = 0x0000,689 .xor_output = 0x0000,
582});690});
583691
584pub const Crc16Profibus = Crc(u16, .{692pub const Crc16Profibus = Generic(u16, .{
585 .polynomial = 0x1dcf,693 .polynomial = 0x1dcf,
586 .initial = 0xffff,694 .initial = 0xffff,
587 .reflect_input = false,695 .reflect_input = false,
...@@ -589,7 +697,7 @@ pub const Crc16Profibus = Crc(u16, .{...@@ -589,7 +697,7 @@ pub const Crc16Profibus = Crc(u16, .{
589 .xor_output = 0xffff,697 .xor_output = 0xffff,
590});698});
591699
592pub const Crc16Riello = Crc(u16, .{700pub const Crc16Riello = Generic(u16, .{
593 .polynomial = 0x1021,701 .polynomial = 0x1021,
594 .initial = 0xb2aa,702 .initial = 0xb2aa,
595 .reflect_input = true,703 .reflect_input = true,
...@@ -597,7 +705,7 @@ pub const Crc16Riello = Crc(u16, .{...@@ -597,7 +705,7 @@ pub const Crc16Riello = Crc(u16, .{
597 .xor_output = 0x0000,705 .xor_output = 0x0000,
598});706});
599707
600pub const Crc16SpiFujitsu = Crc(u16, .{708pub const Crc16SpiFujitsu = Generic(u16, .{
601 .polynomial = 0x1021,709 .polynomial = 0x1021,
602 .initial = 0x1d0f,710 .initial = 0x1d0f,
603 .reflect_input = false,711 .reflect_input = false,
...@@ -605,7 +713,7 @@ pub const Crc16SpiFujitsu = Crc(u16, .{...@@ -605,7 +713,7 @@ pub const Crc16SpiFujitsu = Crc(u16, .{
605 .xor_output = 0x0000,713 .xor_output = 0x0000,
606});714});
607715
608pub const Crc16T10Dif = Crc(u16, .{716pub const Crc16T10Dif = Generic(u16, .{
609 .polynomial = 0x8bb7,717 .polynomial = 0x8bb7,
610 .initial = 0x0000,718 .initial = 0x0000,
611 .reflect_input = false,719 .reflect_input = false,
...@@ -613,7 +721,7 @@ pub const Crc16T10Dif = Crc(u16, .{...@@ -613,7 +721,7 @@ pub const Crc16T10Dif = Crc(u16, .{
613 .xor_output = 0x0000,721 .xor_output = 0x0000,
614});722});
615723
616pub const Crc16Teledisk = Crc(u16, .{724pub const Crc16Teledisk = Generic(u16, .{
617 .polynomial = 0xa097,725 .polynomial = 0xa097,
618 .initial = 0x0000,726 .initial = 0x0000,
619 .reflect_input = false,727 .reflect_input = false,
...@@ -621,7 +729,7 @@ pub const Crc16Teledisk = Crc(u16, .{...@@ -621,7 +729,7 @@ pub const Crc16Teledisk = Crc(u16, .{
621 .xor_output = 0x0000,729 .xor_output = 0x0000,
622});730});
623731
624pub const Crc16Tms37157 = Crc(u16, .{732pub const Crc16Tms37157 = Generic(u16, .{
625 .polynomial = 0x1021,733 .polynomial = 0x1021,
626 .initial = 0x89ec,734 .initial = 0x89ec,
627 .reflect_input = true,735 .reflect_input = true,
...@@ -629,7 +737,7 @@ pub const Crc16Tms37157 = Crc(u16, .{...@@ -629,7 +737,7 @@ pub const Crc16Tms37157 = Crc(u16, .{
629 .xor_output = 0x0000,737 .xor_output = 0x0000,
630});738});
631739
632pub const Crc16Umts = Crc(u16, .{740pub const Crc16Umts = Generic(u16, .{
633 .polynomial = 0x8005,741 .polynomial = 0x8005,
634 .initial = 0x0000,742 .initial = 0x0000,
635 .reflect_input = false,743 .reflect_input = false,
...@@ -637,7 +745,7 @@ pub const Crc16Umts = Crc(u16, .{...@@ -637,7 +745,7 @@ pub const Crc16Umts = Crc(u16, .{
637 .xor_output = 0x0000,745 .xor_output = 0x0000,
638});746});
639747
640pub const Crc16Usb = Crc(u16, .{748pub const Crc16Usb = Generic(u16, .{
641 .polynomial = 0x8005,749 .polynomial = 0x8005,
642 .initial = 0xffff,750 .initial = 0xffff,
643 .reflect_input = true,751 .reflect_input = true,
...@@ -645,7 +753,7 @@ pub const Crc16Usb = Crc(u16, .{...@@ -645,7 +753,7 @@ pub const Crc16Usb = Crc(u16, .{
645 .xor_output = 0xffff,753 .xor_output = 0xffff,
646});754});
647755
648pub const Crc16Xmodem = Crc(u16, .{756pub const Crc16Xmodem = Generic(u16, .{
649 .polynomial = 0x1021,757 .polynomial = 0x1021,
650 .initial = 0x0000,758 .initial = 0x0000,
651 .reflect_input = false,759 .reflect_input = false,
...@@ -653,7 +761,7 @@ pub const Crc16Xmodem = Crc(u16, .{...@@ -653,7 +761,7 @@ pub const Crc16Xmodem = Crc(u16, .{
653 .xor_output = 0x0000,761 .xor_output = 0x0000,
654});762});
655763
656pub const Crc17CanFd = Crc(u17, .{764pub const Crc17CanFd = Generic(u17, .{
657 .polynomial = 0x1685b,765 .polynomial = 0x1685b,
658 .initial = 0x00000,766 .initial = 0x00000,
659 .reflect_input = false,767 .reflect_input = false,
...@@ -661,7 +769,7 @@ pub const Crc17CanFd = Crc(u17, .{...@@ -661,7 +769,7 @@ pub const Crc17CanFd = Crc(u17, .{
661 .xor_output = 0x00000,769 .xor_output = 0x00000,
662});770});
663771
664pub const Crc21CanFd = Crc(u21, .{772pub const Crc21CanFd = Generic(u21, .{
665 .polynomial = 0x102899,773 .polynomial = 0x102899,
666 .initial = 0x000000,774 .initial = 0x000000,
667 .reflect_input = false,775 .reflect_input = false,
...@@ -669,7 +777,7 @@ pub const Crc21CanFd = Crc(u21, .{...@@ -669,7 +777,7 @@ pub const Crc21CanFd = Crc(u21, .{
669 .xor_output = 0x000000,777 .xor_output = 0x000000,
670});778});
671779
672pub const Crc24Ble = Crc(u24, .{780pub const Crc24Ble = Generic(u24, .{
673 .polynomial = 0x00065b,781 .polynomial = 0x00065b,
674 .initial = 0x555555,782 .initial = 0x555555,
675 .reflect_input = true,783 .reflect_input = true,
...@@ -677,7 +785,7 @@ pub const Crc24Ble = Crc(u24, .{...@@ -677,7 +785,7 @@ pub const Crc24Ble = Crc(u24, .{
677 .xor_output = 0x000000,785 .xor_output = 0x000000,
678});786});
679787
680pub const Crc24FlexrayA = Crc(u24, .{788pub const Crc24FlexrayA = Generic(u24, .{
681 .polynomial = 0x5d6dcb,789 .polynomial = 0x5d6dcb,
682 .initial = 0xfedcba,790 .initial = 0xfedcba,
683 .reflect_input = false,791 .reflect_input = false,
...@@ -685,7 +793,7 @@ pub const Crc24FlexrayA = Crc(u24, .{...@@ -685,7 +793,7 @@ pub const Crc24FlexrayA = Crc(u24, .{
685 .xor_output = 0x000000,793 .xor_output = 0x000000,
686});794});
687795
688pub const Crc24FlexrayB = Crc(u24, .{796pub const Crc24FlexrayB = Generic(u24, .{
689 .polynomial = 0x5d6dcb,797 .polynomial = 0x5d6dcb,
690 .initial = 0xabcdef,798 .initial = 0xabcdef,
691 .reflect_input = false,799 .reflect_input = false,
...@@ -693,7 +801,7 @@ pub const Crc24FlexrayB = Crc(u24, .{...@@ -693,7 +801,7 @@ pub const Crc24FlexrayB = Crc(u24, .{
693 .xor_output = 0x000000,801 .xor_output = 0x000000,
694});802});
695803
696pub const Crc24Interlaken = Crc(u24, .{804pub const Crc24Interlaken = Generic(u24, .{
697 .polynomial = 0x328b63,805 .polynomial = 0x328b63,
698 .initial = 0xffffff,806 .initial = 0xffffff,
699 .reflect_input = false,807 .reflect_input = false,
...@@ -701,7 +809,7 @@ pub const Crc24Interlaken = Crc(u24, .{...@@ -701,7 +809,7 @@ pub const Crc24Interlaken = Crc(u24, .{
701 .xor_output = 0xffffff,809 .xor_output = 0xffffff,
702});810});
703811
704pub const Crc24LteA = Crc(u24, .{812pub const Crc24LteA = Generic(u24, .{
705 .polynomial = 0x864cfb,813 .polynomial = 0x864cfb,
706 .initial = 0x000000,814 .initial = 0x000000,
707 .reflect_input = false,815 .reflect_input = false,
...@@ -709,7 +817,7 @@ pub const Crc24LteA = Crc(u24, .{...@@ -709,7 +817,7 @@ pub const Crc24LteA = Crc(u24, .{
709 .xor_output = 0x000000,817 .xor_output = 0x000000,
710});818});
711819
712pub const Crc24LteB = Crc(u24, .{820pub const Crc24LteB = Generic(u24, .{
713 .polynomial = 0x800063,821 .polynomial = 0x800063,
714 .initial = 0x000000,822 .initial = 0x000000,
715 .reflect_input = false,823 .reflect_input = false,
...@@ -717,7 +825,7 @@ pub const Crc24LteB = Crc(u24, .{...@@ -717,7 +825,7 @@ pub const Crc24LteB = Crc(u24, .{
717 .xor_output = 0x000000,825 .xor_output = 0x000000,
718});826});
719827
720pub const Crc24Openpgp = Crc(u24, .{828pub const Crc24Openpgp = Generic(u24, .{
721 .polynomial = 0x864cfb,829 .polynomial = 0x864cfb,
722 .initial = 0xb704ce,830 .initial = 0xb704ce,
723 .reflect_input = false,831 .reflect_input = false,
...@@ -725,7 +833,7 @@ pub const Crc24Openpgp = Crc(u24, .{...@@ -725,7 +833,7 @@ pub const Crc24Openpgp = Crc(u24, .{
725 .xor_output = 0x000000,833 .xor_output = 0x000000,
726});834});
727835
728pub const Crc24Os9 = Crc(u24, .{836pub const Crc24Os9 = Generic(u24, .{
729 .polynomial = 0x800063,837 .polynomial = 0x800063,
730 .initial = 0xffffff,838 .initial = 0xffffff,
731 .reflect_input = false,839 .reflect_input = false,
...@@ -733,7 +841,7 @@ pub const Crc24Os9 = Crc(u24, .{...@@ -733,7 +841,7 @@ pub const Crc24Os9 = Crc(u24, .{
733 .xor_output = 0xffffff,841 .xor_output = 0xffffff,
734});842});
735843
736pub const Crc30Cdma = Crc(u30, .{844pub const Crc30Cdma = Generic(u30, .{
737 .polynomial = 0x2030b9c7,845 .polynomial = 0x2030b9c7,
738 .initial = 0x3fffffff,846 .initial = 0x3fffffff,
739 .reflect_input = false,847 .reflect_input = false,
...@@ -741,7 +849,7 @@ pub const Crc30Cdma = Crc(u30, .{...@@ -741,7 +849,7 @@ pub const Crc30Cdma = Crc(u30, .{
741 .xor_output = 0x3fffffff,849 .xor_output = 0x3fffffff,
742});850});
743851
744pub const Crc31Philips = Crc(u31, .{852pub const Crc31Philips = Generic(u31, .{
745 .polynomial = 0x04c11db7,853 .polynomial = 0x04c11db7,
746 .initial = 0x7fffffff,854 .initial = 0x7fffffff,
747 .reflect_input = false,855 .reflect_input = false,
...@@ -749,7 +857,7 @@ pub const Crc31Philips = Crc(u31, .{...@@ -749,7 +857,7 @@ pub const Crc31Philips = Crc(u31, .{
749 .xor_output = 0x7fffffff,857 .xor_output = 0x7fffffff,
750});858});
751859
752pub const Crc32Aixm = Crc(u32, .{860pub const Crc32Aixm = Generic(u32, .{
753 .polynomial = 0x814141ab,861 .polynomial = 0x814141ab,
754 .initial = 0x00000000,862 .initial = 0x00000000,
755 .reflect_input = false,863 .reflect_input = false,
...@@ -757,7 +865,7 @@ pub const Crc32Aixm = Crc(u32, .{...@@ -757,7 +865,7 @@ pub const Crc32Aixm = Crc(u32, .{
757 .xor_output = 0x00000000,865 .xor_output = 0x00000000,
758});866});
759867
760pub const Crc32Autosar = Crc(u32, .{868pub const Crc32Autosar = Generic(u32, .{
761 .polynomial = 0xf4acfb13,869 .polynomial = 0xf4acfb13,
762 .initial = 0xffffffff,870 .initial = 0xffffffff,
763 .reflect_input = true,871 .reflect_input = true,
...@@ -765,7 +873,7 @@ pub const Crc32Autosar = Crc(u32, .{...@@ -765,7 +873,7 @@ pub const Crc32Autosar = Crc(u32, .{
765 .xor_output = 0xffffffff,873 .xor_output = 0xffffffff,
766});874});
767875
768pub const Crc32Base91D = Crc(u32, .{876pub const Crc32Base91D = Generic(u32, .{
769 .polynomial = 0xa833982b,877 .polynomial = 0xa833982b,
770 .initial = 0xffffffff,878 .initial = 0xffffffff,
771 .reflect_input = true,879 .reflect_input = true,
...@@ -773,7 +881,7 @@ pub const Crc32Base91D = Crc(u32, .{...@@ -773,7 +881,7 @@ pub const Crc32Base91D = Crc(u32, .{
773 .xor_output = 0xffffffff,881 .xor_output = 0xffffffff,
774});882});
775883
776pub const Crc32Bzip2 = Crc(u32, .{884pub const Crc32Bzip2 = Generic(u32, .{
777 .polynomial = 0x04c11db7,885 .polynomial = 0x04c11db7,
778 .initial = 0xffffffff,886 .initial = 0xffffffff,
779 .reflect_input = false,887 .reflect_input = false,
...@@ -781,7 +889,7 @@ pub const Crc32Bzip2 = Crc(u32, .{...@@ -781,7 +889,7 @@ pub const Crc32Bzip2 = Crc(u32, .{
781 .xor_output = 0xffffffff,889 .xor_output = 0xffffffff,
782});890});
783891
784pub const Crc32CdRomEdc = Crc(u32, .{892pub const Crc32CdRomEdc = Generic(u32, .{
785 .polynomial = 0x8001801b,893 .polynomial = 0x8001801b,
786 .initial = 0x00000000,894 .initial = 0x00000000,
787 .reflect_input = true,895 .reflect_input = true,
...@@ -789,7 +897,7 @@ pub const Crc32CdRomEdc = Crc(u32, .{...@@ -789,7 +897,7 @@ pub const Crc32CdRomEdc = Crc(u32, .{
789 .xor_output = 0x00000000,897 .xor_output = 0x00000000,
790});898});
791899
792pub const Crc32Cksum = Crc(u32, .{900pub const Crc32Cksum = Generic(u32, .{
793 .polynomial = 0x04c11db7,901 .polynomial = 0x04c11db7,
794 .initial = 0x00000000,902 .initial = 0x00000000,
795 .reflect_input = false,903 .reflect_input = false,
...@@ -797,7 +905,7 @@ pub const Crc32Cksum = Crc(u32, .{...@@ -797,7 +905,7 @@ pub const Crc32Cksum = Crc(u32, .{
797 .xor_output = 0xffffffff,905 .xor_output = 0xffffffff,
798});906});
799907
800pub const Crc32Iscsi = Crc(u32, .{908pub const Crc32Iscsi = Generic(u32, .{
801 .polynomial = 0x1edc6f41,909 .polynomial = 0x1edc6f41,
802 .initial = 0xffffffff,910 .initial = 0xffffffff,
803 .reflect_input = true,911 .reflect_input = true,
...@@ -805,7 +913,7 @@ pub const Crc32Iscsi = Crc(u32, .{...@@ -805,7 +913,7 @@ pub const Crc32Iscsi = Crc(u32, .{
805 .xor_output = 0xffffffff,913 .xor_output = 0xffffffff,
806});914});
807915
808pub const Crc32IsoHdlc = Crc(u32, .{916pub const Crc32IsoHdlc = Generic(u32, .{
809 .polynomial = 0x04c11db7,917 .polynomial = 0x04c11db7,
810 .initial = 0xffffffff,918 .initial = 0xffffffff,
811 .reflect_input = true,919 .reflect_input = true,
...@@ -813,7 +921,7 @@ pub const Crc32IsoHdlc = Crc(u32, .{...@@ -813,7 +921,7 @@ pub const Crc32IsoHdlc = Crc(u32, .{
813 .xor_output = 0xffffffff,921 .xor_output = 0xffffffff,
814});922});
815923
816pub const Crc32Jamcrc = Crc(u32, .{924pub const Crc32Jamcrc = Generic(u32, .{
817 .polynomial = 0x04c11db7,925 .polynomial = 0x04c11db7,
818 .initial = 0xffffffff,926 .initial = 0xffffffff,
819 .reflect_input = true,927 .reflect_input = true,
...@@ -821,7 +929,7 @@ pub const Crc32Jamcrc = Crc(u32, .{...@@ -821,7 +929,7 @@ pub const Crc32Jamcrc = Crc(u32, .{
821 .xor_output = 0x00000000,929 .xor_output = 0x00000000,
822});930});
823931
824pub const Crc32Koopman = Crc(u32, .{932pub const Crc32Koopman = Generic(u32, .{
825 .polynomial = 0x741b8cd7,933 .polynomial = 0x741b8cd7,
826 .initial = 0xffffffff,934 .initial = 0xffffffff,
827 .reflect_input = true,935 .reflect_input = true,
...@@ -829,7 +937,7 @@ pub const Crc32Koopman = Crc(u32, .{...@@ -829,7 +937,7 @@ pub const Crc32Koopman = Crc(u32, .{
829 .xor_output = 0xffffffff,937 .xor_output = 0xffffffff,
830});938});
831939
832pub const Crc32Mef = Crc(u32, .{940pub const Crc32Mef = Generic(u32, .{
833 .polynomial = 0x741b8cd7,941 .polynomial = 0x741b8cd7,
834 .initial = 0xffffffff,942 .initial = 0xffffffff,
835 .reflect_input = true,943 .reflect_input = true,
...@@ -837,7 +945,7 @@ pub const Crc32Mef = Crc(u32, .{...@@ -837,7 +945,7 @@ pub const Crc32Mef = Crc(u32, .{
837 .xor_output = 0x00000000,945 .xor_output = 0x00000000,
838});946});
839947
840pub const Crc32Mpeg2 = Crc(u32, .{948pub const Crc32Mpeg2 = Generic(u32, .{
841 .polynomial = 0x04c11db7,949 .polynomial = 0x04c11db7,
842 .initial = 0xffffffff,950 .initial = 0xffffffff,
843 .reflect_input = false,951 .reflect_input = false,
...@@ -845,7 +953,7 @@ pub const Crc32Mpeg2 = Crc(u32, .{...@@ -845,7 +953,7 @@ pub const Crc32Mpeg2 = Crc(u32, .{
845 .xor_output = 0x00000000,953 .xor_output = 0x00000000,
846});954});
847955
848pub const Crc32Xfer = Crc(u32, .{956pub const Crc32Xfer = Generic(u32, .{
849 .polynomial = 0x000000af,957 .polynomial = 0x000000af,
850 .initial = 0x00000000,958 .initial = 0x00000000,
851 .reflect_input = false,959 .reflect_input = false,
...@@ -853,7 +961,7 @@ pub const Crc32Xfer = Crc(u32, .{...@@ -853,7 +961,7 @@ pub const Crc32Xfer = Crc(u32, .{
853 .xor_output = 0x00000000,961 .xor_output = 0x00000000,
854});962});
855963
856pub const Crc40Gsm = Crc(u40, .{964pub const Crc40Gsm = Generic(u40, .{
857 .polynomial = 0x0004820009,965 .polynomial = 0x0004820009,
858 .initial = 0x0000000000,966 .initial = 0x0000000000,
859 .reflect_input = false,967 .reflect_input = false,
...@@ -861,7 +969,7 @@ pub const Crc40Gsm = Crc(u40, .{...@@ -861,7 +969,7 @@ pub const Crc40Gsm = Crc(u40, .{
861 .xor_output = 0xffffffffff,969 .xor_output = 0xffffffffff,
862});970});
863971
864pub const Crc64Ecma182 = Crc(u64, .{972pub const Crc64Ecma182 = Generic(u64, .{
865 .polynomial = 0x42f0e1eba9ea3693,973 .polynomial = 0x42f0e1eba9ea3693,
866 .initial = 0x0000000000000000,974 .initial = 0x0000000000000000,
867 .reflect_input = false,975 .reflect_input = false,
...@@ -869,7 +977,7 @@ pub const Crc64Ecma182 = Crc(u64, .{...@@ -869,7 +977,7 @@ pub const Crc64Ecma182 = Crc(u64, .{
869 .xor_output = 0x0000000000000000,977 .xor_output = 0x0000000000000000,
870});978});
871979
872pub const Crc64GoIso = Crc(u64, .{980pub const Crc64GoIso = Generic(u64, .{
873 .polynomial = 0x000000000000001b,981 .polynomial = 0x000000000000001b,
874 .initial = 0xffffffffffffffff,982 .initial = 0xffffffffffffffff,
875 .reflect_input = true,983 .reflect_input = true,
...@@ -877,7 +985,7 @@ pub const Crc64GoIso = Crc(u64, .{...@@ -877,7 +985,7 @@ pub const Crc64GoIso = Crc(u64, .{
877 .xor_output = 0xffffffffffffffff,985 .xor_output = 0xffffffffffffffff,
878});986});
879987
880pub const Crc64Ms = Crc(u64, .{988pub const Crc64Ms = Generic(u64, .{
881 .polynomial = 0x259c84cba6426349,989 .polynomial = 0x259c84cba6426349,
882 .initial = 0xffffffffffffffff,990 .initial = 0xffffffffffffffff,
883 .reflect_input = true,991 .reflect_input = true,
...@@ -885,7 +993,7 @@ pub const Crc64Ms = Crc(u64, .{...@@ -885,7 +993,7 @@ pub const Crc64Ms = Crc(u64, .{
885 .xor_output = 0x0000000000000000,993 .xor_output = 0x0000000000000000,
886});994});
887995
888pub const Crc64Redis = Crc(u64, .{996pub const Crc64Redis = Generic(u64, .{
889 .polynomial = 0xad93d23594c935a9,997 .polynomial = 0xad93d23594c935a9,
890 .initial = 0x0000000000000000,998 .initial = 0x0000000000000000,
891 .reflect_input = true,999 .reflect_input = true,
...@@ -893,7 +1001,7 @@ pub const Crc64Redis = Crc(u64, .{...@@ -893,7 +1001,7 @@ pub const Crc64Redis = Crc(u64, .{
893 .xor_output = 0x0000000000000000,1001 .xor_output = 0x0000000000000000,
894});1002});
8951003
896pub const Crc64We = Crc(u64, .{1004pub const Crc64We = Generic(u64, .{
897 .polynomial = 0x42f0e1eba9ea3693,1005 .polynomial = 0x42f0e1eba9ea3693,
898 .initial = 0xffffffffffffffff,1006 .initial = 0xffffffffffffffff,
899 .reflect_input = false,1007 .reflect_input = false,
...@@ -901,7 +1009,7 @@ pub const Crc64We = Crc(u64, .{...@@ -901,7 +1009,7 @@ pub const Crc64We = Crc(u64, .{
901 .xor_output = 0xffffffffffffffff,1009 .xor_output = 0xffffffffffffffff,
902});1010});
9031011
904pub const Crc64Xz = Crc(u64, .{1012pub const Crc64Xz = Generic(u64, .{
905 .polynomial = 0x42f0e1eba9ea3693,1013 .polynomial = 0x42f0e1eba9ea3693,
906 .initial = 0xffffffffffffffff,1014 .initial = 0xffffffffffffffff,
907 .reflect_input = true,1015 .reflect_input = true,
...@@ -909,10 +1017,14 @@ pub const Crc64Xz = Crc(u64, .{...@@ -909,10 +1017,14 @@ pub const Crc64Xz = Crc(u64, .{
909 .xor_output = 0xffffffffffffffff,1017 .xor_output = 0xffffffffffffffff,
910});1018});
9111019
912pub const Crc82Darc = Crc(u82, .{1020pub const Crc82Darc = Generic(u82, .{
913 .polynomial = 0x0308c0111011401440411,1021 .polynomial = 0x0308c0111011401440411,
914 .initial = 0x000000000000000000000,1022 .initial = 0x000000000000000000000,
915 .reflect_input = true,1023 .reflect_input = true,
916 .reflect_output = true,1024 .reflect_output = true,
917 .xor_output = 0x000000000000000000000,1025 .xor_output = 0x000000000000000000000,
918});1026});
1027
1028test {
1029 _ = @import("crc/test.zig");
1030}
lib/std/hash/crc/impl.zig deleted-112
...@@ -1,112 +0,0 @@
1// There is a generic CRC implementation "Crc()" which can be parameterized via
2// the Algorithm struct for a plethora of uses.
3//
4// The primary interface for all of the standard CRC algorithms is the
5// generated file "crc.zig", which uses the implementation code here to define
6// many standard CRCs.
7
8const std = @import("std");
9
10pub fn Algorithm(comptime W: type) type {
11 return struct {
12 polynomial: W,
13 initial: W,
14 reflect_input: bool,
15 reflect_output: bool,
16 xor_output: W,
17 };
18}
19
20pub fn Crc(comptime W: type, comptime algorithm: Algorithm(W)) type {
21 return struct {
22 const Self = @This();
23 const I = if (@bitSizeOf(W) < 8) u8 else W;
24 const lookup_table = blk: {
25 @setEvalBranchQuota(2500);
26
27 const poly = if (algorithm.reflect_input)
28 @bitReverse(@as(I, algorithm.polynomial)) >> (@bitSizeOf(I) - @bitSizeOf(W))
29 else
30 @as(I, algorithm.polynomial) << (@bitSizeOf(I) - @bitSizeOf(W));
31
32 var table: [256]I = undefined;
33 for (&table, 0..) |*e, i| {
34 var crc: I = i;
35 if (algorithm.reflect_input) {
36 var j: usize = 0;
37 while (j < 8) : (j += 1) {
38 crc = (crc >> 1) ^ ((crc & 1) * poly);
39 }
40 } else {
41 crc <<= @bitSizeOf(I) - 8;
42 var j: usize = 0;
43 while (j < 8) : (j += 1) {
44 crc = (crc << 1) ^ (((crc >> (@bitSizeOf(I) - 1)) & 1) * poly);
45 }
46 }
47 e.* = crc;
48 }
49 break :blk table;
50 };
51
52 crc: I,
53
54 pub fn init() Self {
55 const initial = if (algorithm.reflect_input)
56 @bitReverse(@as(I, algorithm.initial)) >> (@bitSizeOf(I) - @bitSizeOf(W))
57 else
58 @as(I, algorithm.initial) << (@bitSizeOf(I) - @bitSizeOf(W));
59 return Self{ .crc = initial };
60 }
61
62 inline fn tableEntry(index: I) I {
63 return lookup_table[@as(u8, @intCast(index & 0xFF))];
64 }
65
66 pub fn update(self: *Self, bytes: []const u8) void {
67 var i: usize = 0;
68 if (@bitSizeOf(I) <= 8) {
69 while (i < bytes.len) : (i += 1) {
70 self.crc = tableEntry(self.crc ^ bytes[i]);
71 }
72 } else if (algorithm.reflect_input) {
73 while (i < bytes.len) : (i += 1) {
74 const table_index = self.crc ^ bytes[i];
75 self.crc = tableEntry(table_index) ^ (self.crc >> 8);
76 }
77 } else {
78 while (i < bytes.len) : (i += 1) {
79 const table_index = (self.crc >> (@bitSizeOf(I) - 8)) ^ bytes[i];
80 self.crc = tableEntry(table_index) ^ (self.crc << 8);
81 }
82 }
83 }
84
85 pub fn final(self: Self) W {
86 var c = self.crc;
87 if (algorithm.reflect_input != algorithm.reflect_output) {
88 c = @bitReverse(c);
89 }
90 if (!algorithm.reflect_output) {
91 c >>= @bitSizeOf(I) - @bitSizeOf(W);
92 }
93 return @as(W, @intCast(c ^ algorithm.xor_output));
94 }
95
96 pub fn hash(bytes: []const u8) W {
97 var c = Self.init();
98 c.update(bytes);
99 return c.final();
100 }
101 };
102}
103
104pub const Polynomial = enum(u32) {
105 IEEE = @compileError("use Crc with algorithm .Crc32IsoHdlc"),
106 Castagnoli = @compileError("use Crc with algorithm .Crc32Iscsi"),
107 Koopman = @compileError("use Crc with algorithm .Crc32Koopman"),
108 _,
109};
110
111pub const Crc32WithPoly = @compileError("use Crc instead");
112pub const Crc32SmallWithPoly = @compileError("use Crc instead");
lib/std/io/BufferedReader.zig+34-2
...@@ -35,6 +35,10 @@ pub fn bufferContents(br: *BufferedReader) []u8 {...@@ -35,6 +35,10 @@ pub fn bufferContents(br: *BufferedReader) []u8 {
35 return br.buffer[br.seek..br.end];35 return br.buffer[br.seek..br.end];
36}36}
3737
38pub fn bufferedLen(br: *const BufferedReader) usize {
39 return br.end - br.seek;
40}
41
38/// Although `BufferedReader` can easily satisfy the `Reader` interface, it's42/// Although `BufferedReader` can easily satisfy the `Reader` interface, it's
39/// generally more practical to pass a `BufferedReader` instance itself around,43/// generally more practical to pass a `BufferedReader` instance itself around,
40/// since it will result in fewer calls across vtable boundaries.44/// since it will result in fewer calls across vtable boundaries.
...@@ -49,6 +53,10 @@ pub fn reader(br: *BufferedReader) Reader {...@@ -49,6 +53,10 @@ pub fn reader(br: *BufferedReader) Reader {
49 };53 };
50}54}
5155
56pub fn hashed(br: *BufferedReader, hasher: anytype) Reader.Hashed(@TypeOf(hasher)) {
57 return .{ .in = br, .hasher = hasher };
58}
59
52/// Equivalent semantics to `std.io.Reader.VTable.readVec`.60/// Equivalent semantics to `std.io.Reader.VTable.readVec`.
53pub fn readVec(br: *BufferedReader, data: []const []u8) Reader.Error!usize {61pub fn readVec(br: *BufferedReader, data: []const []u8) Reader.Error!usize {
54 return readVecLimit(br, data, .unlimited);62 return readVecLimit(br, data, .unlimited);
...@@ -401,6 +409,30 @@ pub fn readSliceShort(br: *BufferedReader, buffer: []u8) Reader.ShortError!usize...@@ -401,6 +409,30 @@ pub fn readSliceShort(br: *BufferedReader, buffer: []u8) Reader.ShortError!usize
401 }409 }
402}410}
403411
412/// Fill `buffer` with the next `buffer.len` bytes from the stream, advancing
413/// the seek position.
414///
415/// Invalidates previously returned values from `peek`.
416///
417/// If the provided buffer cannot be filled completely, `error.EndOfStream` is
418/// returned instead.
419///
420/// The function is inline to avoid the dead code in case `endian` is
421/// comptime-known and matches host endianness.
422///
423/// See also:
424/// * `readSlice`
425/// * `readSliceEndianAlloc`
426pub inline fn readSliceEndian(
427 br: *BufferedReader,
428 comptime Elem: type,
429 buffer: []Elem,
430 endian: std.builtin.Endian,
431) Reader.Error!void {
432 try readSlice(br, @ptrCast(buffer));
433 if (native_endian != endian) for (buffer) |*elem| std.mem.byteSwapAllFields(Elem, elem);
434}
435
404pub const ReadAllocError = Reader.Error || Allocator.Error;436pub const ReadAllocError = Reader.Error || Allocator.Error;
405437
406/// The function is inline to avoid the dead code in case `endian` is438/// The function is inline to avoid the dead code in case `endian` is
...@@ -408,14 +440,14 @@ pub const ReadAllocError = Reader.Error || Allocator.Error;...@@ -408,14 +440,14 @@ pub const ReadAllocError = Reader.Error || Allocator.Error;
408pub inline fn readSliceEndianAlloc(440pub inline fn readSliceEndianAlloc(
409 br: *BufferedReader,441 br: *BufferedReader,
410 allocator: Allocator,442 allocator: Allocator,
411 Elem: type,443 comptime Elem: type,
412 len: usize,444 len: usize,
413 endian: std.builtin.Endian,445 endian: std.builtin.Endian,
414) ReadAllocError![]Elem {446) ReadAllocError![]Elem {
415 const dest = try allocator.alloc(Elem, len);447 const dest = try allocator.alloc(Elem, len);
416 errdefer allocator.free(dest);448 errdefer allocator.free(dest);
417 try readSlice(br, @ptrCast(dest));449 try readSlice(br, @ptrCast(dest));
418 if (native_endian != endian) std.mem.byteSwapAllFields(Elem, dest);450 if (native_endian != endian) for (dest) |*elem| std.mem.byteSwapAllFields(Elem, elem);
419 return dest;451 return dest;
420}452}
421453
lib/std/io/BufferedWriter.zig+37-3
...@@ -58,6 +58,10 @@ pub fn initFixed(bw: *BufferedWriter, buffer: []u8) void {...@@ -58,6 +58,10 @@ pub fn initFixed(bw: *BufferedWriter, buffer: []u8) void {
58 };58 };
59}59}
6060
61pub fn hashed(bw: *BufferedWriter, hasher: anytype) Writer.Hashed(@TypeOf(hasher)) {
62 return .{ .out = bw, .hasher = hasher };
63}
64
61/// This function is available when using `initFixed`.65/// This function is available when using `initFixed`.
62pub fn getWritten(bw: *const BufferedWriter) []u8 {66pub fn getWritten(bw: *const BufferedWriter) []u8 {
63 assert(bw.unbuffered_writer.vtable == &fixed_vtable);67 assert(bw.unbuffered_writer.vtable == &fixed_vtable);
...@@ -157,7 +161,7 @@ pub fn advance(bw: *BufferedWriter, n: usize) void {...@@ -157,7 +161,7 @@ pub fn advance(bw: *BufferedWriter, n: usize) void {
157}161}
158162
159/// The `data` parameter is mutable because this function needs to mutate the163/// The `data` parameter is mutable because this function needs to mutate the
160/// fields in order to handle partial writes from `Writer.VTable.writeVec`.164/// fields in order to handle partial writes from `Writer.VTable.writeSplat`.
161pub fn writeVecAll(bw: *BufferedWriter, data: [][]const u8) Writer.Error!void {165pub fn writeVecAll(bw: *BufferedWriter, data: [][]const u8) Writer.Error!void {
162 var index: usize = 0;166 var index: usize = 0;
163 var truncate: usize = 0;167 var truncate: usize = 0;
...@@ -175,6 +179,36 @@ pub fn writeVecAll(bw: *BufferedWriter, data: [][]const u8) Writer.Error!void {...@@ -175,6 +179,36 @@ pub fn writeVecAll(bw: *BufferedWriter, data: [][]const u8) Writer.Error!void {
175 }179 }
176}180}
177181
182/// The `data` parameter is mutable because this function needs to mutate the
183/// fields in order to handle partial writes from `Writer.VTable.writeSplat`.
184pub fn writeSplatAll(bw: *BufferedWriter, data: [][]const u8, splat: usize) Writer.Error!void {
185 var index: usize = 0;
186 var truncate: usize = 0;
187 var remaining_splat = splat;
188 while (index + 1 < data.len) {
189 {
190 const untruncated = data[index];
191 data[index] = untruncated[truncate..];
192 defer data[index] = untruncated;
193 truncate += try bw.writeSplat(data[index..], remaining_splat);
194 }
195 while (truncate >= data[index].len) {
196 if (index + 1 < data.len) {
197 truncate -= data[index].len;
198 index += 1;
199 } else {
200 const last = data[data.len - 1];
201 remaining_splat -= @divExact(truncate, last.len);
202 while (remaining_splat > 0) {
203 const n = try bw.writeSplat(data[data.len - 1 ..][0..1], remaining_splat);
204 remaining_splat -= @divExact(n, last.len);
205 }
206 return;
207 }
208 }
209 }
210}
211
178/// If the number of bytes to write based on `data` and `splat` fits inside212/// If the number of bytes to write based on `data` and `splat` fits inside
179/// `unusedCapacitySlice`, this function is guaranteed to not fail, not call213/// `unusedCapacitySlice`, this function is guaranteed to not fail, not call
180/// into the underlying writer, and return the full number of bytes.214/// into the underlying writer, and return the full number of bytes.
...@@ -443,7 +477,7 @@ pub fn splatBytesAll(bw: *BufferedWriter, bytes: []const u8, splat: usize) Write...@@ -443,7 +477,7 @@ pub fn splatBytesAll(bw: *BufferedWriter, bytes: []const u8, splat: usize) Write
443477
444/// Writes the same slice many times, allowing short writes.478/// Writes the same slice many times, allowing short writes.
445///479///
446/// Does maximum of one underlying `Writer.VTable.writeVec`.480/// Does maximum of one underlying `Writer.VTable.writeSplat`.
447pub fn splatBytes(bw: *BufferedWriter, bytes: []const u8, n: usize) Writer.Error!usize {481pub fn splatBytes(bw: *BufferedWriter, bytes: []const u8, n: usize) Writer.Error!usize {
448 return passthruWriteSplat(bw, &.{bytes}, n);482 return passthruWriteSplat(bw, &.{bytes}, n);
449}483}
...@@ -621,7 +655,7 @@ pub const WriteFileOptions = struct {...@@ -621,7 +655,7 @@ pub const WriteFileOptions = struct {
621 /// size here will save one syscall.655 /// size here will save one syscall.
622 limit: Writer.Limit = .unlimited,656 limit: Writer.Limit = .unlimited,
623 /// Headers and trailers must be passed together so that in case `len` is657 /// Headers and trailers must be passed together so that in case `len` is
624 /// zero, they can be forwarded directly to `Writer.VTable.writeVec`.658 /// zero, they can be forwarded directly to `Writer.VTable.writeSplat`.
625 ///659 ///
626 /// The parameter is mutable because this function needs to mutate the660 /// The parameter is mutable because this function needs to mutate the
627 /// fields in order to handle partial writes from `Writer.VTable.writeFile`.661 /// fields in order to handle partial writes from `Writer.VTable.writeFile`.
lib/std/io/Reader.zig+68
...@@ -331,3 +331,71 @@ test "readAlloc when the backing reader provides one byte at a time" {...@@ -331,3 +331,71 @@ test "readAlloc when the backing reader provides one byte at a time" {
331 defer std.testing.allocator.free(res);331 defer std.testing.allocator.free(res);
332 try std.testing.expectEqualStrings(str, res);332 try std.testing.expectEqualStrings(str, res);
333}333}
334
335/// Provides a `Reader` implementation by passing data from an underlying
336/// reader through `Hasher.update`.
337///
338/// The underlying reader is best unbuffered.
339///
340/// This implementation makes suboptimal buffering decisions due to being
341/// generic. A better solution will involve creating a reader for each hash
342/// function, where the discard buffer can be tailored to the hash
343/// implementation details.
344pub fn Hashed(comptime Hasher: type) type {
345 return struct {
346 in: *BufferedReader,
347 hasher: Hasher,
348
349 pub fn readable(this: *@This(), buffer: []u8) BufferedReader {
350 return .{
351 .unbuffered_reader = .{
352 .context = this,
353 .vtable = &.{
354 .read = @This().read,
355 .readVec = @This().readVec,
356 .discard = @This().discard,
357 },
358 },
359 .buffer = buffer,
360 .end = 0,
361 .seek = 0,
362 };
363 }
364
365 fn read(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) RwError!usize {
366 const this: *@This() = @alignCast(@ptrCast(context));
367 const slice = limit.slice(try bw.writableSliceGreedy(1));
368 const n = try this.in.readVec(&.{slice});
369 this.hasher.update(slice[0..n]);
370 bw.advance(n);
371 return n;
372 }
373
374 fn discard(context: ?*anyopaque, limit: Limit) Error!usize {
375 const this: *@This() = @alignCast(@ptrCast(context));
376 var bw = this.hasher.writable(&.{});
377 const n = this.in.read(&bw, limit) catch |err| switch (err) {
378 error.WriteFailed => unreachable,
379 else => |e| return e,
380 };
381 return n;
382 }
383
384 fn readVec(context: ?*anyopaque, data: []const []u8) Error!usize {
385 const this: *@This() = @alignCast(@ptrCast(context));
386 const n = try this.in.readVec(data);
387 var remaining: usize = n;
388 for (data) |slice| {
389 if (remaining < slice.len) {
390 this.hasher.update(slice[0..remaining]);
391 return n;
392 } else {
393 remaining -= slice.len;
394 this.hasher.update(slice);
395 }
396 }
397 assert(remaining == 0);
398 return n;
399 }
400 };
401}
lib/std/io/Writer.zig+84-4
...@@ -136,8 +136,8 @@ pub fn failingWriteSplat(context: ?*anyopaque, data: []const []const u8, splat:...@@ -136,8 +136,8 @@ pub fn failingWriteSplat(context: ?*anyopaque, data: []const []const u8, splat:
136pub fn failingWriteFile(136pub fn failingWriteFile(
137 context: ?*anyopaque,137 context: ?*anyopaque,
138 file: std.fs.File,138 file: std.fs.File,
139 offset: std.io.Writer.Offset,139 offset: Offset,
140 limit: std.io.Writer.Limit,140 limit: Limit,
141 headers_and_trailers: []const []const u8,141 headers_and_trailers: []const []const u8,
142 headers_len: usize,142 headers_len: usize,
143) FileError!usize {143) FileError!usize {
...@@ -158,11 +158,13 @@ pub const failing: Writer = .{...@@ -158,11 +158,13 @@ pub const failing: Writer = .{
158 },158 },
159};159};
160160
161/// For use when the `Writer` implementation can cannot offer a more efficient
162/// implementation than a basic read/write loop on the file.
161pub fn unimplementedWriteFile(163pub fn unimplementedWriteFile(
162 context: ?*anyopaque,164 context: ?*anyopaque,
163 file: std.fs.File,165 file: std.fs.File,
164 offset: std.io.Writer.Offset,166 offset: Offset,
165 limit: std.io.Writer.Limit,167 limit: Limit,
166 headers_and_trailers: []const []const u8,168 headers_and_trailers: []const []const u8,
167 headers_len: usize,169 headers_len: usize,
168) FileError!usize {170) FileError!usize {
...@@ -175,6 +177,84 @@ pub fn unimplementedWriteFile(...@@ -175,6 +177,84 @@ pub fn unimplementedWriteFile(
175 return error.Unimplemented;177 return error.Unimplemented;
176}178}
177179
180/// Provides a `Writer` implementation based on calling `Hasher.update`, sending
181/// all data also to an underlying `std.io.BufferedWriter`.
182///
183/// When using this, the underlying writer is best unbuffered because all
184/// writes are passed on directly to it.
185///
186/// This implementation makes suboptimal buffering decisions due to being
187/// generic. A better solution will involve creating a writer for each hash
188/// function, where the splat buffer can be tailored to the hash implementation
189/// details.
190pub fn Hashed(comptime Hasher: type) type {
191 return struct {
192 out: *std.io.BufferedWriter,
193 hasher: Hasher,
194
195 pub fn writable(this: *@This(), buffer: []u8) std.io.BufferedWriter {
196 return .{
197 .unbuffered_writer = .{
198 .context = this,
199 .vtable = &.{
200 .writeSplat = @This().writeSplat,
201 .writeFile = Writer.unimplementedWriteFile,
202 },
203 },
204 .buffer = buffer,
205 };
206 }
207
208 fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) Writer.Error!usize {
209 const this: *@This() = @alignCast(@ptrCast(context));
210 const n = try this.out.writeSplat(data, splat);
211 const short_data = data[0 .. data.len - @intFromBool(splat == 0)];
212 var remaining: usize = n;
213 for (short_data) |slice| {
214 if (remaining < slice.len) {
215 this.hasher.update(slice[0..remaining]);
216 return n;
217 } else {
218 remaining -= slice.len;
219 this.hasher.update(slice);
220 }
221 }
222 const remaining_splat = switch (splat) {
223 0, 1 => {
224 assert(remaining == 0);
225 return n;
226 },
227 else => splat - 1,
228 };
229 const last = data[data.len - 1];
230 assert(remaining == remaining_splat * last.len);
231 switch (last.len) {
232 0 => {
233 assert(remaining == 0);
234 return n;
235 },
236 1 => {
237 var buffer: [64]u8 = undefined;
238 @memset(&buffer, last[0]);
239 while (remaining > 0) {
240 const update_len = @min(remaining, buffer.len);
241 this.hasher.update(buffer[0..update_len]);
242 remaining -= update_len;
243 }
244 return n;
245 },
246 else => {},
247 }
248 while (remaining > 0) {
249 const update_len = @min(remaining, last.len);
250 this.hasher.update(last[0..update_len]);
251 remaining -= update_len;
252 }
253 return n;
254 }
255 };
256}
257
178test {258test {
179 _ = Null;259 _ = Null;
180}260}
lib/std/io/Writer/Null.zig+4
...@@ -19,6 +19,10 @@ pub fn writer(nw: *NullWriter) Writer {...@@ -19,6 +19,10 @@ pub fn writer(nw: *NullWriter) Writer {
19 };19 };
20}20}
2121
22pub fn writable(nw: *NullWriter, buffer: []u8) std.io.BufferedWriter {
23 return writer(nw).buffered(buffer);
24}
25
22fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) Writer.Error!usize {26fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) Writer.Error!usize {
23 _ = context;27 _ = context;
24 const headers = data[0 .. data.len - 1];28 const headers = data[0 .. data.len - 1];
lib/std/mem.zig+3-1
...@@ -2196,7 +2196,9 @@ pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {...@@ -2196,7 +2196,9 @@ pub fn byteSwapAllFields(comptime S: type, ptr: *S) void {
2196 }2196 }
2197 }2197 }
2198 },2198 },
2199 else => @compileError("byteSwapAllFields expects a struct or array as the first argument"),2199 else => {
2200 ptr.* = @byteSwap(ptr.*);
2201 },
2200 }2202 }
2201}2203}
22022204
src/Package/Fetch/git.zig+179-158
...@@ -11,6 +11,7 @@ const Allocator = mem.Allocator;...@@ -11,6 +11,7 @@ const Allocator = mem.Allocator;
11const Sha1 = std.crypto.hash.Sha1;11const Sha1 = std.crypto.hash.Sha1;
12const Sha256 = std.crypto.hash.sha2.Sha256;12const Sha256 = std.crypto.hash.sha2.Sha256;
13const assert = std.debug.assert;13const assert = std.debug.assert;
14const zlib = std.compress.zlib;
1415
15/// The ID of a Git object.16/// The ID of a Git object.
16pub const Oid = union(Format) {17pub const Oid = union(Format) {
...@@ -52,7 +53,6 @@ pub const Oid = union(Format) {...@@ -52,7 +53,6 @@ pub const Oid = union(Format) {
52 };53 };
53 }54 }
5455
55 // Must be public for use from HashedReader and HashedWriter.
56 pub fn update(hasher: *Hasher, b: []const u8) void {56 pub fn update(hasher: *Hasher, b: []const u8) void {
57 switch (hasher.*) {57 switch (hasher.*) {
58 inline else => |*inner| inner.update(b),58 inline else => |*inner| inner.update(b),
...@@ -64,6 +64,12 @@ pub const Oid = union(Format) {...@@ -64,6 +64,12 @@ pub const Oid = union(Format) {
64 inline else => |*inner, tag| @unionInit(Oid, @tagName(tag), inner.finalResult()),64 inline else => |*inner, tag| @unionInit(Oid, @tagName(tag), inner.finalResult()),
65 };65 };
66 }66 }
67
68 pub fn writable(hasher: *Hasher, buffer: []u8) std.io.BufferedWriter {
69 return switch (hasher.*) {
70 inline else => |*inner| inner.writable(buffer),
71 };
72 }
67 };73 };
6874
69 pub fn fromBytes(oid_format: Format, bytes: []const u8) Oid {75 pub fn fromBytes(oid_format: Format, bytes: []const u8) Oid {
...@@ -73,9 +79,18 @@ pub const Oid = union(Format) {...@@ -73,9 +79,18 @@ pub const Oid = union(Format) {
73 };79 };
74 }80 }
7581
76 pub fn readBytes(oid_format: Format, reader: anytype) @TypeOf(reader).NoEofError!Oid {82 pub fn readBytes(oid_format: Format, reader: *std.io.BufferedReader) std.io.Reader.Error!Oid {
77 return switch (oid_format) {83 return switch (oid_format) {
78 inline else => |tag| @unionInit(Oid, @tagName(tag), try reader.readBytesNoEof(tag.byteLength())),84 .sha1 => {
85 var result: Oid = .{ .sha1 = undefined };
86 try reader.readSlice(&result.sha1);
87 return result;
88 },
89 .sha256 => {
90 var result: Oid = .{ .sha256 = undefined };
91 try reader.readSlice(&result.sha256);
92 return result;
93 },
79 };94 };
80 }95 }
8196
...@@ -167,8 +182,15 @@ pub const Diagnostics = struct {...@@ -167,8 +182,15 @@ pub const Diagnostics = struct {
167pub const Repository = struct {182pub const Repository = struct {
168 odb: Odb,183 odb: Odb,
169184
170 pub fn init(allocator: Allocator, format: Oid.Format, pack_file: std.fs.File, index_file: std.fs.File) !Repository {185 pub fn init(
171 return .{ .odb = try Odb.init(allocator, format, pack_file, index_file) };186 repo: *Repository,
187 allocator: Allocator,
188 format: Oid.Format,
189 pack_file: *std.fs.File.Reader,
190 index_file: *std.fs.File.Reader,
191 ) !void {
192 repo.* = .{ .odb = undefined };
193 try repo.odb.init(allocator, format, pack_file, index_file);
172 }194 }
173195
174 pub fn deinit(repository: *Repository) void {196 pub fn deinit(repository: *Repository) void {
...@@ -337,24 +359,32 @@ pub const Repository = struct {...@@ -337,24 +359,32 @@ pub const Repository = struct {
337/// [pack-format](https://git-scm.com/docs/pack-format).359/// [pack-format](https://git-scm.com/docs/pack-format).
338const Odb = struct {360const Odb = struct {
339 format: Oid.Format,361 format: Oid.Format,
340 pack_file: std.fs.File,362 pack_file: *std.fs.File.Reader,
341 index_header: IndexHeader,363 index_header: IndexHeader,
342 index_file: std.fs.File,364 index_file: *std.fs.File.Reader,
343 cache: ObjectCache = .{},365 cache: ObjectCache = .{},
344 allocator: Allocator,366 allocator: Allocator,
345367
346 /// Initializes the database from open pack and index files.368 /// Initializes the database from open pack and index files.
347 fn init(allocator: Allocator, format: Oid.Format, pack_file: std.fs.File, index_file: std.fs.File) !Odb {369 fn init(
370 odb: *Odb,
371 allocator: Allocator,
372 format: Oid.Format,
373 pack_file: *std.fs.File.Reader,
374 index_file: *std.fs.File.Reader,
375 ) !void {
348 try pack_file.seekTo(0);376 try pack_file.seekTo(0);
349 try index_file.seekTo(0);377 try index_file.seekTo(0);
350 const index_header = try IndexHeader.read(index_file.reader());378 odb.* = .{
351 return .{
352 .format = format,379 .format = format,
353 .pack_file = pack_file,380 .pack_file = pack_file,
354 .index_header = index_header,381 .index_header = undefined,
355 .index_file = index_file,382 .index_file = index_file,
356 .allocator = allocator,383 .allocator = allocator,
357 };384 };
385 var buffer: [1032]u8 = undefined;
386 var index_file_br = index_file.readable(&buffer);
387 try odb.index_header.read(&index_file_br);
358 }388 }
359389
360 fn deinit(odb: *Odb) void {390 fn deinit(odb: *Odb) void {
...@@ -364,27 +394,30 @@ const Odb = struct {...@@ -364,27 +394,30 @@ const Odb = struct {
364394
365 /// Reads the object at the current position in the database.395 /// Reads the object at the current position in the database.
366 fn readObject(odb: *Odb) !Object {396 fn readObject(odb: *Odb) !Object {
367 var base_offset = try odb.pack_file.getPos();397 var pack_read_buffer: [64]u8 = undefined;
398 var base_offset = odb.pack_file.pos;
399 var pack_br = odb.pack_file.readable(&pack_read_buffer);
368 var base_header: EntryHeader = undefined;400 var base_header: EntryHeader = undefined;
369 var delta_offsets: std.ArrayListUnmanaged(u64) = .empty;401 var delta_offsets: std.ArrayListUnmanaged(u64) = .empty;
370 defer delta_offsets.deinit(odb.allocator);402 defer delta_offsets.deinit(odb.allocator);
371 const base_object = while (true) {403 const base_object = while (true) {
372 if (odb.cache.get(base_offset)) |base_object| break base_object;404 if (odb.cache.get(base_offset)) |base_object| break base_object;
373405
374 base_header = try EntryHeader.read(odb.format, odb.pack_file.reader());406 base_header = try EntryHeader.read(odb.format, &pack_br);
375 switch (base_header) {407 switch (base_header) {
376 .ofs_delta => |ofs_delta| {408 .ofs_delta => |ofs_delta| {
377 try delta_offsets.append(odb.allocator, base_offset);409 try delta_offsets.append(odb.allocator, base_offset);
378 base_offset = std.math.sub(u64, base_offset, ofs_delta.offset) catch return error.InvalidFormat;410 base_offset = std.math.sub(u64, base_offset, ofs_delta.offset) catch return error.InvalidFormat;
379 try odb.pack_file.seekTo(base_offset);411 try odb.pack_file.seekTo(base_offset);
412 pack_br = odb.pack_file.readable(&pack_read_buffer);
380 },413 },
381 .ref_delta => |ref_delta| {414 .ref_delta => |ref_delta| {
382 try delta_offsets.append(odb.allocator, base_offset);415 try delta_offsets.append(odb.allocator, base_offset);
383 try odb.seekOid(ref_delta.base_object);416 try odb.seekOid(ref_delta.base_object);
384 base_offset = try odb.pack_file.getPos();417 base_offset = odb.pack_file.pos - pack_br.bufferedLen();
385 },418 },
386 else => {419 else => {
387 const base_data = try readObjectRaw(odb.allocator, odb.pack_file.reader(), base_header.uncompressedLength());420 const base_data = try readObjectRaw(odb.allocator, &pack_br, base_header.uncompressedLength());
388 errdefer odb.allocator.free(base_data);421 errdefer odb.allocator.free(base_data);
389 const base_object: Object = .{ .type = base_header.objectType(), .data = base_data };422 const base_object: Object = .{ .type = base_header.objectType(), .data = base_data };
390 try odb.cache.put(odb.allocator, base_offset, base_object);423 try odb.cache.put(odb.allocator, base_offset, base_object);
...@@ -414,7 +447,8 @@ const Odb = struct {...@@ -414,7 +447,8 @@ const Odb = struct {
414 const found_index = while (start_index < end_index) {447 const found_index = while (start_index < end_index) {
415 const mid_index = start_index + (end_index - start_index) / 2;448 const mid_index = start_index + (end_index - start_index) / 2;
416 try odb.index_file.seekTo(IndexHeader.size + mid_index * oid_length);449 try odb.index_file.seekTo(IndexHeader.size + mid_index * oid_length);
417 const mid_oid = try Oid.readBytes(odb.format, odb.index_file.reader());450 var br = odb.index_file.interface().unbuffered();
451 const mid_oid = try Oid.readBytes(odb.format, &br);
418 switch (mem.order(u8, mid_oid.slice(), oid.slice())) {452 switch (mem.order(u8, mid_oid.slice(), oid.slice())) {
419 .lt => start_index = mid_index + 1,453 .lt => start_index = mid_index + 1,
420 .gt => end_index = mid_index,454 .gt => end_index = mid_index,
...@@ -424,13 +458,16 @@ const Odb = struct {...@@ -424,13 +458,16 @@ const Odb = struct {
424458
425 const n_objects = odb.index_header.fan_out_table[255];459 const n_objects = odb.index_header.fan_out_table[255];
426 const offset_values_start = IndexHeader.size + n_objects * (oid_length + 4);460 const offset_values_start = IndexHeader.size + n_objects * (oid_length + 4);
461 var buffer: [8]u8 = undefined;
427 try odb.index_file.seekTo(offset_values_start + found_index * 4);462 try odb.index_file.seekTo(offset_values_start + found_index * 4);
428 const l1_offset: packed struct { value: u31, big: bool } = @bitCast(try odb.index_file.reader().readInt(u32, .big));463 var br = odb.index_file.interface().buffered(&buffer);
464 const l1_offset: packed struct { value: u31, big: bool } = @bitCast(try br.takeInt(u32, .big));
429 const pack_offset = pack_offset: {465 const pack_offset = pack_offset: {
430 if (l1_offset.big) {466 if (l1_offset.big) {
431 const l2_offset_values_start = offset_values_start + n_objects * 4;467 const l2_offset_values_start = offset_values_start + n_objects * 4;
432 try odb.index_file.seekTo(l2_offset_values_start + l1_offset.value * 4);468 try odb.index_file.seekTo(l2_offset_values_start + l1_offset.value * 4);
433 break :pack_offset try odb.index_file.reader().readInt(u64, .big);469 br = odb.index_file.interface().buffered(&buffer);
470 break :pack_offset try br.takeInt(u64, .big);
434 } else {471 } else {
435 break :pack_offset l1_offset.value;472 break :pack_offset l1_offset.value;
436 }473 }
...@@ -556,7 +593,7 @@ const Packet = union(enum) {...@@ -556,7 +593,7 @@ const Packet = union(enum) {
556 const max_data_length = 65516;593 const max_data_length = 65516;
557594
558 /// Reads a packet in pkt-line format.595 /// Reads a packet in pkt-line format.
559 fn read(reader: anytype, buf: *[max_data_length]u8) !Packet {596 fn read(reader: *std.io.BufferedReader, buf: *[max_data_length]u8) !Packet {
560 const length = std.fmt.parseUnsigned(u16, &try reader.readBytesNoEof(4), 16) catch return error.InvalidPacket;597 const length = std.fmt.parseUnsigned(u16, &try reader.readBytesNoEof(4), 16) catch return error.InvalidPacket;
561 switch (length) {598 switch (length) {
562 0 => return .flush,599 0 => return .flush,
...@@ -571,7 +608,7 @@ const Packet = union(enum) {...@@ -571,7 +608,7 @@ const Packet = union(enum) {
571 }608 }
572609
573 /// Writes a packet in pkt-line format.610 /// Writes a packet in pkt-line format.
574 fn write(packet: Packet, writer: anytype) !void {611 fn write(packet: Packet, writer: *std.io.BufferedWriter) !void {
575 switch (packet) {612 switch (packet) {
576 .flush => try writer.writeAll("0000"),613 .flush => try writer.writeAll("0000"),
577 .delimiter => try writer.writeAll("0001"),614 .delimiter => try writer.writeAll("0001"),
...@@ -1070,21 +1107,12 @@ const PackHeader = struct {...@@ -1070,21 +1107,12 @@ const PackHeader = struct {
1070 const signature = "PACK";1107 const signature = "PACK";
1071 const supported_version = 2;1108 const supported_version = 2;
10721109
1073 fn read(reader: anytype) !PackHeader {1110 fn read(reader: *std.io.BufferedReader) !PackHeader {
1074 const actual_signature = reader.readBytesNoEof(4) catch |e| switch (e) {1111 const actual_signature = try reader.take(4);
1075 error.EndOfStream => return error.InvalidHeader,1112 if (!mem.eql(u8, actual_signature, signature)) return error.InvalidHeader;
1076 else => |other| return other,1113 const version = try reader.takeInt(u32, .big);
1077 };
1078 if (!mem.eql(u8, &actual_signature, signature)) return error.InvalidHeader;
1079 const version = reader.readInt(u32, .big) catch |e| switch (e) {
1080 error.EndOfStream => return error.InvalidHeader,
1081 else => |other| return other,
1082 };
1083 if (version != supported_version) return error.UnsupportedVersion;1114 if (version != supported_version) return error.UnsupportedVersion;
1084 const total_objects = reader.readInt(u32, .big) catch |e| switch (e) {1115 const total_objects = try reader.takeInt(u32, .big);
1085 error.EndOfStream => return error.InvalidHeader,
1086 else => |other| return other,
1087 };
1088 return .{ .total_objects = total_objects };1116 return .{ .total_objects = total_objects };
1089 }1117 }
1090};1118};
...@@ -1133,12 +1161,9 @@ const EntryHeader = union(Type) {...@@ -1133,12 +1161,9 @@ const EntryHeader = union(Type) {
1133 };1161 };
1134 }1162 }
11351163
1136 fn read(format: Oid.Format, reader: anytype) !EntryHeader {1164 fn read(format: Oid.Format, reader: *std.io.BufferedReader) !EntryHeader {
1137 const InitialByte = packed struct { len: u4, type: u3, has_next: bool };1165 const InitialByte = packed struct { len: u4, type: u3, has_next: bool };
1138 const initial: InitialByte = @bitCast(reader.readByte() catch |e| switch (e) {1166 const initial: InitialByte = @bitCast(try reader.takeByte());
1139 error.EndOfStream => return error.InvalidFormat,
1140 else => |other| return other,
1141 });
1142 const rest_len = if (initial.has_next) try readSizeVarInt(reader) else 0;1167 const rest_len = if (initial.has_next) try readSizeVarInt(reader) else 0;
1143 var uncompressed_length: u64 = initial.len;1168 var uncompressed_length: u64 = initial.len;
1144 uncompressed_length |= std.math.shlExact(u64, rest_len, 4) catch return error.InvalidFormat;1169 uncompressed_length |= std.math.shlExact(u64, rest_len, 4) catch return error.InvalidFormat;
...@@ -1162,25 +1187,25 @@ const EntryHeader = union(Type) {...@@ -1162,25 +1187,25 @@ const EntryHeader = union(Type) {
1162 }1187 }
1163};1188};
11641189
1165fn readSizeVarInt(r: anytype) !u64 {1190fn readSizeVarInt(r: *std.io.BufferedReader) !u64 {
1166 const Byte = packed struct { value: u7, has_next: bool };1191 const Byte = packed struct { value: u7, has_next: bool };
1167 var b: Byte = @bitCast(try r.readByte());1192 var b: Byte = @bitCast(try r.takeByte());
1168 var value: u64 = b.value;1193 var value: u64 = b.value;
1169 var shift: u6 = 0;1194 var shift: u6 = 0;
1170 while (b.has_next) {1195 while (b.has_next) {
1171 b = @bitCast(try r.readByte());1196 b = @bitCast(try r.takeByte());
1172 shift = std.math.add(u6, shift, 7) catch return error.InvalidFormat;1197 shift = std.math.add(u6, shift, 7) catch return error.InvalidFormat;
1173 value |= @as(u64, b.value) << shift;1198 value |= @as(u64, b.value) << shift;
1174 }1199 }
1175 return value;1200 return value;
1176}1201}
11771202
1178fn readOffsetVarInt(r: anytype) !u64 {1203fn readOffsetVarInt(r: *std.io.BufferedReader) !u64 {
1179 const Byte = packed struct { value: u7, has_next: bool };1204 const Byte = packed struct { value: u7, has_next: bool };
1180 var b: Byte = @bitCast(try r.readByte());1205 var b: Byte = @bitCast(try r.takeByte());
1181 var value: u64 = b.value;1206 var value: u64 = b.value;
1182 while (b.has_next) {1207 while (b.has_next) {
1183 b = @bitCast(try r.readByte());1208 b = @bitCast(try r.takeByte());
1184 value = std.math.shlExact(u64, value + 1, 7) catch return error.InvalidFormat;1209 value = std.math.shlExact(u64, value + 1, 7) catch return error.InvalidFormat;
1185 value |= b.value;1210 value |= b.value;
1186 }1211 }
...@@ -1194,19 +1219,12 @@ const IndexHeader = struct {...@@ -1194,19 +1219,12 @@ const IndexHeader = struct {
1194 const supported_version = 2;1219 const supported_version = 2;
1195 const size = 4 + 4 + @sizeOf([256]u32);1220 const size = 4 + 4 + @sizeOf([256]u32);
11961221
1197 fn read(reader: anytype) !IndexHeader {1222 fn read(index_header: *IndexHeader, br: *std.io.BufferedReader) !void {
1198 var header_bytes = try reader.readBytesNoEof(size);1223 const sig = try br.take(4);
1199 if (!mem.eql(u8, header_bytes[0..4], signature)) return error.InvalidHeader;1224 if (!mem.eql(u8, sig, signature)) return error.InvalidHeader;
1200 const version = mem.readInt(u32, header_bytes[4..8], .big);1225 const version = try br.takeInt(u32, .big);
1201 if (version != supported_version) return error.UnsupportedVersion;1226 if (version != supported_version) return error.UnsupportedVersion;
12021227 try br.readSliceEndian(u32, &index_header.fan_out_table, .big);
1203 var fan_out_table: [256]u32 = undefined;
1204 var fan_out_table_stream = std.io.fixedBufferStream(header_bytes[8..]);
1205 const fan_out_table_reader = fan_out_table_stream.reader();
1206 for (&fan_out_table) |*entry| {
1207 entry.* = fan_out_table_reader.readInt(u32, .big) catch unreachable;
1208 }
1209 return .{ .fan_out_table = fan_out_table };
1210 }1228 }
1211};1229};
12121230
...@@ -1217,7 +1235,12 @@ const IndexEntry = struct {...@@ -1217,7 +1235,12 @@ const IndexEntry = struct {
12171235
1218/// Writes out a version 2 index for the given packfile, as documented in1236/// Writes out a version 2 index for the given packfile, as documented in
1219/// [pack-format](https://git-scm.com/docs/pack-format).1237/// [pack-format](https://git-scm.com/docs/pack-format).
1220pub fn indexPack(allocator: Allocator, format: Oid.Format, pack: std.fs.File, index_writer: anytype) !void {1238pub fn indexPack(
1239 allocator: Allocator,
1240 format: Oid.Format,
1241 pack: *std.fs.File.Reader,
1242 index_writer: *std.fs.File.Writer,
1243) !void {
1221 try pack.seekTo(0);1244 try pack.seekTo(0);
12221245
1223 var index_entries: std.AutoHashMapUnmanaged(Oid, IndexEntry) = .empty;1246 var index_entries: std.AutoHashMapUnmanaged(Oid, IndexEntry) = .empty;
...@@ -1270,8 +1293,10 @@ pub fn indexPack(allocator: Allocator, format: Oid.Format, pack: std.fs.File, in...@@ -1270,8 +1293,10 @@ pub fn indexPack(allocator: Allocator, format: Oid.Format, pack: std.fs.File, in
1270 }1293 }
1271 @memset(fan_out_table[fan_out_index..], count);1294 @memset(fan_out_table[fan_out_index..], count);
12721295
1273 var index_hashed_writer = std.compress.hashedWriter(index_writer, Oid.Hasher.init(format));1296 var index_writer_bw = index_writer.writable(&.{});
1274 const writer = index_hashed_writer.writer();1297 var index_hashed_writer = index_writer_bw.hashed(Oid.Hasher.init(format));
1298 var write_buffer: [256]u8 = undefined;
1299 var writer = index_hashed_writer.writable(&write_buffer);
1275 try writer.writeAll(IndexHeader.signature);1300 try writer.writeAll(IndexHeader.signature);
1276 try writer.writeInt(u32, IndexHeader.supported_version, .big);1301 try writer.writeInt(u32, IndexHeader.supported_version, .big);
1277 for (fan_out_table) |fan_out_entry| {1302 for (fan_out_table) |fan_out_entry| {
...@@ -1303,8 +1328,9 @@ pub fn indexPack(allocator: Allocator, format: Oid.Format, pack: std.fs.File, in...@@ -1303,8 +1328,9 @@ pub fn indexPack(allocator: Allocator, format: Oid.Format, pack: std.fs.File, in
1303 }1328 }
13041329
1305 try writer.writeAll(pack_checksum.slice());1330 try writer.writeAll(pack_checksum.slice());
1331 try writer.flush();
1306 const index_checksum = index_hashed_writer.hasher.finalResult();1332 const index_checksum = index_hashed_writer.hasher.finalResult();
1307 try index_writer.writeAll(index_checksum.slice());1333 try index_writer_bw.writeAll(index_checksum.slice());
1308}1334}
13091335
1310/// Performs the first pass over the packfile data for index construction.1336/// Performs the first pass over the packfile data for index construction.
...@@ -1314,50 +1340,46 @@ pub fn indexPack(allocator: Allocator, format: Oid.Format, pack: std.fs.File, in...@@ -1314,50 +1340,46 @@ pub fn indexPack(allocator: Allocator, format: Oid.Format, pack: std.fs.File, in
1314fn indexPackFirstPass(1340fn indexPackFirstPass(
1315 allocator: Allocator,1341 allocator: Allocator,
1316 format: Oid.Format,1342 format: Oid.Format,
1317 pack: std.fs.File,1343 pack: *std.fs.File.Reader,
1318 index_entries: *std.AutoHashMapUnmanaged(Oid, IndexEntry),1344 index_entries: *std.AutoHashMapUnmanaged(Oid, IndexEntry),
1319 pending_deltas: *std.ArrayListUnmanaged(IndexEntry),1345 pending_deltas: *std.ArrayListUnmanaged(IndexEntry),
1320) !Oid {1346) !Oid {
1321 var pack_buffered_reader = std.io.bufferedReader(pack.reader());1347 var pack_br = pack.readable(&.{});
1322 var pack_counting_reader = std.io.countingReader(pack_buffered_reader.reader());1348 var pack_hashed_reader = pack_br.hashed(Oid.Hasher.init(format));
1323 var pack_hashed_reader = std.compress.hashedReader(pack_counting_reader.reader(), Oid.Hasher.init(format));1349 var pack_buffer: [2048]u8 = undefined; // Reasonably large buffer for file system.
1324 const pack_reader = pack_hashed_reader.reader();1350 var pack_hashed_br = pack_hashed_reader.readable(&pack_buffer);
13251351
1326 const pack_header = try PackHeader.read(pack_reader);1352 const pack_header = try PackHeader.read(&pack_hashed_br);
13271353
1328 var current_entry: u32 = 0;1354 for (0..pack_header.total_objects) |_| {
1329 while (current_entry < pack_header.total_objects) : (current_entry += 1) {1355 const entry_offset = pack.pos - pack_hashed_br.bufferContents().len;
1330 const entry_offset = pack_counting_reader.bytes_read;1356 var entry_crc32_reader = pack_hashed_br.hashed(std.hash.Crc32.init());
1331 var entry_crc32_reader = std.compress.hashedReader(pack_reader, std.hash.Crc32.init());1357 var entry_buffer: [64]u8 = undefined; // Buffer only needed for loading EntryHeader.
1332 const entry_header = try EntryHeader.read(format, entry_crc32_reader.reader());1358 var entry_crc32_br = entry_crc32_reader.readable(&entry_buffer);
1359 const entry_header = try EntryHeader.read(format, &entry_crc32_br);
1360 var entry_decompress_stream: zlib.Decompressor = .init(&entry_crc32_br);
1361 // Decompress uses large output buffer; no input buffer needed.
1362 var entry_decompress_br = entry_decompress_stream.readable(&.{});
1333 switch (entry_header) {1363 switch (entry_header) {
1334 .commit, .tree, .blob, .tag => |object| {1364 .commit, .tree, .blob, .tag => |object| {
1335 var entry_decompress_stream = std.compress.zlib.decompressor(entry_crc32_reader.reader());1365 var oid_hasher = Oid.Hasher.init(format);
1336 var entry_counting_reader = std.io.countingReader(entry_decompress_stream.reader());1366 var oid_hasher_buffer: [zlib.max_window_len]u8 = undefined;
1337 var entry_hashed_writer = std.compress.hashedWriter(std.io.null_writer, Oid.Hasher.init(format));1367 var oid_hasher_bw = oid_hasher.writable(&oid_hasher_buffer);
1338 const entry_writer = entry_hashed_writer.writer();
1339 // The object header is not included in the pack data but is1368 // The object header is not included in the pack data but is
1340 // part of the object's ID1369 // part of the object's ID.
1341 try entry_writer.print("{s} {}\x00", .{ @tagName(entry_header), object.uncompressed_length });1370 try oid_hasher_bw.print("{s} {d}\x00", .{ @tagName(entry_header), object.uncompressed_length });
1342 var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();1371 const n = try entry_decompress_br.readRemaining(&oid_hasher_bw);
1343 try fifo.pump(entry_counting_reader.reader(), entry_writer);1372 if (n != object.uncompressed_length) return error.InvalidObject;
1344 if (entry_counting_reader.bytes_read != object.uncompressed_length) {1373 try oid_hasher_bw.flush();
1345 return error.InvalidObject;1374 const oid = oid_hasher.finalResult();
1346 }
1347 const oid = entry_hashed_writer.hasher.finalResult();
1348 try index_entries.put(allocator, oid, .{1375 try index_entries.put(allocator, oid, .{
1349 .offset = entry_offset,1376 .offset = entry_offset,
1350 .crc32 = entry_crc32_reader.hasher.final(),1377 .crc32 = entry_crc32_reader.hasher.final(),
1351 });1378 });
1352 },1379 },
1353 inline .ofs_delta, .ref_delta => |delta| {1380 inline .ofs_delta, .ref_delta => |delta| {
1354 var entry_decompress_stream = std.compress.zlib.decompressor(entry_crc32_reader.reader());1381 const n = try entry_decompress_br.discardRemaining();
1355 var entry_counting_reader = std.io.countingReader(entry_decompress_stream.reader());1382 if (n != delta.uncompressed_length) return error.InvalidObject;
1356 var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();
1357 try fifo.pump(entry_counting_reader.reader(), std.io.null_writer);
1358 if (entry_counting_reader.bytes_read != delta.uncompressed_length) {
1359 return error.InvalidObject;
1360 }
1361 try pending_deltas.append(allocator, .{1383 try pending_deltas.append(allocator, .{
1362 .offset = entry_offset,1384 .offset = entry_offset,
1363 .crc32 = entry_crc32_reader.hasher.final(),1385 .crc32 = entry_crc32_reader.hasher.final(),
...@@ -1367,15 +1389,11 @@ fn indexPackFirstPass(...@@ -1367,15 +1389,11 @@ fn indexPackFirstPass(
1367 }1389 }
13681390
1369 const pack_checksum = pack_hashed_reader.hasher.finalResult();1391 const pack_checksum = pack_hashed_reader.hasher.finalResult();
1370 const recorded_checksum = try Oid.readBytes(format, pack_buffered_reader.reader());1392 const recorded_checksum = try Oid.readBytes(format, &pack_br);
1371 if (!mem.eql(u8, pack_checksum.slice(), recorded_checksum.slice())) {1393 if (!mem.eql(u8, pack_checksum.slice(), recorded_checksum.slice())) {
1372 return error.CorruptedPack;1394 return error.CorruptedPack;
1373 }1395 }
1374 _ = pack_reader.readByte() catch |e| switch (e) {1396 return pack_checksum;
1375 error.EndOfStream => return pack_checksum,
1376 else => |other| return other,
1377 };
1378 return error.InvalidFormat;
1379}1397}
13801398
1381/// Attempts to determine the final object ID of the given deltified object.1399/// Attempts to determine the final object ID of the given deltified object.
...@@ -1384,7 +1402,7 @@ fn indexPackFirstPass(...@@ -1384,7 +1402,7 @@ fn indexPackFirstPass(
1384fn indexPackHashDelta(1402fn indexPackHashDelta(
1385 allocator: Allocator,1403 allocator: Allocator,
1386 format: Oid.Format,1404 format: Oid.Format,
1387 pack: std.fs.File,1405 pack: *std.fs.File.Reader,
1388 delta: IndexEntry,1406 delta: IndexEntry,
1389 index_entries: std.AutoHashMapUnmanaged(Oid, IndexEntry),1407 index_entries: std.AutoHashMapUnmanaged(Oid, IndexEntry),
1390 cache: *ObjectCache,1408 cache: *ObjectCache,
...@@ -1398,7 +1416,9 @@ fn indexPackHashDelta(...@@ -1398,7 +1416,9 @@ fn indexPackHashDelta(
1398 if (cache.get(base_offset)) |base_object| break base_object;1416 if (cache.get(base_offset)) |base_object| break base_object;
13991417
1400 try pack.seekTo(base_offset);1418 try pack.seekTo(base_offset);
1401 base_header = try EntryHeader.read(format, pack.reader());1419 var pack_read_buffer: [64]u8 = undefined;
1420 var pack_br = pack.readable(&pack_read_buffer);
1421 base_header = try EntryHeader.read(format, &pack_br);
1402 switch (base_header) {1422 switch (base_header) {
1403 .ofs_delta => |ofs_delta| {1423 .ofs_delta => |ofs_delta| {
1404 try delta_offsets.append(allocator, base_offset);1424 try delta_offsets.append(allocator, base_offset);
...@@ -1409,7 +1429,7 @@ fn indexPackHashDelta(...@@ -1409,7 +1429,7 @@ fn indexPackHashDelta(
1409 base_offset = (index_entries.get(ref_delta.base_object) orelse return null).offset;1429 base_offset = (index_entries.get(ref_delta.base_object) orelse return null).offset;
1410 },1430 },
1411 else => {1431 else => {
1412 const base_data = try readObjectRaw(allocator, pack.reader(), base_header.uncompressedLength());1432 const base_data = try readObjectRaw(allocator, &pack_br, base_header.uncompressedLength());
1413 errdefer allocator.free(base_data);1433 errdefer allocator.free(base_data);
1414 const base_object: Object = .{ .type = base_header.objectType(), .data = base_data };1434 const base_object: Object = .{ .type = base_header.objectType(), .data = base_data };
1415 try cache.put(allocator, base_offset, base_object);1435 try cache.put(allocator, base_offset, base_object);
...@@ -1421,9 +1441,12 @@ fn indexPackHashDelta(...@@ -1421,9 +1441,12 @@ fn indexPackHashDelta(
1421 const base_data = try resolveDeltaChain(allocator, format, pack, base_object, delta_offsets.items, cache);1441 const base_data = try resolveDeltaChain(allocator, format, pack, base_object, delta_offsets.items, cache);
14221442
1423 var entry_hasher: Oid.Hasher = .init(format);1443 var entry_hasher: Oid.Hasher = .init(format);
1424 var entry_hashed_writer = std.compress.hashedWriter(std.io.null_writer, &entry_hasher);1444 var entry_hasher_buffer: [64]u8 = undefined;
1425 try entry_hashed_writer.writer().print("{s} {}\x00", .{ @tagName(base_object.type), base_data.len });1445 var entry_hasher_bw = entry_hasher.writable(&entry_hasher_buffer);
1426 entry_hasher.update(base_data);1446 // Writes to hashers cannot fail.
1447 entry_hasher_bw.print("{s} {d}\x00", .{ @tagName(base_object.type), base_data.len }) catch unreachable;
1448 entry_hasher_bw.writeAll(base_data) catch unreachable;
1449 entry_hasher_bw.flush() catch unreachable;
1427 return entry_hasher.finalResult();1450 return entry_hasher.finalResult();
1428}1451}
14291452
...@@ -1434,7 +1457,7 @@ fn indexPackHashDelta(...@@ -1434,7 +1457,7 @@ fn indexPackHashDelta(
1434fn resolveDeltaChain(1457fn resolveDeltaChain(
1435 allocator: Allocator,1458 allocator: Allocator,
1436 format: Oid.Format,1459 format: Oid.Format,
1437 pack: std.fs.File,1460 pack: *std.fs.File.Reader,
1438 base_object: Object,1461 base_object: Object,
1439 delta_offsets: []const u64,1462 delta_offsets: []const u64,
1440 cache: *ObjectCache,1463 cache: *ObjectCache,
...@@ -1446,21 +1469,22 @@ fn resolveDeltaChain(...@@ -1446,21 +1469,22 @@ fn resolveDeltaChain(
14461469
1447 const delta_offset = delta_offsets[i];1470 const delta_offset = delta_offsets[i];
1448 try pack.seekTo(delta_offset);1471 try pack.seekTo(delta_offset);
1449 const delta_header = try EntryHeader.read(format, pack.reader());1472 var pack_read_buffer: [64]u8 = undefined;
1450 const delta_data = try readObjectRaw(allocator, pack.reader(), delta_header.uncompressedLength());1473 var pack_br = pack.readable(&pack_read_buffer);
1451 defer allocator.free(delta_data);1474 const delta_header = try EntryHeader.read(format, &pack_br);
1452 var delta_stream = std.io.fixedBufferStream(delta_data);1475 _ = delta_header;
1453 const delta_reader = delta_stream.reader();1476 var delta_decompress: zlib.Decompressor = .init(&pack_br);
1454 _ = try readSizeVarInt(delta_reader); // base object size1477 var delta_decompress_buffer: [zlib.max_window_len]u8 = undefined;
1455 const expanded_size = try readSizeVarInt(delta_reader);1478 var delta_reader = delta_decompress.readable(&delta_decompress_buffer);
14561479 _ = try readSizeVarInt(&delta_reader); // base object size
1480 const expanded_size = try readSizeVarInt(&delta_reader);
1457 const expanded_alloc_size = std.math.cast(usize, expanded_size) orelse return error.ObjectTooLarge;1481 const expanded_alloc_size = std.math.cast(usize, expanded_size) orelse return error.ObjectTooLarge;
1458 const expanded_data = try allocator.alloc(u8, expanded_alloc_size);1482 const expanded_data = try allocator.alloc(u8, expanded_alloc_size);
1459 errdefer allocator.free(expanded_data);1483 errdefer allocator.free(expanded_data);
1460 var expanded_delta_stream = std.io.fixedBufferStream(expanded_data);1484 var expanded_delta_stream: std.io.BufferedWriter = undefined;
1461 var base_stream = std.io.fixedBufferStream(base_data);1485 expanded_delta_stream.initFixed(expanded_data);
1462 try expandDelta(&base_stream, delta_reader, expanded_delta_stream.writer());1486 try expandDelta(base_data, &delta_reader, &expanded_delta_stream);
1463 if (expanded_delta_stream.pos != expanded_size) return error.InvalidObject;1487 if (expanded_delta_stream.end != expanded_size) return error.InvalidObject;
14641488
1465 try cache.put(allocator, delta_offset, .{ .type = base_object.type, .data = expanded_data });1489 try cache.put(allocator, delta_offset, .{ .type = base_object.type, .data = expanded_data });
1466 base_data = expanded_data;1490 base_data = expanded_data;
...@@ -1468,31 +1492,23 @@ fn resolveDeltaChain(...@@ -1468,31 +1492,23 @@ fn resolveDeltaChain(
1468 return base_data;1492 return base_data;
1469}1493}
14701494
1471/// Reads the complete contents of an object from `reader`. This function may1495/// Reads the complete contents of an object from `reader`.
1472/// read more bytes than required from `reader`, so the reader position after1496fn readObjectRaw(gpa: Allocator, reader: *std.io.BufferedReader, size: u64) ![]u8 {
1473/// returning is not reliable.
1474fn readObjectRaw(allocator: Allocator, reader: anytype, size: u64) ![]u8 {
1475 const alloc_size = std.math.cast(usize, size) orelse return error.ObjectTooLarge;1497 const alloc_size = std.math.cast(usize, size) orelse return error.ObjectTooLarge;
1476 var buffered_reader = std.io.bufferedReader(reader);1498 var decompress: zlib.Decompressor = .init(reader);
1477 var decompress_stream = std.compress.zlib.decompressor(buffered_reader.reader());1499 var buffer: std.ArrayListUnmanaged(u8) = .empty;
1478 const data = try allocator.alloc(u8, alloc_size);1500 defer buffer.deinit(gpa);
1479 errdefer allocator.free(data);1501 try decompress.reader().readRemainingArrayList(gpa, null, &buffer, .limited(alloc_size), zlib.max_window_len);
1480 try decompress_stream.reader().readNoEof(data);1502 if (buffer.items.len < size) return error.EndOfStream;
1481 _ = decompress_stream.reader().readByte() catch |e| switch (e) {1503 return buffer.toOwnedSlice(gpa);
1482 error.EndOfStream => return data,
1483 else => |other| return other,
1484 };
1485 return error.InvalidFormat;
1486}1504}
14871505
1488/// Expands delta data from `delta_reader` to `writer`. `base_object` must
1489/// support `reader` and `seekTo` (such as a `std.io.FixedBufferStream`).
1490///
1491/// The format of the delta data is documented in1506/// The format of the delta data is documented in
1492/// [pack-format](https://git-scm.com/docs/pack-format).1507/// [pack-format](https://git-scm.com/docs/pack-format).
1493fn expandDelta(base_object: anytype, delta_reader: *std.io.BufferedReader, writer: *std.io.BufferedWriter) !void {1508fn expandDelta(base_object: []const u8, delta_reader: *std.io.BufferedReader, writer: *std.io.BufferedWriter) !void {
1509 var base_offset: u32 = 0;
1494 while (true) {1510 while (true) {
1495 const inst: packed struct { value: u7, copy: bool } = @bitCast(delta_reader.readByte() catch |e| switch (e) {1511 const inst: packed struct { value: u7, copy: bool } = @bitCast(delta_reader.takeByte() catch |e| switch (e) {
1496 error.EndOfStream => return,1512 error.EndOfStream => return,
1497 else => |other| return other,1513 else => |other| return other,
1498 });1514 });
...@@ -1507,23 +1523,22 @@ fn expandDelta(base_object: anytype, delta_reader: *std.io.BufferedReader, write...@@ -1507,23 +1523,22 @@ fn expandDelta(base_object: anytype, delta_reader: *std.io.BufferedReader, write
1507 size3: bool,1523 size3: bool,
1508 } = @bitCast(inst.value);1524 } = @bitCast(inst.value);
1509 const offset_parts: packed struct { offset1: u8, offset2: u8, offset3: u8, offset4: u8 } = .{1525 const offset_parts: packed struct { offset1: u8, offset2: u8, offset3: u8, offset4: u8 } = .{
1510 .offset1 = if (available.offset1) try delta_reader.readByte() else 0,1526 .offset1 = if (available.offset1) try delta_reader.takeByte() else 0,
1511 .offset2 = if (available.offset2) try delta_reader.readByte() else 0,1527 .offset2 = if (available.offset2) try delta_reader.takeByte() else 0,
1512 .offset3 = if (available.offset3) try delta_reader.readByte() else 0,1528 .offset3 = if (available.offset3) try delta_reader.takeByte() else 0,
1513 .offset4 = if (available.offset4) try delta_reader.readByte() else 0,1529 .offset4 = if (available.offset4) try delta_reader.takeByte() else 0,
1514 };1530 };
1515 const offset: u32 = @bitCast(offset_parts);1531 base_offset = @bitCast(offset_parts);
1516 const size_parts: packed struct { size1: u8, size2: u8, size3: u8 } = .{1532 const size_parts: packed struct { size1: u8, size2: u8, size3: u8 } = .{
1517 .size1 = if (available.size1) try delta_reader.readByte() else 0,1533 .size1 = if (available.size1) try delta_reader.takeByte() else 0,
1518 .size2 = if (available.size2) try delta_reader.readByte() else 0,1534 .size2 = if (available.size2) try delta_reader.takeByte() else 0,
1519 .size3 = if (available.size3) try delta_reader.readByte() else 0,1535 .size3 = if (available.size3) try delta_reader.takeByte() else 0,
1520 };1536 };
1521 var size: u24 = @bitCast(size_parts);1537 var size: u24 = @bitCast(size_parts);
1522 if (size == 0) size = 0x10000;1538 if (size == 0) size = 0x10000;
1523 try base_object.seekTo(offset);
15241539
1525 var base_object_br = base_object.reader();1540 try writer.writeAll(base_object[base_offset..][0..size]);
1526 try base_object_br.readAll(writer, .limited(size));1541 base_offset += size;
1527 } else if (inst.value != 0) {1542 } else if (inst.value != 0) {
1528 try delta_reader.readAll(writer, .limited(inst.value));1543 try delta_reader.readAll(writer, .limited(inst.value));
1529 } else {1544 } else {
...@@ -1557,7 +1572,8 @@ fn runRepositoryTest(comptime format: Oid.Format, head_commit: []const u8) !void...@@ -1557,7 +1572,8 @@ fn runRepositoryTest(comptime format: Oid.Format, head_commit: []const u8) !void
15571572
1558 var index_file = try git_dir.dir.createFile("testrepo.idx", .{ .read = true });1573 var index_file = try git_dir.dir.createFile("testrepo.idx", .{ .read = true });
1559 defer index_file.close();1574 defer index_file.close();
1560 try indexPack(testing.allocator, format, pack_file, index_file.writer());1575 var index_file_writer = index_file.writer();
1576 try indexPack(testing.allocator, format, pack_file, &index_file_writer);
15611577
1562 // Arbitrary size limit on files read while checking the repository contents1578 // Arbitrary size limit on files read while checking the repository contents
1563 // (all files in the test repo are known to be smaller than this)1579 // (all files in the test repo are known to be smaller than this)
...@@ -1571,7 +1587,8 @@ fn runRepositoryTest(comptime format: Oid.Format, head_commit: []const u8) !void...@@ -1571,7 +1587,8 @@ fn runRepositoryTest(comptime format: Oid.Format, head_commit: []const u8) !void
1571 const testrepo_idx = @embedFile("git/testdata/testrepo-" ++ @tagName(format) ++ ".idx");1587 const testrepo_idx = @embedFile("git/testdata/testrepo-" ++ @tagName(format) ++ ".idx");
1572 try testing.expectEqualSlices(u8, testrepo_idx, index_file_data);1588 try testing.expectEqualSlices(u8, testrepo_idx, index_file_data);
15731589
1574 var repository = try Repository.init(testing.allocator, format, pack_file, index_file);1590 var index_file_reader = index_file_writer.moveToReader();
1591 var repository = try Repository.init(testing.allocator, format, pack_file, &index_file_reader);
1575 defer repository.deinit();1592 defer repository.deinit();
15761593
1577 var worktree = testing.tmpDir(.{ .iterate = true });1594 var worktree = testing.tmpDir(.{ .iterate = true });
...@@ -1652,10 +1669,12 @@ test "SHA-256 packfile indexing and checkout" {...@@ -1652,10 +1669,12 @@ test "SHA-256 packfile indexing and checkout" {
1652/// Checks out a commit of a packfile. Intended for experimenting with and1669/// Checks out a commit of a packfile. Intended for experimenting with and
1653/// benchmarking possible optimizations to the indexing and checkout behavior.1670/// benchmarking possible optimizations to the indexing and checkout behavior.
1654pub fn main() !void {1671pub fn main() !void {
1655 const allocator = std.heap.c_allocator;1672 var debug_allocator: std.heap.DebugAllocator(.{}) = .init;
1673 defer _ = debug_allocator.deinit();
1674 const gpa = if (std.debug.runtime_safety) debug_allocator.allocator() else std.heap.smp_allocator;
16561675
1657 const args = try std.process.argsAlloc(allocator);1676 const args = try std.process.argsAlloc(gpa);
1658 defer std.process.argsFree(allocator, args);1677 defer std.process.argsFree(gpa, args);
1659 if (args.len != 5) {1678 if (args.len != 5) {
1660 return error.InvalidArguments; // Arguments: format packfile commit worktree1679 return error.InvalidArguments; // Arguments: format packfile commit worktree
1661 }1680 }
...@@ -1674,15 +1693,17 @@ pub fn main() !void {...@@ -1674,15 +1693,17 @@ pub fn main() !void {
1674 std.debug.print("Starting index...\n", .{});1693 std.debug.print("Starting index...\n", .{});
1675 var index_file = try git_dir.createFile("idx", .{ .read = true });1694 var index_file = try git_dir.createFile("idx", .{ .read = true });
1676 defer index_file.close();1695 defer index_file.close();
1677 var index_buffered_writer = std.io.bufferedWriter(index_file.writer());1696 var index_file_writer = index_file.writer();
1678 try indexPack(allocator, format, pack_file, index_buffered_writer.writer());1697 var pack_file_reader = pack_file.reader();
1679 try index_buffered_writer.flush();1698 try indexPack(gpa, format, &pack_file_reader, &index_file_writer);
1680 try index_file.sync();1699 try index_file.sync();
16811700
1682 std.debug.print("Starting checkout...\n", .{});1701 std.debug.print("Starting checkout...\n", .{});
1683 var repository = try Repository.init(allocator, format, pack_file, index_file);1702 var index_file_reader = index_file_writer.moveToReader();
1703 var repository: Repository = undefined;
1704 try repository.init(gpa, format, &pack_file_reader, &index_file_reader);
1684 defer repository.deinit();1705 defer repository.deinit();
1685 var diagnostics: Diagnostics = .{ .allocator = allocator };1706 var diagnostics: Diagnostics = .{ .allocator = gpa };
1686 defer diagnostics.deinit();1707 defer diagnostics.deinit();
1687 try repository.checkout(worktree, commit, &diagnostics);1708 try repository.checkout(worktree, commit, &diagnostics);
16881709
src/main.zig+3-4
...@@ -3330,12 +3330,11 @@ fn buildOutputType(...@@ -3330,12 +3330,11 @@ fn buildOutputType(
3330 // for the hashing algorithm here and in the cache are the same.3330 // for the hashing algorithm here and in the cache are the same.
3331 // We are providing our own cache key, because this file has nothing3331 // We are providing our own cache key, because this file has nothing
3332 // to do with the cache manifest.3332 // to do with the cache manifest.
3333 var hasher = Cache.Hasher.init("0123456789abcdef");
3334 var file_writer = f.writer();3333 var file_writer = f.writer();
3335 var file_writer_bw = file_writer.interface().unbuffered();3334 var file_writer_bw = file_writer.writable(&.{});
3336 var hasher_writer = hasher.writer(&file_writer_bw);3335 var hasher_writer = file_writer_bw.hashed(Cache.Hasher.init("0123456789abcdef"));
3337 var buffer: [1000]u8 = undefined;3336 var buffer: [1000]u8 = undefined;
3338 var bw = hasher_writer.interface().buffered(&buffer);3337 var bw = hasher_writer.writable(&buffer);
3339 bw.writeFileAll(.stdin(), .{}) catch |err| switch (err) {3338 bw.writeFileAll(.stdin(), .{}) catch |err| switch (err) {
3340 error.WriteFailed => fatal("failed to write {s}: {s}", .{ dump_path, file_writer.err.? }),3339 error.WriteFailed => fatal("failed to write {s}: {s}", .{ dump_path, file_writer.err.? }),
3341 else => fatal("failed to pipe stdin to {s}: {s}", .{ dump_path, err }),3340 else => fatal("failed to pipe stdin to {s}: {s}", .{ dump_path, err }),