authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-04-13 02:33:28 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-04-13 02:33:28 -07:00
log52075b3bd908a77c2cd2aebc5b480354643496f7
treea98d0dc94b1bb20d265aa379d092be53e973ba46
parent3c080a86f2a7cc235c0d64245399fcf306cde245
signaturebadge-check Signed by SSH key SHA256:4hHJbtBRU58AYXwjL7fkz2fnQHdiye8x1QpTCQ0sHNw

use zlib c library for decompression


2 files changed, 95 insertions(+), 15 deletions(-)

git.zig+71-15
...@@ -966,18 +966,20 @@ pub const Repository = struct {...@@ -966,18 +966,20 @@ pub const Repository = struct {
966 else => |e| return e,966 else => |e| return e,
967 };967 };
968 defer objfile.close();968 defer objfile.close();
969 var bufr = nio.BufferedReader(4096, nfs.File).init(objfile);969 const compressed_content = try objfile.mmap();
970 var list: std.ArrayList(u8) = .init(r.gpa);970 defer nfs.munmap(compressed_content);
971 errdefer list.deinit();971 var list: std.ArrayListUnmanaged(u8) = .empty;
972 try list.ensureUnusedCapacity(512);972 errdefer list.deinit(r.gpa);
973 try std.compress.flate.inflate.decompress(.zlib, bufr.anyReadable(), list.writer());973 try list.ensureUnusedCapacity(r.gpa, 512);
974 // try std.compress.flate.inflate.decompress(.zlib, bufr.anyReadable(), list.writer());
975 try inflate_decompress(compressed_content, &list, r.gpa);
974 const data = list.items;976 const data = list.items;
975 const header = data[0..std.mem.indexOfScalar(u8, data, 0).?];977 const header = data[0..std.mem.indexOfScalar(u8, data, 0).?];
976 const _type_s = header[0..std.mem.indexOfScalar(u8, header, ' ').?];978 const _type_s = header[0..std.mem.indexOfScalar(u8, header, ' ').?];
977 const _type = std.meta.stringToEnum(RefType, _type_s).?;979 const _type = std.meta.stringToEnum(RefType, _type_s).?;
978 const content_len = try extras.parseDigits(u64, header[_type_s.len + 1 ..], 10);980 const content_len = try extras.parseDigits(u64, header[_type_s.len + 1 ..], 10);
979 list.replaceRangeAssumeCapacity(0, header.len + 1, "");981 list.replaceRangeAssumeCapacity(0, header.len + 1, "");
980 const content = try list.toOwnedSlice();982 const content = try list.toOwnedSlice(r.gpa);
981 std.debug.assert(content.len == content_len);983 std.debug.assert(content.len == content_len);
982 const obj: GitObject = .{ .type = _type, .content = content };984 const obj: GitObject = .{ .type = _type, .content = content };
983 try r.unpacked_objects.put(r.gpa, oid, obj);985 try r.unpacked_objects.put(r.gpa, oid, obj);
...@@ -1096,13 +1098,13 @@ pub const Repository = struct {...@@ -1096,13 +1098,13 @@ pub const Repository = struct {
1096 },1098 },
1097 .commit, .tree, .blob, .tag => {1099 .commit, .tree, .blob, .tag => {
1098 const compressed_content = packedobj_fbs.rest()[0..size];1100 const compressed_content = packedobj_fbs.rest()[0..size];
1099 var bufr = nio.FixedBufferStream([]const u8).init(compressed_content);1101 var list: std.ArrayListUnmanaged(u8) = .empty;
1100 var list: std.ArrayList(u8) = .init(r.gpa);1102 errdefer list.deinit(r.gpa);
1101 errdefer list.deinit();1103 try list.ensureUnusedCapacity(r.gpa, 512);
1102 try list.ensureUnusedCapacity(512);1104 // try std.compress.flate.inflate.decompress(.zlib, bufr.anyReadable(), list.writer());
1103 try std.compress.flate.inflate.decompress(.zlib, bufr.anyReadable(), list.writer());1105 try inflate_decompress(compressed_content, &list, r.gpa);
1104 const _type = std.meta.stringToEnum(RefType, @tagName(ty)).?;1106 const _type = std.meta.stringToEnum(RefType, @tagName(ty)).?;
1105 const content = try list.toOwnedSlice();1107 const content = try list.toOwnedSlice(r.gpa);
1106 const obj: GitObject = .{ .type = _type, .content = content };1108 const obj: GitObject = .{ .type = _type, .content = content };
1107 if (maybe_oid) |oid| try r.unpacked_objects.put(r.gpa, oid, obj);1109 if (maybe_oid) |oid| try r.unpacked_objects.put(r.gpa, oid, obj);
1108 return obj;1110 return obj;
...@@ -1140,12 +1142,11 @@ pub const Repository = struct {...@@ -1140,12 +1142,11 @@ pub const Repository = struct {
11401142
1141 fn getDeltadObject(r: *Repository, maybe_oid: ?Id, packedobj_fbs: *nio.FixedBufferStream([]const u8), size: usize, base_obj: GitObject) !GitObject {1143 fn getDeltadObject(r: *Repository, maybe_oid: ?Id, packedobj_fbs: *nio.FixedBufferStream([]const u8), size: usize, base_obj: GitObject) !GitObject {
1142 const compressed_content = packedobj_fbs.rest()[0..size];1144 const compressed_content = packedobj_fbs.rest()[0..size];
1143 var bufr = nio.FixedBufferStream([]const u8).init(compressed_content);
1144
1145 var list: std.ArrayListUnmanaged(u8) = .empty;1145 var list: std.ArrayListUnmanaged(u8) = .empty;
1146 defer list.deinit(r.gpa);1146 defer list.deinit(r.gpa);
1147 try list.ensureUnusedCapacity(r.gpa, size);1147 try list.ensureUnusedCapacity(r.gpa, size);
1148 try std.compress.flate.inflate.decompress(.zlib, bufr.anyReadable(), list.writer(r.gpa));1148 // try std.compress.flate.inflate.decompress(.zlib, bufr.anyReadable(), list.writer(r.gpa));
1149 try inflate_decompress(compressed_content, &list, r.gpa);
1149 // std.log.debug("transformation data={d}", .{list.items});1150 // std.log.debug("transformation data={d}", .{list.items});
11501151
1151 var unpackedobj_fbs = nio.FixedBufferStream([]const u8).init(list.items);1152 var unpackedobj_fbs = nio.FixedBufferStream([]const u8).init(list.items);
...@@ -1362,3 +1363,58 @@ pub const Repository = struct {...@@ -1362,3 +1363,58 @@ pub const Repository = struct {
1362 }1363 }
1363 }1364 }
1364};1365};
1366
1367const z = @cImport({
1368 @cInclude("zlib.h");
1369});
1370
1371fn inflate_decompress(in: []const u8, out: *std.ArrayListUnmanaged(u8), allocator: std.mem.Allocator) !void {
1372 // std.log.debug("{x}", .{in});
1373 var strm: z.z_stream = std.mem.zeroes(z.z_stream);
1374 {
1375 const ret: ZlibCode = @enumFromInt(z.inflateInit(&strm));
1376 if (ret == .Z_MEM_ERROR) return error.OutOfMemory;
1377 std.debug.assert(ret != .Z_VERSION_ERROR);
1378 std.debug.assert(ret != .Z_STREAM_ERROR);
1379 }
1380 defer {
1381 const ret: ZlibCode = @enumFromInt(z.inflateEnd(&strm));
1382 std.debug.assert(ret != .Z_STREAM_ERROR);
1383 std.debug.assert(ret == .Z_OK);
1384 }
1385 strm.next_in = @constCast(in.ptr);
1386 strm.avail_in = @intCast(in.len);
1387 // std.log.debug("inflate_decompress: -> {*} {d}", .{ strm.next_in, strm.avail_in });
1388
1389 while (true) {
1390 var buf: [16384]u8 = @splat(0);
1391 strm.next_out = &buf;
1392 strm.avail_out = buf.len;
1393 // std.log.debug("inflate_decompress: -> {*} {*} {d} {d}", .{ strm.next_in, strm.next_out, strm.avail_in, strm.avail_out });
1394 const ret: ZlibCode = @enumFromInt(z.inflate(&strm, z.Z_NO_FLUSH));
1395 // std.log.debug("inflate_decompress: <- {*} {*} {d} {d} {s}", .{ strm.next_in, strm.next_out, strm.avail_in, strm.avail_out, @tagName(ret) });
1396 std.debug.assert(ret != .Z_STREAM_ERROR);
1397 // if (ret == .Z_BUF_ERROR) std.log.err("{s}", .{strm.msg});
1398 std.debug.assert(ret != .Z_BUF_ERROR);
1399 if (ret == .Z_MEM_ERROR) return error.OutOfMemory;
1400 if (ret == .Z_DATA_ERROR) return error.Z_DATA_ERROR;
1401 if (ret == .Z_NEED_DICT) return error.Z_NEED_DICT;
1402 // Z_ERRNO
1403 // Z_VERSION_ERROR
1404 std.debug.assert(ret == .Z_OK or ret == .Z_STREAM_END);
1405 try out.appendSlice(allocator, buf[0 .. buf.len - strm.avail_out]);
1406 if (ret == .Z_STREAM_END) break;
1407 }
1408}
1409
1410const ZlibCode = enum(c_int) {
1411 Z_OK = 0,
1412 Z_STREAM_END = 1,
1413 Z_NEED_DICT = 2,
1414 Z_ERRNO = -1,
1415 Z_STREAM_ERROR = -2,
1416 Z_DATA_ERROR = -3,
1417 Z_MEM_ERROR = -4,
1418 Z_BUF_ERROR = -5,
1419 Z_VERSION_ERROR = -6,
1420};
zig.mod+24
...@@ -9,6 +9,30 @@ dependencies:...@@ -9,6 +9,30 @@ dependencies:
9 - src: git https://github.com/nektro/zig-tracer9 - src: git https://github.com/nektro/zig-tracer
10 - src: git https://github.com/nektro/zig-nfs10 - src: git https://github.com/nektro/zig-nfs
11 - src: git https://github.com/nektro/zig-nio11 - src: git https://github.com/nektro/zig-nio
12
13 - src: git https://github.com/madler/zlib tag-v1.3.2
14 license: Zlib
15 c_include_dirs:
16 -
17 c_source_files:
18 - inftrees.c
19 - inflate.c
20 - adler32.c
21 - zutil.c
22 - trees.c
23 - gzclose.c
24 - gzwrite.c
25 - gzread.c
26 - deflate.c
27 - compress.c
28 - crc32.c
29 - infback.c
30 - gzlib.c
31 - uncompr.c
32 - inffast.c
33 c_source_flags:
34 - -DZ_HAVE_UNISTD_H=1
35
12root_dependencies:36root_dependencies:
13 - src: git https://github.com/nektro/zig-extras37 - src: git https://github.com/nektro/zig-extras
14 - src: git https://github.com/nektro/zig-expect38 - src: git https://github.com/nektro/zig-expect