Working on re-doing decompression
This commit is contained in:
+2
-6
@@ -2,10 +2,7 @@ const std = @import("std");
|
||||
const Reader = std.Io.Reader;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const config = if (builtin.is_test) .{
|
||||
.use_zig_decomp = !builtin.link_libc,
|
||||
.allow_lzo = false, // Change once LZO compilation is fixed
|
||||
} else @import("config");
|
||||
const config = @import("config");
|
||||
|
||||
pub const c = @cImport({
|
||||
@cInclude("zlib-ng.h");
|
||||
@@ -13,6 +10,5 @@ pub const c = @cImport({
|
||||
@cInclude("lz4.h");
|
||||
@cInclude("zstd.h");
|
||||
@cInclude("zstd_errors.h");
|
||||
if (config.allow_lzo)
|
||||
@cInclude("lzo/minilzo.h");
|
||||
@cInclude("lzo/minilzo.h");
|
||||
});
|
||||
|
||||
+2
-17
@@ -15,14 +15,12 @@ const ZlibErrors = error{
|
||||
const Self = @This();
|
||||
|
||||
alloc: std.mem.Allocator,
|
||||
window_size: i16,
|
||||
|
||||
streams: std.AutoHashMap(std.Thread.Id, zng_stream),
|
||||
|
||||
pub fn init(alloc: std.mem.Allocator, window_size: i16) !Self {
|
||||
pub fn init(alloc: std.mem.Allocator) !Self {
|
||||
return .{
|
||||
.alloc = alloc,
|
||||
.window_size = window_size,
|
||||
.streams = .init(alloc),
|
||||
};
|
||||
}
|
||||
@@ -40,7 +38,7 @@ pub fn decompress(self: *Self, in: []u8, out: []u8) ZlibErrors!usize {
|
||||
stream.avail_in = in.len;
|
||||
stream.next_out = out.ptr;
|
||||
stream.avail_out = out.len;
|
||||
var res = c.zng_inflateReset2(stream, self.window_size);
|
||||
var res = c.zng_inflateReset(stream);
|
||||
switch (res) {
|
||||
c.Z_OK => {},
|
||||
c.Z_STREAM_ERROR => return ZlibErrors.StreamError,
|
||||
@@ -74,16 +72,3 @@ fn zfree(self_ptr: ?*anyopaque, alloc_ptr: ?*anyopaque) ?*anyopaque {
|
||||
var self: *Self = @ptrCast(self_ptr);
|
||||
self.alloc.rawFree(@ptrCast(alloc_ptr), .@"1", 0);
|
||||
}
|
||||
|
||||
pub fn stateless(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
|
||||
_ = alloc;
|
||||
var out_len: usize = out.len;
|
||||
const res = c.zng_uncompress(out.ptr, &out_len, in.ptr, in.len);
|
||||
return switch (res) {
|
||||
c.Z_OK => out_len,
|
||||
c.Z_MEM_ERROR => ZlibErrors.NotEnoughMemory,
|
||||
c.Z_BUF_ERROR => ZlibErrors.OutputBufferTooSmall,
|
||||
c.Z_DATA_ERROR => ZlibErrors.BadData,
|
||||
else => ZlibErrors.Unknown,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const c = @import("c.zig").c;
|
||||
const stream = c.lzma_stream;
|
||||
|
||||
const Self = @This();
|
||||
|
||||
alloc: std.mem.Allocator,
|
||||
streams: std.AutoHashMap(std.Thread.Id, stream),
|
||||
|
||||
xz: bool,
|
||||
|
||||
pub fn init(alloc: std.mem.Allocator, xz: bool) !Self {
|
||||
return .{
|
||||
.alloc = alloc,
|
||||
.streams = .init(alloc),
|
||||
.xz = xz,
|
||||
};
|
||||
}
|
||||
pub fn deinit(self: Self) void {
|
||||
var iter = self.streams.keyIterator();
|
||||
while (iter.next()) |key|
|
||||
c.lzma_end(self.streams.getPtr(key));
|
||||
self.streams.deinit();
|
||||
}
|
||||
|
||||
pub fn decompress(self: *Self, in: []u8, out: []u8) LzmaError!usize {
|
||||
var strm = try self.getOrCreate();
|
||||
strm.next_in = in.ptr;
|
||||
strm.avail_in = in.len;
|
||||
strm.next_out = out.ptr;
|
||||
strm.avail_out = out.len;
|
||||
|
||||
var res = if (self.xz)
|
||||
c.lzma_stream_decoder(strm, in.len * 2, 0)
|
||||
else
|
||||
c.lzma_alone_decoder(strm, in.len * 2);
|
||||
switch (res) {
|
||||
c.LZMA_OK => {},
|
||||
c.LZMA_MEM_ERROR => return LzmaError.LzmaMemoryError,
|
||||
c.LZMA_PROG_ERROR => return LzmaError.LzmaProgramError,
|
||||
else => return LzmaError.UnknownResult,
|
||||
}
|
||||
while (res == c.LZMA_OK)
|
||||
res = c.lzma_code(strm, c.LZMA_RUN);
|
||||
return switch (res) {
|
||||
c.LZMA_STREAM_END => strm.total_out,
|
||||
c.LZMA_MEM_ERROR => LzmaError.LzmaMemoryError,
|
||||
c.LZMA_MEMLIMIT_ERROR => LzmaError.LzmaMemoryLimit,
|
||||
c.LZMA_FORMAT_ERROR => LzmaError.LzmaBadFormat,
|
||||
c.LZMA_DATA_ERROR => LzmaError.LzmaDataCorrupt,
|
||||
c.LZMA_BUF_ERROR => LzmaError.LzmaCannotProgress,
|
||||
c.LZMA_PROG_ERROR => LzmaError.LzmaProgramError,
|
||||
else => LzmaError.UnknownResult,
|
||||
};
|
||||
}
|
||||
|
||||
inline fn getOrCreate(self: *Self) LzmaError!*stream {
|
||||
const res = try self.streams.getOrPut(std.Thread.getCurrentId());
|
||||
if (res.found_existing) return res.value_ptr;
|
||||
|
||||
// Ideally, the zero value should be LZMA_STREAM_INIT, but translate-c can't handle it properly.
|
||||
// According to lzma, setting it to entirely zero values *should* work.
|
||||
// res.value_ptr.* = c.LZMA_STREAM_INIT;
|
||||
res.value_ptr.* = std.mem.zeroInit(stream, .{});
|
||||
return res.value_ptr;
|
||||
}
|
||||
|
||||
pub const LzmaError = error{
|
||||
OutOfMemory,
|
||||
LzmaMemoryError,
|
||||
LzmaMemoryLimit,
|
||||
LzmaBadFormat,
|
||||
LzmaDataCorrupt,
|
||||
LzmaCannotProgress,
|
||||
LzmaProgramError,
|
||||
Unknown,
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
const c = @import("c.zig").c;
|
||||
|
||||
pub fn lzo(in: []u8, out: []u8) anyerror!usize {
|
||||
var res = c.lzo_init();
|
||||
if (res != 0) return error.LzoInitFailed;
|
||||
var out_len: usize = out.len;
|
||||
res = c.lzo1x_decompress(in.ptr, in.len, out.ptr, &out_len, null);
|
||||
|
||||
return switch (res) {
|
||||
c.LZO_E_OK => out_len,
|
||||
c.LZO_E_ERROR => error.LzoError,
|
||||
c.LZO_E_OUT_OF_MEMORY => error.LzoOutOfMemory,
|
||||
c.LZO_E_NOT_COMPRESSIBLE => error.LzoNotCompressible,
|
||||
c.LZO_E_INPUT_OVERRUN => error.LzoInputOverrun,
|
||||
c.LZO_E_OUTPUT_OVERRUN => error.LzoOutputOverrun,
|
||||
c.LZO_E_LOOKBEHIND_OVERRUN => error.LzoLookbehindOverrun,
|
||||
c.LZO_E_EOF_NOT_FOUND => error.LzoEofNotFound,
|
||||
c.LZO_E_INPUT_NOT_CONSUMED => error.LzoInputNotConsumed,
|
||||
c.LZO_E_NOT_YET_IMPLEMENTED => error.LzoNotYetImplemented,
|
||||
c.LZO_E_INVALID_ARGUMENT => error.LzoInvalidArgument,
|
||||
c.LZO_E_INVALID_ALIGNMENT => error.LzoInvalidAlignment,
|
||||
c.LZO_E_OUTPUT_NOT_CONSUMED => error.LzoOutputNotConsumed,
|
||||
c.LZO_E_INTERNAL_ERROR => error.LzoInternalError,
|
||||
else => error.UnknownResult,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn lz4(in: []u8, out: []u8) anyerror!usize {
|
||||
const res = c.LZ4_decompress_safe(in.ptr, out.ptr, @intCast(in.len), @intCast(out.len));
|
||||
if (res > 0) return @abs(res); // TODO: Find out what error values it can return.
|
||||
return error.Lz4DecompressFailed;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
const std = @import("std");
|
||||
const Reader = std.Io.Reader;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub const DecompFn = *const fn (alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize; // TODO: replace anyerror to definitive error types.
|
||||
|
||||
pub fn gzip(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
|
||||
var rdr: Reader = .fixed(in);
|
||||
const buf = try alloc.alloc(u8, out.len);
|
||||
defer alloc.free(buf);
|
||||
var decomp = std.compress.flate.Decompress.init(&rdr, .zlib, buf);
|
||||
return decomp.reader.readSliceShort(out);
|
||||
}
|
||||
|
||||
pub fn lzma(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
|
||||
var rdr: Reader = .fixed(in);
|
||||
var decomp = try std.compress.lzma.decompress(alloc, rdr.adaptToOldInterface());
|
||||
return decomp.read(out);
|
||||
}
|
||||
|
||||
pub fn xz(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
|
||||
var rdr: Reader = .fixed(in);
|
||||
var decomp = try std.compress.xz.decompress(alloc, rdr.adaptToOldInterface());
|
||||
return decomp.read(out);
|
||||
}
|
||||
|
||||
pub fn zstd(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
|
||||
var rdr: Reader = .fixed(in);
|
||||
const buf = try alloc.alloc(u8, 1024 * 1024);
|
||||
defer alloc.free(buf);
|
||||
var decomp = std.compress.zstd.Decompress.init(&rdr, buf, .{});
|
||||
return decomp.reader.readSliceShort(out) catch |err| {
|
||||
return decomp.err orelse err;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user