| author | |
| committer | |
| log | 05ce1f99a60df0bcede00af1c98a1e5fdce35051 |
| tree | b9dfb4f32f94125bda0a1ad925fec8a66179f9ed |
| parent | 2569f4ff8514f47730c1abd42691f8fc1cdd22d5 |
7 files changed, 122 insertions(+), 107 deletions(-)
lib/std/Io/Reader.zig+9| ... | @@ -1709,6 +1709,15 @@ fn failingDiscard(r: *Reader, limit: Limit) Error!usize { | ... | @@ -1709,6 +1709,15 @@ fn failingDiscard(r: *Reader, limit: Limit) Error!usize { |
| 1709 | return error.ReadFailed; | 1709 | return error.ReadFailed; |
| 1710 | } | 1710 | } |
| 1711 | 1711 | ||
| 1712 | pub fn adaptToOldInterface(r: *Reader) std.Io.AnyReader { | ||
| 1713 | return .{ .context = r, .readFn = derpRead }; | ||
| 1714 | } | ||
| 1715 | |||
| 1716 | fn derpRead(context: *const anyopaque, buffer: []u8) anyerror!usize { | ||
| 1717 | const r: *Reader = @constCast(@alignCast(@ptrCast(context))); | ||
| 1718 | return r.readSliceShort(buffer); | ||
| 1719 | } | ||
| 1720 | |||
| 1712 | test "readAlloc when the backing reader provides one byte at a time" { | 1721 | test "readAlloc when the backing reader provides one byte at a time" { |
| 1713 | const str = "This is a test"; | 1722 | const str = "This is a test"; |
| 1714 | var tiny_buffer: [1]u8 = undefined; | 1723 | var tiny_buffer: [1]u8 = undefined; |
lib/std/compress/flate/Decompress.zig+5-5| ... | @@ -23,7 +23,7 @@ dst_dec: DistanceDecoder, | ... | @@ -23,7 +23,7 @@ dst_dec: DistanceDecoder, |
| 23 | final_block: bool, | 23 | final_block: bool, |
| 24 | state: State, | 24 | state: State, |
| 25 | 25 | ||
| 26 | read_err: ?Error, | 26 | err: ?Error, |
| 27 | 27 | ||
| 28 | const BlockType = enum(u2) { | 28 | const BlockType = enum(u2) { |
| 29 | stored = 0, | 29 | stored = 0, |
| ... | @@ -74,7 +74,7 @@ pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress { | ... | @@ -74,7 +74,7 @@ pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress { |
| 74 | .dst_dec = .{}, | 74 | .dst_dec = .{}, |
| 75 | .final_block = false, | 75 | .final_block = false, |
| 76 | .state = .protocol_header, | 76 | .state = .protocol_header, |
| 77 | .read_err = null, | 77 | .err = null, |
| 78 | }; | 78 | }; |
| 79 | } | 79 | } |
| 80 | 80 | ||
| ... | @@ -153,7 +153,7 @@ pub fn stream(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!us | ... | @@ -153,7 +153,7 @@ pub fn stream(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!us |
| 153 | if (d.state == .end) { | 153 | if (d.state == .end) { |
| 154 | return error.EndOfStream; | 154 | return error.EndOfStream; |
| 155 | } else { | 155 | } else { |
| 156 | d.read_err = error.EndOfStream; | 156 | d.err = error.EndOfStream; |
| 157 | return error.ReadFailed; | 157 | return error.ReadFailed; |
| 158 | } | 158 | } |
| 159 | }, | 159 | }, |
| ... | @@ -161,7 +161,7 @@ pub fn stream(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!us | ... | @@ -161,7 +161,7 @@ pub fn stream(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!us |
| 161 | else => |e| { | 161 | else => |e| { |
| 162 | // In the event of an error, state is unmodified so that it can be | 162 | // In the event of an error, state is unmodified so that it can be |
| 163 | // better used to diagnose the failure. | 163 | // better used to diagnose the failure. |
| 164 | d.read_err = e; | 164 | d.err = e; |
| 165 | return error.ReadFailed; | 165 | return error.ReadFailed; |
| 166 | }, | 166 | }, |
| 167 | }; | 167 | }; |
| ... | @@ -1179,7 +1179,7 @@ fn testFailure(container: Container, in: []const u8, expected_err: anyerror) !vo | ... | @@ -1179,7 +1179,7 @@ fn testFailure(container: Container, in: []const u8, expected_err: anyerror) !vo |
| 1179 | 1179 | ||
| 1180 | var decompress: Decompress = .init(&reader, container, &.{}); | 1180 | var decompress: Decompress = .init(&reader, container, &.{}); |
| 1181 | try testing.expectError(error.ReadFailed, decompress.reader.streamRemaining(&aw.writer)); | 1181 | try testing.expectError(error.ReadFailed, decompress.reader.streamRemaining(&aw.writer)); |
| 1182 | try testing.expectEqual(expected_err, decompress.read_err orelse return error.TestFailed); | 1182 | try testing.expectEqual(expected_err, decompress.err orelse return error.TestFailed); |
| 1183 | } | 1183 | } |
| 1184 | 1184 | ||
| 1185 | fn testDecompress(container: Container, compressed: []const u8, expected_plain: []const u8) !void { | 1185 | fn testDecompress(container: Container, compressed: []const u8, expected_plain: []const u8) !void { |
lib/std/http/Client.zig+9-10| ... | @@ -405,8 +405,8 @@ pub const RequestTransfer = union(enum) { | ... | @@ -405,8 +405,8 @@ pub const RequestTransfer = union(enum) { |
| 405 | 405 | ||
| 406 | /// The decompressor for response messages. | 406 | /// The decompressor for response messages. |
| 407 | pub const Compression = union(enum) { | 407 | pub const Compression = union(enum) { |
| 408 | deflate: std.compress.flate.Decompress, | 408 | //deflate: std.compress.flate.Decompress, |
| 409 | gzip: std.compress.flate.Decompress, | 409 | //gzip: std.compress.flate.Decompress, |
| 410 | // https://github.com/ziglang/zig/issues/18937 | 410 | // https://github.com/ziglang/zig/issues/18937 |
| 411 | //zstd: ZstdDecompressor, | 411 | //zstd: ZstdDecompressor, |
| 412 | none: void, | 412 | none: void, |
| ... | @@ -1074,12 +1074,10 @@ pub const Request = struct { | ... | @@ -1074,12 +1074,10 @@ pub const Request = struct { |
| 1074 | switch (req.response.transfer_compression) { | 1074 | switch (req.response.transfer_compression) { |
| 1075 | .identity => req.response.compression = .none, | 1075 | .identity => req.response.compression = .none, |
| 1076 | .compress, .@"x-compress" => return error.CompressionUnsupported, | 1076 | .compress, .@"x-compress" => return error.CompressionUnsupported, |
| 1077 | .deflate => req.response.compression = .{ | 1077 | // I'm about to upstream my http.Client rewrite |
| 1078 | .deflate = std.compress.zlib.decompressor(req.transferReader()), | 1078 | .deflate => return error.CompressionUnsupported, |
| 1079 | }, | 1079 | // I'm about to upstream my http.Client rewrite |
| 1080 | .gzip, .@"x-gzip" => req.response.compression = .{ | 1080 | .gzip, .@"x-gzip" => return error.CompressionUnsupported, |
| 1081 | .gzip = std.compress.gzip.decompressor(req.transferReader()), | ||
| 1082 | }, | ||
| 1083 | // https://github.com/ziglang/zig/issues/18937 | 1081 | // https://github.com/ziglang/zig/issues/18937 |
| 1084 | //.zstd => req.response.compression = .{ | 1082 | //.zstd => req.response.compression = .{ |
| 1085 | // .zstd = std.compress.zstd.decompressStream(req.client.allocator, req.transferReader()), | 1083 | // .zstd = std.compress.zstd.decompressStream(req.client.allocator, req.transferReader()), |
| ... | @@ -1105,8 +1103,9 @@ pub const Request = struct { | ... | @@ -1105,8 +1103,9 @@ pub const Request = struct { |
| 1105 | /// Reads data from the response body. Must be called after `wait`. | 1103 | /// Reads data from the response body. Must be called after `wait`. |
| 1106 | pub fn read(req: *Request, buffer: []u8) ReadError!usize { | 1104 | pub fn read(req: *Request, buffer: []u8) ReadError!usize { |
| 1107 | const out_index = switch (req.response.compression) { | 1105 | const out_index = switch (req.response.compression) { |
| 1108 | .deflate => |*deflate| deflate.read(buffer) catch return error.DecompressionFailure, | 1106 | // I'm about to upstream my http client rewrite |
| 1109 | .gzip => |*gzip| gzip.read(buffer) catch return error.DecompressionFailure, | 1107 | //.deflate => |*deflate| deflate.readSlice(buffer) catch return error.DecompressionFailure, |
| 1108 | //.gzip => |*gzip| gzip.read(buffer) catch return error.DecompressionFailure, | ||
| 1110 | // https://github.com/ziglang/zig/issues/18937 | 1109 | // https://github.com/ziglang/zig/issues/18937 |
| 1111 | //.zstd => |*zstd| zstd.read(buffer) catch return error.DecompressionFailure, | 1110 | //.zstd => |*zstd| zstd.read(buffer) catch return error.DecompressionFailure, |
| 1112 | else => try req.transferRead(buffer), | 1111 | else => try req.transferRead(buffer), |
lib/std/zip.zig+45-39| ... | @@ -7,8 +7,9 @@ const builtin = @import("builtin"); | ... | @@ -7,8 +7,9 @@ const builtin = @import("builtin"); |
| 7 | const std = @import("std"); | 7 | const std = @import("std"); |
| 8 | const File = std.fs.File; | 8 | const File = std.fs.File; |
| 9 | const is_le = builtin.target.cpu.arch.endian() == .little; | 9 | const is_le = builtin.target.cpu.arch.endian() == .little; |
| 10 | const Writer = std.io.Writer; | 10 | const Writer = std.Io.Writer; |
| 11 | const Reader = std.io.Reader; | 11 | const Reader = std.Io.Reader; |
| 12 | const flate = std.compress.flate; | ||
| 12 | 13 | ||
| 13 | pub const CompressionMethod = enum(u16) { | 14 | pub const CompressionMethod = enum(u16) { |
| 14 | store = 0, | 15 | store = 0, |
| ... | @@ -117,6 +118,7 @@ pub const EndRecord = extern struct { | ... | @@ -117,6 +118,7 @@ pub const EndRecord = extern struct { |
| 117 | pub const FindFileError = File.GetEndPosError || File.SeekError || File.ReadError || error{ | 118 | pub const FindFileError = File.GetEndPosError || File.SeekError || File.ReadError || error{ |
| 118 | ZipNoEndRecord, | 119 | ZipNoEndRecord, |
| 119 | EndOfStream, | 120 | EndOfStream, |
| 121 | ReadFailed, | ||
| 120 | }; | 122 | }; |
| 121 | 123 | ||
| 122 | pub fn findFile(fr: *File.Reader) FindFileError!EndRecord { | 124 | pub fn findFile(fr: *File.Reader) FindFileError!EndRecord { |
| ... | @@ -137,8 +139,7 @@ pub const EndRecord = extern struct { | ... | @@ -137,8 +139,7 @@ pub const EndRecord = extern struct { |
| 137 | 139 | ||
| 138 | try fr.seekTo(end_pos - @as(u64, new_loaded_len)); | 140 | try fr.seekTo(end_pos - @as(u64, new_loaded_len)); |
| 139 | const read_buf: []u8 = buf[buf.len - new_loaded_len ..][0..read_len]; | 141 | const read_buf: []u8 = buf[buf.len - new_loaded_len ..][0..read_len]; |
| 140 | var br = fr.interface().unbuffered(); | 142 | fr.interface.readSliceAll(read_buf) catch |err| switch (err) { |
| 141 | br.readSlice(read_buf) catch |err| switch (err) { | ||
| 142 | error.ReadFailed => return fr.err.?, | 143 | error.ReadFailed => return fr.err.?, |
| 143 | error.EndOfStream => return error.EndOfStream, | 144 | error.EndOfStream => return error.EndOfStream, |
| 144 | }; | 145 | }; |
| ... | @@ -164,7 +165,7 @@ pub const EndRecord = extern struct { | ... | @@ -164,7 +165,7 @@ pub const EndRecord = extern struct { |
| 164 | pub const Decompress = struct { | 165 | pub const Decompress = struct { |
| 165 | interface: Reader, | 166 | interface: Reader, |
| 166 | state: union { | 167 | state: union { |
| 167 | inflate: std.compress.flate.Decompress, | 168 | inflate: flate.Decompress, |
| 168 | store: *Reader, | 169 | store: *Reader, |
| 169 | }, | 170 | }, |
| 170 | 171 | ||
| ... | @@ -201,7 +202,7 @@ pub const Decompress = struct { | ... | @@ -201,7 +202,7 @@ pub const Decompress = struct { |
| 201 | 202 | ||
| 202 | fn streamDeflate(r: *Reader, w: *Writer, limit: std.io.Limit) Reader.StreamError!usize { | 203 | fn streamDeflate(r: *Reader, w: *Writer, limit: std.io.Limit) Reader.StreamError!usize { |
| 203 | const d: *Decompress = @fieldParentPtr("interface", r); | 204 | const d: *Decompress = @fieldParentPtr("interface", r); |
| 204 | return std.compress.flate.Decompress.read(&d.inflate, w, limit); | 205 | return flate.Decompress.read(&d.inflate, w, limit); |
| 205 | } | 206 | } |
| 206 | }; | 207 | }; |
| 207 | 208 | ||
| ... | @@ -305,7 +306,7 @@ pub const Iterator = struct { | ... | @@ -305,7 +306,7 @@ pub const Iterator = struct { |
| 305 | if (locator_end_offset > stream_len) | 306 | if (locator_end_offset > stream_len) |
| 306 | return error.ZipTruncated; | 307 | return error.ZipTruncated; |
| 307 | try input.seekTo(stream_len - locator_end_offset); | 308 | try input.seekTo(stream_len - locator_end_offset); |
| 308 | const locator = input.interface.takeStructEndian(EndLocator64, .little) catch |err| switch (err) { | 309 | const locator = input.interface.takeStruct(EndLocator64, .little) catch |err| switch (err) { |
| 309 | error.ReadFailed => return input.err.?, | 310 | error.ReadFailed => return input.err.?, |
| 310 | error.EndOfStream => return error.EndOfStream, | 311 | error.EndOfStream => return error.EndOfStream, |
| 311 | }; | 312 | }; |
| ... | @@ -318,7 +319,7 @@ pub const Iterator = struct { | ... | @@ -318,7 +319,7 @@ pub const Iterator = struct { |
| 318 | 319 | ||
| 319 | try input.seekTo(locator.record_file_offset); | 320 | try input.seekTo(locator.record_file_offset); |
| 320 | 321 | ||
| 321 | const record64 = input.interface.takeStructEndian(EndRecord64, .little) catch |err| switch (err) { | 322 | const record64 = input.interface.takeStruct(EndRecord64, .little) catch |err| switch (err) { |
| 322 | error.ReadFailed => return input.err.?, | 323 | error.ReadFailed => return input.err.?, |
| 323 | error.EndOfStream => return error.EndOfStream, | 324 | error.EndOfStream => return error.EndOfStream, |
| 324 | }; | 325 | }; |
| ... | @@ -374,7 +375,7 @@ pub const Iterator = struct { | ... | @@ -374,7 +375,7 @@ pub const Iterator = struct { |
| 374 | const header_zip_offset = self.cd_zip_offset + self.cd_record_offset; | 375 | const header_zip_offset = self.cd_zip_offset + self.cd_record_offset; |
| 375 | const input = self.input; | 376 | const input = self.input; |
| 376 | try input.seekTo(header_zip_offset); | 377 | try input.seekTo(header_zip_offset); |
| 377 | const header = input.interface.takeStructEndian(CentralDirectoryFileHeader, .little) catch |err| switch (err) { | 378 | const header = input.interface.takeStruct(CentralDirectoryFileHeader, .little) catch |err| switch (err) { |
| 378 | error.ReadFailed => return input.err.?, | 379 | error.ReadFailed => return input.err.?, |
| 379 | error.EndOfStream => return error.EndOfStream, | 380 | error.EndOfStream => return error.EndOfStream, |
| 380 | }; | 381 | }; |
| ... | @@ -405,7 +406,7 @@ pub const Iterator = struct { | ... | @@ -405,7 +406,7 @@ pub const Iterator = struct { |
| 405 | const extra = extra_buf[0..header.extra_len]; | 406 | const extra = extra_buf[0..header.extra_len]; |
| 406 | 407 | ||
| 407 | try input.seekTo(header_zip_offset + @sizeOf(CentralDirectoryFileHeader) + header.filename_len); | 408 | try input.seekTo(header_zip_offset + @sizeOf(CentralDirectoryFileHeader) + header.filename_len); |
| 408 | input.interface.readSlice(extra) catch |err| switch (err) { | 409 | input.interface.readSliceAll(extra) catch |err| switch (err) { |
| 409 | error.ReadFailed => return input.err.?, | 410 | error.ReadFailed => return input.err.?, |
| 410 | error.EndOfStream => return error.EndOfStream, | 411 | error.EndOfStream => return error.EndOfStream, |
| 411 | }; | 412 | }; |
| ... | @@ -460,7 +461,7 @@ pub const Iterator = struct { | ... | @@ -460,7 +461,7 @@ pub const Iterator = struct { |
| 460 | options: ExtractOptions, | 461 | options: ExtractOptions, |
| 461 | filename_buf: []u8, | 462 | filename_buf: []u8, |
| 462 | dest: std.fs.Dir, | 463 | dest: std.fs.Dir, |
| 463 | ) !u32 { | 464 | ) !void { |
| 464 | if (filename_buf.len < self.filename_len) | 465 | if (filename_buf.len < self.filename_len) |
| 465 | return error.ZipInsufficientBuffer; | 466 | return error.ZipInsufficientBuffer; |
| 466 | switch (self.compression_method) { | 467 | switch (self.compression_method) { |
| ... | @@ -470,13 +471,13 @@ pub const Iterator = struct { | ... | @@ -470,13 +471,13 @@ pub const Iterator = struct { |
| 470 | const filename = filename_buf[0..self.filename_len]; | 471 | const filename = filename_buf[0..self.filename_len]; |
| 471 | { | 472 | { |
| 472 | try stream.seekTo(self.header_zip_offset + @sizeOf(CentralDirectoryFileHeader)); | 473 | try stream.seekTo(self.header_zip_offset + @sizeOf(CentralDirectoryFileHeader)); |
| 473 | try stream.interface.readSlice(filename); | 474 | try stream.interface.readSliceAll(filename); |
| 474 | } | 475 | } |
| 475 | 476 | ||
| 476 | const local_data_header_offset: u64 = local_data_header_offset: { | 477 | const local_data_header_offset: u64 = local_data_header_offset: { |
| 477 | const local_header = blk: { | 478 | const local_header = blk: { |
| 478 | try stream.seekTo(self.file_offset); | 479 | try stream.seekTo(self.file_offset); |
| 479 | break :blk try stream.interface.takeStructEndian(LocalFileHeader, .little); | 480 | break :blk try stream.interface.takeStruct(LocalFileHeader, .little); |
| 480 | }; | 481 | }; |
| 481 | if (!std.mem.eql(u8, &local_header.signature, &local_file_header_sig)) | 482 | if (!std.mem.eql(u8, &local_header.signature, &local_file_header_sig)) |
| 482 | return error.ZipBadFileOffset; | 483 | return error.ZipBadFileOffset; |
| ... | @@ -502,7 +503,7 @@ pub const Iterator = struct { | ... | @@ -502,7 +503,7 @@ pub const Iterator = struct { |
| 502 | 503 | ||
| 503 | { | 504 | { |
| 504 | try stream.seekTo(self.file_offset + @sizeOf(LocalFileHeader) + local_header.filename_len); | 505 | try stream.seekTo(self.file_offset + @sizeOf(LocalFileHeader) + local_header.filename_len); |
| 505 | try stream.interface.readSlice(extra); | 506 | try stream.interface.readSliceAll(extra); |
| 506 | } | 507 | } |
| 507 | 508 | ||
| 508 | var extra_offset: usize = 0; | 509 | var extra_offset: usize = 0; |
| ... | @@ -550,7 +551,7 @@ pub const Iterator = struct { | ... | @@ -550,7 +551,7 @@ pub const Iterator = struct { |
| 550 | if (self.uncompressed_size != 0) | 551 | if (self.uncompressed_size != 0) |
| 551 | return error.ZipBadDirectorySize; | 552 | return error.ZipBadDirectorySize; |
| 552 | try dest.makePath(filename[0 .. filename.len - 1]); | 553 | try dest.makePath(filename[0 .. filename.len - 1]); |
| 553 | return std.hash.Crc32.hash(&.{}); | 554 | return; |
| 554 | } | 555 | } |
| 555 | 556 | ||
| 556 | const out_file = blk: { | 557 | const out_file = blk: { |
| ... | @@ -564,31 +565,36 @@ pub const Iterator = struct { | ... | @@ -564,31 +565,36 @@ pub const Iterator = struct { |
| 564 | break :blk try dest.createFile(filename, .{ .exclusive = true }); | 565 | break :blk try dest.createFile(filename, .{ .exclusive = true }); |
| 565 | }; | 566 | }; |
| 566 | defer out_file.close(); | 567 | defer out_file.close(); |
| 567 | var file_writer = out_file.writer(); | 568 | var out_file_buffer: [1024]u8 = undefined; |
| 568 | var file_bw = file_writer.writer(&.{}); | 569 | var file_writer = out_file.writer(&out_file_buffer); |
| 569 | const local_data_file_offset: u64 = | 570 | const local_data_file_offset: u64 = |
| 570 | @as(u64, self.file_offset) + | 571 | @as(u64, self.file_offset) + |
| 571 | @as(u64, @sizeOf(LocalFileHeader)) + | 572 | @as(u64, @sizeOf(LocalFileHeader)) + |
| 572 | local_data_header_offset; | 573 | local_data_header_offset; |
| 573 | try stream.seekTo(local_data_file_offset); | 574 | try stream.seekTo(local_data_file_offset); |
| 574 | var limited_file_reader = stream.interface.limited(.limited(self.compressed_size)); | 575 | |
| 575 | var file_read_buffer: [1000]u8 = undefined; | 576 | // TODO limit based on self.compressed_size |
| 576 | var decompress_read_buffer: [1000]u8 = undefined; | 577 | |
| 577 | var limited_br = limited_file_reader.reader().buffered(&file_read_buffer); | 578 | switch (self.compression_method) { |
| 578 | var decompress: Decompress = undefined; | 579 | .store => { |
| 579 | var decompress_br = decompress.readable(&limited_br, self.compression_method, &decompress_read_buffer); | 580 | stream.interface.streamExact(&file_writer.interface, self.uncompressed_size) catch |err| switch (err) { |
| 580 | const start_out = file_bw.count; | 581 | error.ReadFailed => return stream.err.?, |
| 581 | var hash_writer = file_bw.hashed(std.hash.Crc32.init()); | 582 | error.WriteFailed => return file_writer.err.?, |
| 582 | var hash_bw = hash_writer.writer(&.{}); | 583 | error.EndOfStream => return error.ZipDecompressTruncated, |
| 583 | decompress_br.readAll(&hash_bw, .limited(self.uncompressed_size)) catch |err| switch (err) { | 584 | }; |
| 584 | error.ReadFailed => return stream.err.?, | 585 | }, |
| 585 | error.WriteFailed => return file_writer.err.?, | 586 | .deflate => { |
| 586 | error.EndOfStream => return error.ZipDecompressTruncated, | 587 | var flate_buffer: [flate.max_window_len]u8 = undefined; |
| 587 | }; | 588 | var decompress: flate.Decompress = .init(&stream.interface, .raw, &flate_buffer); |
| 588 | if (limited_file_reader.remaining.nonzero()) return error.ZipDecompressTruncated; | 589 | decompress.reader.streamExact(&file_writer.interface, self.uncompressed_size) catch |err| switch (err) { |
| 589 | const written = file_bw.count - start_out; | 590 | error.ReadFailed => return stream.err.?, |
| 590 | if (written != self.uncompressed_size) return error.ZipUncompressSizeMismatch; | 591 | error.WriteFailed => return file_writer.err orelse decompress.err.?, |
| 591 | return hash_writer.hasher.final(); | 592 | error.EndOfStream => return error.ZipDecompressTruncated, |
| 593 | }; | ||
| 594 | }, | ||
| 595 | else => return error.UnsupportedCompressionMethod, | ||
| 596 | } | ||
| 597 | try file_writer.end(); | ||
| 592 | } | 598 | } |
| 593 | }; | 599 | }; |
| 594 | }; | 600 | }; |
| ... | @@ -636,19 +642,19 @@ pub const ExtractOptions = struct { | ... | @@ -636,19 +642,19 @@ pub const ExtractOptions = struct { |
| 636 | /// Allow filenames within the zip to use backslashes. Back slashes are normalized | 642 | /// Allow filenames within the zip to use backslashes. Back slashes are normalized |
| 637 | /// to forward slashes before forwarding them to platform APIs. | 643 | /// to forward slashes before forwarding them to platform APIs. |
| 638 | allow_backslashes: bool = false, | 644 | allow_backslashes: bool = false, |
| 639 | |||
| 640 | diagnostics: ?*Diagnostics = null, | 645 | diagnostics: ?*Diagnostics = null, |
| 646 | verify_checksums: bool = false, | ||
| 641 | }; | 647 | }; |
| 642 | 648 | ||
| 643 | /// Extract the zipped files to the given `dest` directory. | 649 | /// Extract the zipped files to the given `dest` directory. |
| 644 | pub fn extract(dest: std.fs.Dir, fr: *File.Reader, options: ExtractOptions) !void { | 650 | pub fn extract(dest: std.fs.Dir, fr: *File.Reader, options: ExtractOptions) !void { |
| 651 | if (options.verify_checksums) @panic("TODO unimplemented"); | ||
| 652 | |||
| 645 | var iter = try Iterator.init(fr); | 653 | var iter = try Iterator.init(fr); |
| 646 | 654 | ||
| 647 | var filename_buf: [std.fs.max_path_bytes]u8 = undefined; | 655 | var filename_buf: [std.fs.max_path_bytes]u8 = undefined; |
| 648 | while (try iter.next()) |entry| { | 656 | while (try iter.next()) |entry| { |
| 649 | const crc32 = try entry.extract(fr, options, &filename_buf, dest); | 657 | try entry.extract(fr, options, &filename_buf, dest); |
| 650 | if (crc32 != entry.crc32) | ||
| 651 | return error.ZipCrcMismatch; | ||
| 652 | if (options.diagnostics) |d| { | 658 | if (options.diagnostics) |d| { |
| 653 | try d.nextFilename(filename_buf[0..entry.filename_len]); | 659 | try d.nextFilename(filename_buf[0..entry.filename_len]); |
| 654 | } | 660 | } |
src/Package/Fetch.zig+15-10| ... | @@ -1203,12 +1203,11 @@ fn unpackResource( | ... | @@ -1203,12 +1203,11 @@ fn unpackResource( |
| 1203 | return unpackTarball(f, tmp_directory.handle, &adapter.new_interface); | 1203 | return unpackTarball(f, tmp_directory.handle, &adapter.new_interface); |
| 1204 | }, | 1204 | }, |
| 1205 | .@"tar.gz" => { | 1205 | .@"tar.gz" => { |
| 1206 | const reader = resource.reader(); | 1206 | var adapter_buffer: [std.crypto.tls.max_ciphertext_record_len]u8 = undefined; |
| 1207 | var br = std.io.bufferedReaderSize(std.crypto.tls.max_ciphertext_record_len, reader); | 1207 | var adapter = resource.reader().adaptToNewApi(&adapter_buffer); |
| 1208 | var dcp = std.compress.gzip.decompressor(br.reader()); | 1208 | var flate_buffer: [std.compress.flate.max_window_len]u8 = undefined; |
| 1209 | var adapter_buffer: [1024]u8 = undefined; | 1209 | var decompress: std.compress.flate.Decompress = .init(&adapter.new_interface, .gzip, &flate_buffer); |
| 1210 | var adapter = dcp.reader().adaptToNewApi(&adapter_buffer); | 1210 | return try unpackTarball(f, tmp_directory.handle, &decompress.reader); |
| 1211 | return try unpackTarball(f, tmp_directory.handle, &adapter.new_interface); | ||
| 1212 | }, | 1211 | }, |
| 1213 | .@"tar.xz" => { | 1212 | .@"tar.xz" => { |
| 1214 | const gpa = f.arena.child_allocator; | 1213 | const gpa = f.arena.child_allocator; |
| ... | @@ -1352,7 +1351,10 @@ fn unzip(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!UnpackResult { | ... | @@ -1352,7 +1351,10 @@ fn unzip(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!UnpackResult { |
| 1352 | )); | 1351 | )); |
| 1353 | defer zip_file.close(); | 1352 | defer zip_file.close(); |
| 1354 | 1353 | ||
| 1355 | std.zip.extract(out_dir, zip_file.seekableStream(), .{ | 1354 | var zip_file_buffer: [1024]u8 = undefined; |
| 1355 | var zip_file_reader = zip_file.reader(&zip_file_buffer); | ||
| 1356 | |||
| 1357 | std.zip.extract(out_dir, &zip_file_reader, .{ | ||
| 1356 | .allow_backslashes = true, | 1358 | .allow_backslashes = true, |
| 1357 | .diagnostics = &diagnostics, | 1359 | .diagnostics = &diagnostics, |
| 1358 | }) catch |err| return f.fail(f.location_tok, try eb.printString( | 1360 | }) catch |err| return f.fail(f.location_tok, try eb.printString( |
| ... | @@ -1384,23 +1386,26 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U | ... | @@ -1384,23 +1386,26 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U |
| 1384 | defer pack_dir.close(); | 1386 | defer pack_dir.close(); |
| 1385 | var pack_file = try pack_dir.createFile("pkg.pack", .{ .read = true }); | 1387 | var pack_file = try pack_dir.createFile("pkg.pack", .{ .read = true }); |
| 1386 | defer pack_file.close(); | 1388 | defer pack_file.close(); |
| 1387 | var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init(); | 1389 | var pack_file_buffer: [4096]u8 = undefined; |
| 1390 | var fifo = std.fifo.LinearFifo(u8, .{ .Slice = {} }).init(&pack_file_buffer); | ||
| 1388 | try fifo.pump(resource.fetch_stream.reader(), pack_file.deprecatedWriter()); | 1391 | try fifo.pump(resource.fetch_stream.reader(), pack_file.deprecatedWriter()); |
| 1389 | 1392 | ||
| 1393 | var pack_file_reader = pack_file.reader(&pack_file_buffer); | ||
| 1394 | |||
| 1390 | var index_file = try pack_dir.createFile("pkg.idx", .{ .read = true }); | 1395 | var index_file = try pack_dir.createFile("pkg.idx", .{ .read = true }); |
| 1391 | defer index_file.close(); | 1396 | defer index_file.close(); |
| 1392 | { | 1397 | { |
| 1393 | const index_prog_node = f.prog_node.start("Index pack", 0); | 1398 | const index_prog_node = f.prog_node.start("Index pack", 0); |
| 1394 | defer index_prog_node.end(); | 1399 | defer index_prog_node.end(); |
| 1395 | var index_buffered_writer = std.io.bufferedWriter(index_file.deprecatedWriter()); | 1400 | var index_buffered_writer = std.io.bufferedWriter(index_file.deprecatedWriter()); |
| 1396 | try git.indexPack(gpa, object_format, pack_file, index_buffered_writer.writer()); | 1401 | try git.indexPack(gpa, object_format, &pack_file_reader, index_buffered_writer.writer()); |
| 1397 | try index_buffered_writer.flush(); | 1402 | try index_buffered_writer.flush(); |
| 1398 | } | 1403 | } |
| 1399 | 1404 | ||
| 1400 | { | 1405 | { |
| 1401 | const checkout_prog_node = f.prog_node.start("Checkout", 0); | 1406 | const checkout_prog_node = f.prog_node.start("Checkout", 0); |
| 1402 | defer checkout_prog_node.end(); | 1407 | defer checkout_prog_node.end(); |
| 1403 | var repository = try git.Repository.init(gpa, object_format, pack_file, index_file); | 1408 | var repository = try git.Repository.init(gpa, object_format, &pack_file_reader, index_file); |
| 1404 | defer repository.deinit(); | 1409 | defer repository.deinit(); |
| 1405 | var diagnostics: git.Diagnostics = .{ .allocator = arena }; | 1410 | var diagnostics: git.Diagnostics = .{ .allocator = arena }; |
| 1406 | try repository.checkout(out_dir, resource.want_oid, &diagnostics); | 1411 | try repository.checkout(out_dir, resource.want_oid, &diagnostics); |
src/Package/Fetch/git.zig+32-35| ... | @@ -73,7 +73,7 @@ pub const Oid = union(Format) { | ... | @@ -73,7 +73,7 @@ pub const Oid = union(Format) { |
| 73 | }; | 73 | }; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | pub fn readBytes(oid_format: Format, reader: anytype) @TypeOf(reader).NoEofError!Oid { | 76 | pub fn readBytes(oid_format: Format, reader: anytype) !Oid { |
| 77 | return switch (oid_format) { | 77 | return switch (oid_format) { |
| 78 | inline else => |tag| @unionInit(Oid, @tagName(tag), try reader.readBytesNoEof(tag.byteLength())), | 78 | inline else => |tag| @unionInit(Oid, @tagName(tag), try reader.readBytesNoEof(tag.byteLength())), |
| 79 | }; | 79 | }; |
| ... | @@ -166,7 +166,7 @@ pub const Diagnostics = struct { | ... | @@ -166,7 +166,7 @@ pub const Diagnostics = struct { |
| 166 | pub const Repository = struct { | 166 | pub const Repository = struct { |
| 167 | odb: Odb, | 167 | odb: Odb, |
| 168 | 168 | ||
| 169 | pub fn init(allocator: Allocator, format: Oid.Format, pack_file: std.fs.File, index_file: std.fs.File) !Repository { | 169 | pub fn init(allocator: Allocator, format: Oid.Format, pack_file: *std.fs.File.Reader, index_file: std.fs.File) !Repository { |
| 170 | return .{ .odb = try Odb.init(allocator, format, pack_file, index_file) }; | 170 | return .{ .odb = try Odb.init(allocator, format, pack_file, index_file) }; |
| 171 | } | 171 | } |
| 172 | 172 | ||
| ... | @@ -335,14 +335,14 @@ pub const Repository = struct { | ... | @@ -335,14 +335,14 @@ pub const Repository = struct { |
| 335 | /// [pack-format](https://git-scm.com/docs/pack-format). | 335 | /// [pack-format](https://git-scm.com/docs/pack-format). |
| 336 | const Odb = struct { | 336 | const Odb = struct { |
| 337 | format: Oid.Format, | 337 | format: Oid.Format, |
| 338 | pack_file: std.fs.File, | 338 | pack_file: *std.fs.File.Reader, |
| 339 | index_header: IndexHeader, | 339 | index_header: IndexHeader, |
| 340 | index_file: std.fs.File, | 340 | index_file: std.fs.File, |
| 341 | cache: ObjectCache = .{}, | 341 | cache: ObjectCache = .{}, |
| 342 | allocator: Allocator, | 342 | allocator: Allocator, |
| 343 | 343 | ||
| 344 | /// Initializes the database from open pack and index files. | 344 | /// Initializes the database from open pack and index files. |
| 345 | fn init(allocator: Allocator, format: Oid.Format, pack_file: std.fs.File, index_file: std.fs.File) !Odb { | 345 | fn init(allocator: Allocator, format: Oid.Format, pack_file: *std.fs.File.Reader, index_file: std.fs.File) !Odb { |
| 346 | try pack_file.seekTo(0); | 346 | try pack_file.seekTo(0); |
| 347 | try index_file.seekTo(0); | 347 | try index_file.seekTo(0); |
| 348 | const index_header = try IndexHeader.read(index_file.deprecatedReader()); | 348 | const index_header = try IndexHeader.read(index_file.deprecatedReader()); |
| ... | @@ -362,14 +362,14 @@ const Odb = struct { | ... | @@ -362,14 +362,14 @@ const Odb = struct { |
| 362 | 362 | ||
| 363 | /// Reads the object at the current position in the database. | 363 | /// Reads the object at the current position in the database. |
| 364 | fn readObject(odb: *Odb) !Object { | 364 | fn readObject(odb: *Odb) !Object { |
| 365 | var base_offset = try odb.pack_file.getPos(); | 365 | var base_offset = odb.pack_file.logicalPos(); |
| 366 | var base_header: EntryHeader = undefined; | 366 | var base_header: EntryHeader = undefined; |
| 367 | var delta_offsets: std.ArrayListUnmanaged(u64) = .empty; | 367 | var delta_offsets: std.ArrayListUnmanaged(u64) = .empty; |
| 368 | defer delta_offsets.deinit(odb.allocator); | 368 | defer delta_offsets.deinit(odb.allocator); |
| 369 | const base_object = while (true) { | 369 | const base_object = while (true) { |
| 370 | if (odb.cache.get(base_offset)) |base_object| break base_object; | 370 | if (odb.cache.get(base_offset)) |base_object| break base_object; |
| 371 | 371 | ||
| 372 | base_header = try EntryHeader.read(odb.format, odb.pack_file.deprecatedReader()); | 372 | base_header = try EntryHeader.read(odb.format, odb.pack_file.interface.adaptToOldInterface()); |
| 373 | switch (base_header) { | 373 | switch (base_header) { |
| 374 | .ofs_delta => |ofs_delta| { | 374 | .ofs_delta => |ofs_delta| { |
| 375 | try delta_offsets.append(odb.allocator, base_offset); | 375 | try delta_offsets.append(odb.allocator, base_offset); |
| ... | @@ -379,10 +379,10 @@ const Odb = struct { | ... | @@ -379,10 +379,10 @@ const Odb = struct { |
| 379 | .ref_delta => |ref_delta| { | 379 | .ref_delta => |ref_delta| { |
| 380 | try delta_offsets.append(odb.allocator, base_offset); | 380 | try delta_offsets.append(odb.allocator, base_offset); |
| 381 | try odb.seekOid(ref_delta.base_object); | 381 | try odb.seekOid(ref_delta.base_object); |
| 382 | base_offset = try odb.pack_file.getPos(); | 382 | base_offset = odb.pack_file.logicalPos(); |
| 383 | }, | 383 | }, |
| 384 | else => { | 384 | else => { |
| 385 | const base_data = try readObjectRaw(odb.allocator, odb.pack_file.deprecatedReader(), base_header.uncompressedLength()); | 385 | const base_data = try readObjectRaw(odb.allocator, &odb.pack_file.interface, base_header.uncompressedLength()); |
| 386 | errdefer odb.allocator.free(base_data); | 386 | errdefer odb.allocator.free(base_data); |
| 387 | const base_object: Object = .{ .type = base_header.objectType(), .data = base_data }; | 387 | const base_object: Object = .{ .type = base_header.objectType(), .data = base_data }; |
| 388 | try odb.cache.put(odb.allocator, base_offset, base_object); | 388 | try odb.cache.put(odb.allocator, base_offset, base_object); |
| ... | @@ -1227,7 +1227,7 @@ const IndexEntry = struct { | ... | @@ -1227,7 +1227,7 @@ const IndexEntry = struct { |
| 1227 | 1227 | ||
| 1228 | /// Writes out a version 2 index for the given packfile, as documented in | 1228 | /// Writes out a version 2 index for the given packfile, as documented in |
| 1229 | /// [pack-format](https://git-scm.com/docs/pack-format). | 1229 | /// [pack-format](https://git-scm.com/docs/pack-format). |
| 1230 | pub fn indexPack(allocator: Allocator, format: Oid.Format, pack: std.fs.File, index_writer: anytype) !void { | 1230 | pub fn indexPack(allocator: Allocator, format: Oid.Format, pack: *std.fs.File.Reader, index_writer: anytype) !void { |
| 1231 | try pack.seekTo(0); | 1231 | try pack.seekTo(0); |
| 1232 | 1232 | ||
| 1233 | var index_entries: std.AutoHashMapUnmanaged(Oid, IndexEntry) = .empty; | 1233 | var index_entries: std.AutoHashMapUnmanaged(Oid, IndexEntry) = .empty; |
| ... | @@ -1324,12 +1324,11 @@ pub fn indexPack(allocator: Allocator, format: Oid.Format, pack: std.fs.File, in | ... | @@ -1324,12 +1324,11 @@ pub fn indexPack(allocator: Allocator, format: Oid.Format, pack: std.fs.File, in |
| 1324 | fn indexPackFirstPass( | 1324 | fn indexPackFirstPass( |
| 1325 | allocator: Allocator, | 1325 | allocator: Allocator, |
| 1326 | format: Oid.Format, | 1326 | format: Oid.Format, |
| 1327 | pack: std.fs.File, | 1327 | pack: *std.fs.File.Reader, |
| 1328 | index_entries: *std.AutoHashMapUnmanaged(Oid, IndexEntry), | 1328 | index_entries: *std.AutoHashMapUnmanaged(Oid, IndexEntry), |
| 1329 | pending_deltas: *std.ArrayListUnmanaged(IndexEntry), | 1329 | pending_deltas: *std.ArrayListUnmanaged(IndexEntry), |
| 1330 | ) !Oid { | 1330 | ) !Oid { |
| 1331 | var pack_buffered_reader = std.io.bufferedReader(pack.deprecatedReader()); | 1331 | var pack_counting_reader = std.io.countingReader(pack.interface.adaptToOldInterface()); |
| 1332 | var pack_counting_reader = std.io.countingReader(pack_buffered_reader.reader()); | ||
| 1333 | var pack_hashed_reader = hashedReader(pack_counting_reader.reader(), Oid.Hasher.init(format)); | 1332 | var pack_hashed_reader = hashedReader(pack_counting_reader.reader(), Oid.Hasher.init(format)); |
| 1334 | const pack_reader = pack_hashed_reader.reader(); | 1333 | const pack_reader = pack_hashed_reader.reader(); |
| 1335 | 1334 | ||
| ... | @@ -1340,15 +1339,19 @@ fn indexPackFirstPass( | ... | @@ -1340,15 +1339,19 @@ fn indexPackFirstPass( |
| 1340 | const entry_offset = pack_counting_reader.bytes_read; | 1339 | const entry_offset = pack_counting_reader.bytes_read; |
| 1341 | var entry_crc32_reader = hashedReader(pack_reader, std.hash.Crc32.init()); | 1340 | var entry_crc32_reader = hashedReader(pack_reader, std.hash.Crc32.init()); |
| 1342 | const entry_header = try EntryHeader.read(format, entry_crc32_reader.reader()); | 1341 | const entry_header = try EntryHeader.read(format, entry_crc32_reader.reader()); |
| 1342 | var adapter_buffer: [1024]u8 = undefined; | ||
| 1343 | var adapter = entry_crc32_reader.reader().adaptToNewApi(&adapter_buffer); | ||
| 1344 | var flate_buffer: [std.compress.flate.max_window_len]u8 = undefined; | ||
| 1345 | var entry_decompress_stream: std.compress.flate.Decompress = .init(&adapter.new_interface, .zlib, &flate_buffer); | ||
| 1346 | const old = entry_decompress_stream.reader.adaptToOldInterface(); | ||
| 1347 | var entry_counting_reader = std.io.countingReader(old); | ||
| 1343 | switch (entry_header) { | 1348 | switch (entry_header) { |
| 1344 | .commit, .tree, .blob, .tag => |object| { | 1349 | .commit, .tree, .blob, .tag => |object| { |
| 1345 | var entry_decompress_stream = std.compress.zlib.decompressor(entry_crc32_reader.reader()); | ||
| 1346 | var entry_counting_reader = std.io.countingReader(entry_decompress_stream.reader()); | ||
| 1347 | var entry_hashed_writer = hashedWriter(std.io.null_writer, Oid.Hasher.init(format)); | 1350 | var entry_hashed_writer = hashedWriter(std.io.null_writer, Oid.Hasher.init(format)); |
| 1348 | const entry_writer = entry_hashed_writer.writer(); | 1351 | const entry_writer = entry_hashed_writer.writer(); |
| 1349 | // The object header is not included in the pack data but is | 1352 | // The object header is not included in the pack data but is |
| 1350 | // part of the object's ID | 1353 | // part of the object's ID |
| 1351 | try entry_writer.print("{s} {}\x00", .{ @tagName(entry_header), object.uncompressed_length }); | 1354 | try entry_writer.print("{s} {d}\x00", .{ @tagName(entry_header), object.uncompressed_length }); |
| 1352 | var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init(); | 1355 | var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init(); |
| 1353 | try fifo.pump(entry_counting_reader.reader(), entry_writer); | 1356 | try fifo.pump(entry_counting_reader.reader(), entry_writer); |
| 1354 | if (entry_counting_reader.bytes_read != object.uncompressed_length) { | 1357 | if (entry_counting_reader.bytes_read != object.uncompressed_length) { |
| ... | @@ -1361,8 +1364,6 @@ fn indexPackFirstPass( | ... | @@ -1361,8 +1364,6 @@ fn indexPackFirstPass( |
| 1361 | }); | 1364 | }); |
| 1362 | }, | 1365 | }, |
| 1363 | inline .ofs_delta, .ref_delta => |delta| { | 1366 | inline .ofs_delta, .ref_delta => |delta| { |
| 1364 | var entry_decompress_stream = std.compress.zlib.decompressor(entry_crc32_reader.reader()); | ||
| 1365 | var entry_counting_reader = std.io.countingReader(entry_decompress_stream.reader()); | ||
| 1366 | var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init(); | 1367 | var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init(); |
| 1367 | try fifo.pump(entry_counting_reader.reader(), std.io.null_writer); | 1368 | try fifo.pump(entry_counting_reader.reader(), std.io.null_writer); |
| 1368 | if (entry_counting_reader.bytes_read != delta.uncompressed_length) { | 1369 | if (entry_counting_reader.bytes_read != delta.uncompressed_length) { |
| ... | @@ -1377,7 +1378,7 @@ fn indexPackFirstPass( | ... | @@ -1377,7 +1378,7 @@ fn indexPackFirstPass( |
| 1377 | } | 1378 | } |
| 1378 | 1379 | ||
| 1379 | const pack_checksum = pack_hashed_reader.hasher.finalResult(); | 1380 | const pack_checksum = pack_hashed_reader.hasher.finalResult(); |
| 1380 | const recorded_checksum = try Oid.readBytes(format, pack_buffered_reader.reader()); | 1381 | const recorded_checksum = try Oid.readBytes(format, pack.interface.adaptToOldInterface()); |
| 1381 | if (!mem.eql(u8, pack_checksum.slice(), recorded_checksum.slice())) { | 1382 | if (!mem.eql(u8, pack_checksum.slice(), recorded_checksum.slice())) { |
| 1382 | return error.CorruptedPack; | 1383 | return error.CorruptedPack; |
| 1383 | } | 1384 | } |
| ... | @@ -1394,7 +1395,7 @@ fn indexPackFirstPass( | ... | @@ -1394,7 +1395,7 @@ fn indexPackFirstPass( |
| 1394 | fn indexPackHashDelta( | 1395 | fn indexPackHashDelta( |
| 1395 | allocator: Allocator, | 1396 | allocator: Allocator, |
| 1396 | format: Oid.Format, | 1397 | format: Oid.Format, |
| 1397 | pack: std.fs.File, | 1398 | pack: *std.fs.File.Reader, |
| 1398 | delta: IndexEntry, | 1399 | delta: IndexEntry, |
| 1399 | index_entries: std.AutoHashMapUnmanaged(Oid, IndexEntry), | 1400 | index_entries: std.AutoHashMapUnmanaged(Oid, IndexEntry), |
| 1400 | cache: *ObjectCache, | 1401 | cache: *ObjectCache, |
| ... | @@ -1408,7 +1409,7 @@ fn indexPackHashDelta( | ... | @@ -1408,7 +1409,7 @@ fn indexPackHashDelta( |
| 1408 | if (cache.get(base_offset)) |base_object| break base_object; | 1409 | if (cache.get(base_offset)) |base_object| break base_object; |
| 1409 | 1410 | ||
| 1410 | try pack.seekTo(base_offset); | 1411 | try pack.seekTo(base_offset); |
| 1411 | base_header = try EntryHeader.read(format, pack.deprecatedReader()); | 1412 | base_header = try EntryHeader.read(format, pack.interface.adaptToOldInterface()); |
| 1412 | switch (base_header) { | 1413 | switch (base_header) { |
| 1413 | .ofs_delta => |ofs_delta| { | 1414 | .ofs_delta => |ofs_delta| { |
| 1414 | try delta_offsets.append(allocator, base_offset); | 1415 | try delta_offsets.append(allocator, base_offset); |
| ... | @@ -1419,7 +1420,7 @@ fn indexPackHashDelta( | ... | @@ -1419,7 +1420,7 @@ fn indexPackHashDelta( |
| 1419 | base_offset = (index_entries.get(ref_delta.base_object) orelse return null).offset; | 1420 | base_offset = (index_entries.get(ref_delta.base_object) orelse return null).offset; |
| 1420 | }, | 1421 | }, |
| 1421 | else => { | 1422 | else => { |
| 1422 | const base_data = try readObjectRaw(allocator, pack.deprecatedReader(), base_header.uncompressedLength()); | 1423 | const base_data = try readObjectRaw(allocator, &pack.interface, base_header.uncompressedLength()); |
| 1423 | errdefer allocator.free(base_data); | 1424 | errdefer allocator.free(base_data); |
| 1424 | const base_object: Object = .{ .type = base_header.objectType(), .data = base_data }; | 1425 | const base_object: Object = .{ .type = base_header.objectType(), .data = base_data }; |
| 1425 | try cache.put(allocator, base_offset, base_object); | 1426 | try cache.put(allocator, base_offset, base_object); |
| ... | @@ -1444,7 +1445,7 @@ fn indexPackHashDelta( | ... | @@ -1444,7 +1445,7 @@ fn indexPackHashDelta( |
| 1444 | fn resolveDeltaChain( | 1445 | fn resolveDeltaChain( |
| 1445 | allocator: Allocator, | 1446 | allocator: Allocator, |
| 1446 | format: Oid.Format, | 1447 | format: Oid.Format, |
| 1447 | pack: std.fs.File, | 1448 | pack: *std.fs.File.Reader, |
| 1448 | base_object: Object, | 1449 | base_object: Object, |
| 1449 | delta_offsets: []const u64, | 1450 | delta_offsets: []const u64, |
| 1450 | cache: *ObjectCache, | 1451 | cache: *ObjectCache, |
| ... | @@ -1456,8 +1457,8 @@ fn resolveDeltaChain( | ... | @@ -1456,8 +1457,8 @@ fn resolveDeltaChain( |
| 1456 | 1457 | ||
| 1457 | const delta_offset = delta_offsets[i]; | 1458 | const delta_offset = delta_offsets[i]; |
| 1458 | try pack.seekTo(delta_offset); | 1459 | try pack.seekTo(delta_offset); |
| 1459 | const delta_header = try EntryHeader.read(format, pack.deprecatedReader()); | 1460 | const delta_header = try EntryHeader.read(format, pack.interface.adaptToOldInterface()); |
| 1460 | const delta_data = try readObjectRaw(allocator, pack.deprecatedReader(), delta_header.uncompressedLength()); | 1461 | const delta_data = try readObjectRaw(allocator, &pack.interface, delta_header.uncompressedLength()); |
| 1461 | defer allocator.free(delta_data); | 1462 | defer allocator.free(delta_data); |
| 1462 | var delta_stream = std.io.fixedBufferStream(delta_data); | 1463 | var delta_stream = std.io.fixedBufferStream(delta_data); |
| 1463 | const delta_reader = delta_stream.reader(); | 1464 | const delta_reader = delta_stream.reader(); |
| ... | @@ -1481,18 +1482,14 @@ fn resolveDeltaChain( | ... | @@ -1481,18 +1482,14 @@ fn resolveDeltaChain( |
| 1481 | /// Reads the complete contents of an object from `reader`. This function may | 1482 | /// Reads the complete contents of an object from `reader`. This function may |
| 1482 | /// read more bytes than required from `reader`, so the reader position after | 1483 | /// read more bytes than required from `reader`, so the reader position after |
| 1483 | /// returning is not reliable. | 1484 | /// returning is not reliable. |
| 1484 | fn readObjectRaw(allocator: Allocator, reader: anytype, size: u64) ![]u8 { | 1485 | fn readObjectRaw(allocator: Allocator, reader: *std.Io.Reader, size: u64) ![]u8 { |
| 1485 | const alloc_size = std.math.cast(usize, size) orelse return error.ObjectTooLarge; | 1486 | const alloc_size = std.math.cast(usize, size) orelse return error.ObjectTooLarge; |
| 1486 | var buffered_reader = std.io.bufferedReader(reader); | 1487 | var aw: std.Io.Writer.Allocating = .init(allocator); |
| 1487 | var decompress_stream = std.compress.zlib.decompressor(buffered_reader.reader()); | 1488 | try aw.ensureTotalCapacity(alloc_size); |
| 1488 | const data = try allocator.alloc(u8, alloc_size); | 1489 | defer aw.deinit(); |
| 1489 | errdefer allocator.free(data); | 1490 | var decompress: std.compress.flate.Decompress = .init(reader, .zlib, &.{}); |
| 1490 | try decompress_stream.reader().readNoEof(data); | 1491 | try decompress.reader.streamExact(&aw.writer, alloc_size); |
| 1491 | _ = decompress_stream.reader().readByte() catch |e| switch (e) { | 1492 | return aw.toOwnedSlice(); |
| 1492 | error.EndOfStream => return data, | ||
| 1493 | else => |other| return other, | ||
| 1494 | }; | ||
| 1495 | return error.InvalidFormat; | ||
| 1496 | } | 1493 | } |
| 1497 | 1494 | ||
| 1498 | /// Expands delta data from `delta_reader` to `writer`. `base_object` must | 1495 | /// Expands delta data from `delta_reader` to `writer`. `base_object` must |
src/link/Elf/Object.zig+7-8| ... | @@ -1198,15 +1198,14 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index | ... | @@ -1198,15 +1198,14 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index |
| 1198 | const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*; | 1198 | const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*; |
| 1199 | switch (chdr.ch_type) { | 1199 | switch (chdr.ch_type) { |
| 1200 | .ZLIB => { | 1200 | .ZLIB => { |
| 1201 | var stream = std.io.fixedBufferStream(data[@sizeOf(elf.Elf64_Chdr)..]); | 1201 | var stream: std.Io.Reader = .fixed(data[@sizeOf(elf.Elf64_Chdr)..]); |
| 1202 | var zlib_stream = std.compress.zlib.decompressor(stream.reader()); | 1202 | var zlib_stream: std.compress.flate.Decompress = .init(&stream, .zlib, &.{}); |
| 1203 | const size = std.math.cast(usize, chdr.ch_size) orelse return error.Overflow; | 1203 | const size = std.math.cast(usize, chdr.ch_size) orelse return error.Overflow; |
| 1204 | const decomp = try gpa.alloc(u8, size); | 1204 | var aw: std.Io.Writer.Allocating = .init(gpa); |
| 1205 | const nread = zlib_stream.reader().readAll(decomp) catch return error.InputOutput; | 1205 | try aw.ensureUnusedCapacity(size); |
| 1206 | if (nread != decomp.len) { | 1206 | defer aw.deinit(); |
| 1207 | return error.InputOutput; | 1207 | _ = try zlib_stream.reader.streamRemaining(&aw.writer); |
| 1208 | } | 1208 | return aw.toOwnedSlice(); |
| 1209 | return decomp; | ||
| 1210 | }, | 1209 | }, |
| 1211 | else => @panic("TODO unhandled compression scheme"), | 1210 | else => @panic("TODO unhandled compression scheme"), |
| 1212 | } | 1211 | } |