const std = @import("../std.zig"); const math = std.math; const mem = std.mem; const Allocator = std.mem.Allocator; pub const decode = @import("lzma/decode.zig"); pub fn decompress( allocator: Allocator, reader: anytype, ) !Decompress(@TypeOf(reader)) { return decompressWithOptions(allocator, reader, .{}); } pub fn decompressWithOptions( allocator: Allocator, reader: anytype, options: decode.Options, ) !Decompress(@TypeOf(reader)) { const params = try decode.Params.readHeader(reader, options); return Decompress(@TypeOf(reader)).init(allocator, reader, params, options.memlimit); } pub fn Decompress(comptime ReaderType: type) type { return struct { const Self = @This(); pub const Error = ReaderType.Error || Allocator.Error || error{ CorruptInput, EndOfStream, Overflow }; pub const Reader = std.io.Reader(*Self, Error, read); allocator: Allocator, in_reader: ReaderType, to_read: std.ArrayListUnmanaged(u8), buffer: decode.lzbuffer.LzCircularBuffer, decoder: decode.rangecoder.RangeDecoder, state: decode.DecoderState, pub fn init(allocator: Allocator, source: ReaderType, params: decode.Params, memlimit: ?usize) !Self { return Self{ .allocator = allocator, .in_reader = source, .to_read = .{}, .buffer = decode.lzbuffer.LzCircularBuffer.init(params.dict_size, memlimit orelse math.maxInt(usize)), .decoder = try decode.rangecoder.RangeDecoder.init(source), .state = try decode.DecoderState.init(allocator, params.properties, params.unpacked_size), }; } pub fn reader(self: *Self) Reader { return .{ .context = self }; } pub fn deinit(self: *Self) void { self.to_read.deinit(self.allocator); self.buffer.deinit(self.allocator); self.state.deinit(self.allocator); self.* = undefined; } pub fn read(self: *Self, output: []u8) Error!usize { const writer = self.to_read.writer(self.allocator); while (self.to_read.items.len < output.len) { switch (try self.state.process(self.allocator, self.in_reader, writer, &self.buffer, &self.decoder)) { .continue_ => {}, .finished => { try self.buffer.finish(writer); break; }, } } const input = self.to_read.items; const n = @min(input.len, output.len); @memcpy(output[0..n], input[0..n]); @memcpy(input[0 .. input.len - n], input[n..]); self.to_read.shrinkRetainingCapacity(input.len - n); return n; } }; } test { _ = @import("lzma/test.zig"); _ = @import("lzma/vec2d.zig"); }