| ... | @@ -13,6 +13,7 @@ const os = @import("os.zig"); | ... | @@ -13,6 +13,7 @@ const os = @import("os.zig"); |
| 13 | const base64_encoder = fs.base64_encoder; | 13 | const base64_encoder = fs.base64_encoder; |
| 14 | const base64_decoder = fs.base64_decoder; | 14 | const base64_decoder = fs.base64_decoder; |
| 15 | const BIN_DIGEST_LEN = 32; | 15 | const BIN_DIGEST_LEN = 32; |
| | 16 | const BASE64_DIGEST_LEN = base64.Base64Encoder.calcSize(BIN_DIGEST_LEN); |
| 16 | | 17 | |
| 17 | pub const File = struct { | 18 | pub const File = struct { |
| 18 | path: ?[]const u8, | 19 | path: ?[]const u8, |
| ... | @@ -41,7 +42,7 @@ pub const CacheHash = struct { | ... | @@ -41,7 +42,7 @@ pub const CacheHash = struct { |
| 41 | manifest_dirty: bool, | 42 | manifest_dirty: bool, |
| 42 | force_check_manifest: bool, | 43 | force_check_manifest: bool, |
| 43 | files: ArrayList(File), | 44 | files: ArrayList(File), |
| 44 | b64_digest: ArrayList(u8), | 45 | b64_digest: [BASE64_DIGEST_LEN]u8, |
| 45 | | 46 | |
| 46 | pub fn init(alloc: *Allocator, manifest_dir_path: []const u8) !@This() { | 47 | pub fn init(alloc: *Allocator, manifest_dir_path: []const u8) !@This() { |
| 47 | try fs.cwd().makePath(manifest_dir_path); | 48 | try fs.cwd().makePath(manifest_dir_path); |
| ... | @@ -55,7 +56,7 @@ pub const CacheHash = struct { | ... | @@ -55,7 +56,7 @@ pub const CacheHash = struct { |
| 55 | .manifest_dirty = false, | 56 | .manifest_dirty = false, |
| 56 | .force_check_manifest = false, | 57 | .force_check_manifest = false, |
| 57 | .files = ArrayList(File).init(alloc), | 58 | .files = ArrayList(File).init(alloc), |
| 58 | .b64_digest = ArrayList(u8).init(alloc), | 59 | .b64_digest = undefined, |
| 59 | }; | 60 | }; |
| 60 | } | 61 | } |
| 61 | | 62 | |
| ... | @@ -126,27 +127,23 @@ pub const CacheHash = struct { | ... | @@ -126,27 +127,23 @@ pub const CacheHash = struct { |
| 126 | self.addSlice(cache_hash_file.path.?); | 127 | self.addSlice(cache_hash_file.path.?); |
| 127 | } | 128 | } |
| 128 | | 129 | |
| 129 | pub fn hit(self: *@This(), out_digest: *ArrayList(u8)) !bool { | 130 | pub fn hit(self: *@This()) !?[BASE64_DIGEST_LEN]u8 { |
| 130 | debug.assert(self.manifest_file == null); | 131 | debug.assert(self.manifest_file == null); |
| 131 | | 132 | |
| 132 | var bin_digest: [BIN_DIGEST_LEN]u8 = undefined; | 133 | var bin_digest: [BIN_DIGEST_LEN]u8 = undefined; |
| 133 | self.blake3.final(&bin_digest); | 134 | self.blake3.final(&bin_digest); |
| 134 | | 135 | |
| 135 | const OUT_DIGEST_LEN = base64.Base64Encoder.calcSize(BIN_DIGEST_LEN); | 136 | base64_encoder.encode(self.b64_digest[0..], &bin_digest); |
| 136 | try self.b64_digest.resize(OUT_DIGEST_LEN); | | |
| 137 | base64_encoder.encode(self.b64_digest.toSlice(), &bin_digest); | | |
| 138 | | 137 | |
| 139 | if (self.files.toSlice().len == 0 and !self.force_check_manifest) { | 138 | if (self.files.toSlice().len == 0 and !self.force_check_manifest) { |
| 140 | try out_digest.resize(OUT_DIGEST_LEN); | 139 | return self.b64_digest; |
| 141 | mem.copy(u8, out_digest.toSlice(), self.b64_digest.toSlice()); | | |
| 142 | return true; | | |
| 143 | } | 140 | } |
| 144 | | 141 | |
| 145 | self.blake3 = Blake3.init(); | 142 | self.blake3 = Blake3.init(); |
| 146 | self.blake3.update(&bin_digest); | 143 | self.blake3.update(&bin_digest); |
| 147 | | 144 | |
| 148 | { | 145 | { |
| 149 | const manifest_file_path = try fmt.allocPrint(self.alloc, "{}.txt", .{self.b64_digest.toSlice()}); | 146 | const manifest_file_path = try fmt.allocPrint(self.alloc, "{}.txt", .{self.b64_digest}); |
| 150 | defer self.alloc.free(manifest_file_path); | 147 | defer self.alloc.free(manifest_file_path); |
| 151 | | 148 | |
| 152 | self.manifest_file = try self.manifest_dir.createFile(manifest_file_path, .{ .read = true, .truncate = false }); | 149 | self.manifest_file = try self.manifest_dir.createFile(manifest_file_path, .{ .read = true, .truncate = false }); |
| ... | @@ -231,7 +228,7 @@ pub const CacheHash = struct { | ... | @@ -231,7 +228,7 @@ pub const CacheHash = struct { |
| 231 | for (self.files.toSlice()) |file| { | 228 | for (self.files.toSlice()) |file| { |
| 232 | self.blake3.update(&file.bin_digest); | 229 | self.blake3.update(&file.bin_digest); |
| 233 | } | 230 | } |
| 234 | return false; | 231 | return null; |
| 235 | } | 232 | } |
| 236 | | 233 | |
| 237 | if (idx < input_file_count or idx == 0) { | 234 | if (idx < input_file_count or idx == 0) { |
| ... | @@ -244,11 +241,10 @@ pub const CacheHash = struct { | ... | @@ -244,11 +241,10 @@ pub const CacheHash = struct { |
| 244 | return error.CacheUnavailable; | 241 | return error.CacheUnavailable; |
| 245 | }; | 242 | }; |
| 246 | } | 243 | } |
| 247 | return false; | 244 | return null; |
| 248 | } | 245 | } |
| 249 | | 246 | |
| 250 | try self.final(out_digest); | 247 | return try self.final(); |
| 251 | return true; | | |
| 252 | } | 248 | } |
| 253 | | 249 | |
| 254 | pub fn populate_file_hash(self: *@This(), cache_hash_file: *File) !void { | 250 | pub fn populate_file_hash(self: *@This(), cache_hash_file: *File) !void { |
| ... | @@ -265,22 +261,22 @@ pub const CacheHash = struct { | ... | @@ -265,22 +261,22 @@ pub const CacheHash = struct { |
| 265 | self.blake3.update(&cache_hash_file.bin_digest); | 261 | self.blake3.update(&cache_hash_file.bin_digest); |
| 266 | } | 262 | } |
| 267 | | 263 | |
| 268 | pub fn final(self: *@This(), out_digest: *ArrayList(u8)) !void { | 264 | pub fn final(self: *@This()) ![BASE64_DIGEST_LEN]u8 { |
| 269 | debug.assert(self.manifest_file != null); | 265 | debug.assert(self.manifest_file != null); |
| 270 | | 266 | |
| 271 | var bin_digest: [BIN_DIGEST_LEN]u8 = undefined; | 267 | var bin_digest: [BIN_DIGEST_LEN]u8 = undefined; |
| 272 | self.blake3.final(&bin_digest); | 268 | self.blake3.final(&bin_digest); |
| 273 | | 269 | |
| 274 | const OUT_DIGEST_LEN = base64.Base64Encoder.calcSize(BIN_DIGEST_LEN); | 270 | var out_digest: [BASE64_DIGEST_LEN]u8 = undefined; |
| 275 | try out_digest.resize(OUT_DIGEST_LEN); | 271 | base64_encoder.encode(&out_digest, &bin_digest); |
| 276 | base64_encoder.encode(out_digest.toSlice(), &bin_digest); | 272 | |
| | 273 | return out_digest; |
| 277 | } | 274 | } |
| 278 | | 275 | |
| 279 | pub fn write_manifest(self: *@This()) !void { | 276 | pub fn write_manifest(self: *@This()) !void { |
| 280 | debug.assert(self.manifest_file != null); | 277 | debug.assert(self.manifest_file != null); |
| 281 | | 278 | |
| 282 | const OUT_DIGEST_LEN = base64.Base64Encoder.calcSize(BIN_DIGEST_LEN); | 279 | var encoded_digest = try Buffer.initSize(self.alloc, BASE64_DIGEST_LEN); |
| 283 | var encoded_digest = try Buffer.initSize(self.alloc, OUT_DIGEST_LEN); | | |
| 284 | defer encoded_digest.deinit(); | 280 | defer encoded_digest.deinit(); |
| 285 | var contents = try Buffer.init(self.alloc, ""); | 281 | var contents = try Buffer.init(self.alloc, ""); |
| 286 | defer contents.deinit(); | 282 | defer contents.deinit(); |
| ... | @@ -308,7 +304,6 @@ pub const CacheHash = struct { | ... | @@ -308,7 +304,6 @@ pub const CacheHash = struct { |
| 308 | file.deinit(self.alloc); | 304 | file.deinit(self.alloc); |
| 309 | } | 305 | } |
| 310 | self.files.deinit(); | 306 | self.files.deinit(); |
| 311 | self.b64_digest.deinit(); | | |
| 312 | self.manifest_dir.close(); | 307 | self.manifest_dir.close(); |
| 313 | } | 308 | } |
| 314 | }; | 309 | }; |
| ... | @@ -332,10 +327,8 @@ test "cache file and the recall it" { | ... | @@ -332,10 +327,8 @@ test "cache file and the recall it" { |
| 332 | | 327 | |
| 333 | try cwd.writeFile("test.txt", "Hello, world!\n"); | 328 | try cwd.writeFile("test.txt", "Hello, world!\n"); |
| 334 | | 329 | |
| 335 | var digest1 = try ArrayList(u8).initCapacity(testing.allocator, 32); | 330 | var digest1: [BASE64_DIGEST_LEN]u8 = undefined; |
| 336 | defer digest1.deinit(); | 331 | var digest2: [BASE64_DIGEST_LEN]u8 = undefined; |
| 337 | var digest2 = try ArrayList(u8).initCapacity(testing.allocator, 32); | | |
| 338 | defer digest2.deinit(); | | |
| 339 | | 332 | |
| 340 | { | 333 | { |
| 341 | var ch = try CacheHash.init(testing.allocator, temp_manifest_dir); | 334 | var ch = try CacheHash.init(testing.allocator, temp_manifest_dir); |
| ... | @@ -347,9 +340,9 @@ test "cache file and the recall it" { | ... | @@ -347,9 +340,9 @@ test "cache file and the recall it" { |
| 347 | try ch.addFile("test.txt"); | 340 | try ch.addFile("test.txt"); |
| 348 | | 341 | |
| 349 | // There should be nothing in the cache | 342 | // There should be nothing in the cache |
| 350 | debug.assert((try ch.hit(&digest1)) == false); | 343 | debug.assert((try ch.hit()) == null); |
| 351 | | 344 | |
| 352 | try ch.final(&digest1); | 345 | digest1 = try ch.final(); |
| 353 | } | 346 | } |
| 354 | { | 347 | { |
| 355 | var ch = try CacheHash.init(testing.allocator, temp_manifest_dir); | 348 | var ch = try CacheHash.init(testing.allocator, temp_manifest_dir); |
| ... | @@ -361,10 +354,10 @@ test "cache file and the recall it" { | ... | @@ -361,10 +354,10 @@ test "cache file and the recall it" { |
| 361 | try ch.addFile("test.txt"); | 354 | try ch.addFile("test.txt"); |
| 362 | | 355 | |
| 363 | // Cache hit! We just "built" the same file | 356 | // Cache hit! We just "built" the same file |
| 364 | debug.assert((try ch.hit(&digest2)) == true); | 357 | digest2 = (try ch.hit()).?; |
| 365 | } | 358 | } |
| 366 | | 359 | |
| 367 | debug.assert(mem.eql(u8, digest1.toSlice(), digest2.toSlice())); | 360 | debug.assert(mem.eql(u8, digest1[0..], digest2[0..])); |
| 368 | | 361 | |
| 369 | try cwd.deleteTree(temp_manifest_dir); | 362 | try cwd.deleteTree(temp_manifest_dir); |
| 370 | } | 363 | } |