aboutsummaryrefslogtreecommitdiff
path: root/lib/std/compress/lzma.zig
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/compress/lzma.zig')
-rw-r--r--lib/std/compress/lzma.zig90
1 files changed, 90 insertions, 0 deletions
diff --git a/lib/std/compress/lzma.zig b/lib/std/compress/lzma.zig
new file mode 100644
index 0000000000..8bb8c19da1
--- /dev/null
+++ b/lib/std/compress/lzma.zig
@@ -0,0 +1,90 @@
+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 = math.min(input.len, output.len);
+ mem.copy(u8, output[0..n], input[0..n]);
+ mem.copy(u8, input, input[n..]);
+ self.to_read.shrinkRetainingCapacity(input.len - n);
+ return n;
+ }
+ };
+}
+
+test {
+ _ = @import("lzma/test.zig");
+ _ = @import("lzma/vec2d.zig");
+}