Commit e03d6c42ea

fn ⌃ ⌥ <70830482+FnControlOption@users.noreply.github.com>
2023-02-05 15:52:28
Delete redundant `lzma`/`lzma2` prefix in function/struct names
1 parent d57813e
lib/std/compress/lzma/decode/lzma.zig
@@ -1,398 +0,0 @@
-const std = @import("../../../std.zig");
-const assert = std.debug.assert;
-const math = std.math;
-const Allocator = std.mem.Allocator;
-const ArrayListUnmanaged = std.ArrayListUnmanaged;
-const FixedBufferStream = std.io.FixedBufferStream;
-
-const LzCircularBuffer = @import("lzbuffer.zig").LzCircularBuffer;
-const Options = @import("../decode.zig").Options;
-const Vec2D = @import("../vec2d.zig").Vec2D;
-const rangecoder = @import("rangecoder.zig");
-const BitTree = rangecoder.BitTree;
-const LenDecoder = rangecoder.LenDecoder;
-const RangeDecoder = rangecoder.RangeDecoder;
-
-const ProcessingStatus = enum {
-    continue_,
-    finished,
-};
-
-pub const LzmaProperties = struct {
-    lc: u4,
-    lp: u3,
-    pb: u3,
-
-    fn validate(self: LzmaProperties) void {
-        assert(self.lc <= 8);
-        assert(self.lp <= 4);
-        assert(self.pb <= 4);
-    }
-};
-
-pub const LzmaParams = struct {
-    properties: LzmaProperties,
-    dict_size: u32,
-    unpacked_size: ?u64,
-
-    pub fn readHeader(reader: anytype, options: Options) !LzmaParams {
-        var props = try reader.readByte();
-        if (props >= 225) {
-            return error.CorruptInput;
-        }
-
-        const lc = @intCast(u4, props % 9);
-        props /= 9;
-        const lp = @intCast(u3, props % 5);
-        props /= 5;
-        const pb = @intCast(u3, props);
-
-        const dict_size_provided = try reader.readIntLittle(u32);
-        const dict_size = math.max(0x1000, dict_size_provided);
-
-        const unpacked_size = switch (options.unpacked_size) {
-            .read_from_header => blk: {
-                const unpacked_size_provided = try reader.readIntLittle(u64);
-                const marker_mandatory = unpacked_size_provided == 0xFFFF_FFFF_FFFF_FFFF;
-                break :blk if (marker_mandatory)
-                    null
-                else
-                    unpacked_size_provided;
-            },
-            .read_header_but_use_provided => |x| blk: {
-                _ = try reader.readIntLittle(u64);
-                break :blk x;
-            },
-            .use_provided => |x| x,
-        };
-
-        return LzmaParams{
-            .properties = LzmaProperties{ .lc = lc, .lp = lp, .pb = pb },
-            .dict_size = dict_size,
-            .unpacked_size = unpacked_size,
-        };
-    }
-};
-
-pub const DecoderState = struct {
-    lzma_props: LzmaProperties,
-    unpacked_size: ?u64,
-    literal_probs: Vec2D(u16),
-    pos_slot_decoder: [4]BitTree(6),
-    align_decoder: BitTree(4),
-    pos_decoders: [115]u16,
-    is_match: [192]u16,
-    is_rep: [12]u16,
-    is_rep_g0: [12]u16,
-    is_rep_g1: [12]u16,
-    is_rep_g2: [12]u16,
-    is_rep_0long: [192]u16,
-    state: usize,
-    rep: [4]usize,
-    len_decoder: LenDecoder,
-    rep_len_decoder: LenDecoder,
-
-    pub fn init(
-        allocator: Allocator,
-        lzma_props: LzmaProperties,
-        unpacked_size: ?u64,
-    ) !DecoderState {
-        return .{
-            .lzma_props = lzma_props,
-            .unpacked_size = unpacked_size,
-            .literal_probs = try Vec2D(u16).init(allocator, 0x400, .{ @as(usize, 1) << (lzma_props.lc + lzma_props.lp), 0x300 }),
-            .pos_slot_decoder = .{.{}} ** 4,
-            .align_decoder = .{},
-            .pos_decoders = .{0x400} ** 115,
-            .is_match = .{0x400} ** 192,
-            .is_rep = .{0x400} ** 12,
-            .is_rep_g0 = .{0x400} ** 12,
-            .is_rep_g1 = .{0x400} ** 12,
-            .is_rep_g2 = .{0x400} ** 12,
-            .is_rep_0long = .{0x400} ** 192,
-            .state = 0,
-            .rep = .{0} ** 4,
-            .len_decoder = .{},
-            .rep_len_decoder = .{},
-        };
-    }
-
-    pub fn deinit(self: *DecoderState, allocator: Allocator) void {
-        self.literal_probs.deinit(allocator);
-        self.* = undefined;
-    }
-
-    pub fn resetState(self: *DecoderState, allocator: Allocator, new_props: LzmaProperties) !void {
-        new_props.validate();
-        if (self.lzma_props.lc + self.lzma_props.lp == new_props.lc + new_props.lp) {
-            self.literal_probs.fill(0x400);
-        } else {
-            self.literal_probs.deinit(allocator);
-            self.literal_probs = try Vec2D(u16).init(allocator, 0x400, .{ @as(usize, 1) << (new_props.lc + new_props.lp), 0x300 });
-        }
-
-        self.lzma_props = new_props;
-        for (self.pos_slot_decoder) |*t| t.reset();
-        self.align_decoder.reset();
-        self.pos_decoders = .{0x400} ** 115;
-        self.is_match = .{0x400} ** 192;
-        self.is_rep = .{0x400} ** 12;
-        self.is_rep_g0 = .{0x400} ** 12;
-        self.is_rep_g1 = .{0x400} ** 12;
-        self.is_rep_g2 = .{0x400} ** 12;
-        self.is_rep_0long = .{0x400} ** 192;
-        self.state = 0;
-        self.rep = .{0} ** 4;
-        self.len_decoder.reset();
-        self.rep_len_decoder.reset();
-    }
-
-    fn processNextInner(
-        self: *DecoderState,
-        allocator: Allocator,
-        reader: anytype,
-        writer: anytype,
-        buffer: anytype,
-        decoder: *RangeDecoder,
-        update: bool,
-    ) !ProcessingStatus {
-        const pos_state = buffer.len & ((@as(usize, 1) << self.lzma_props.pb) - 1);
-
-        if (!try decoder.decodeBit(
-            reader,
-            &self.is_match[(self.state << 4) + pos_state],
-            update,
-        )) {
-            const byte: u8 = try self.decodeLiteral(reader, buffer, decoder, update);
-
-            if (update) {
-                try buffer.appendLiteral(allocator, byte, writer);
-
-                self.state = if (self.state < 4)
-                    0
-                else if (self.state < 10)
-                    self.state - 3
-                else
-                    self.state - 6;
-            }
-            return .continue_;
-        }
-
-        var len: usize = undefined;
-        if (try decoder.decodeBit(reader, &self.is_rep[self.state], update)) {
-            if (!try decoder.decodeBit(reader, &self.is_rep_g0[self.state], update)) {
-                if (!try decoder.decodeBit(
-                    reader,
-                    &self.is_rep_0long[(self.state << 4) + pos_state],
-                    update,
-                )) {
-                    if (update) {
-                        self.state = if (self.state < 7) 9 else 11;
-                        const dist = self.rep[0] + 1;
-                        try buffer.appendLz(allocator, 1, dist, writer);
-                    }
-                    return .continue_;
-                }
-            } else {
-                const idx: usize = if (!try decoder.decodeBit(reader, &self.is_rep_g1[self.state], update))
-                    1
-                else if (!try decoder.decodeBit(reader, &self.is_rep_g2[self.state], update))
-                    2
-                else
-                    3;
-                if (update) {
-                    const dist = self.rep[idx];
-                    var i = idx;
-                    while (i > 0) : (i -= 1) {
-                        self.rep[i] = self.rep[i - 1];
-                    }
-                    self.rep[0] = dist;
-                }
-            }
-
-            len = try self.rep_len_decoder.decode(reader, decoder, pos_state, update);
-
-            if (update) {
-                self.state = if (self.state < 7) 8 else 11;
-            }
-        } else {
-            if (update) {
-                self.rep[3] = self.rep[2];
-                self.rep[2] = self.rep[1];
-                self.rep[1] = self.rep[0];
-            }
-
-            len = try self.len_decoder.decode(reader, decoder, pos_state, update);
-
-            if (update) {
-                self.state = if (self.state < 7) 7 else 10;
-            }
-
-            const rep_0 = try self.decodeDistance(reader, decoder, len, update);
-
-            if (update) {
-                self.rep[0] = rep_0;
-                if (self.rep[0] == 0xFFFF_FFFF) {
-                    if (decoder.isFinished()) {
-                        return .finished;
-                    }
-                    return error.CorruptInput;
-                }
-            }
-        }
-
-        if (update) {
-            len += 2;
-
-            const dist = self.rep[0] + 1;
-            try buffer.appendLz(allocator, len, dist, writer);
-        }
-
-        return .continue_;
-    }
-
-    fn processNext(
-        self: *DecoderState,
-        allocator: Allocator,
-        reader: anytype,
-        writer: anytype,
-        buffer: anytype,
-        decoder: *RangeDecoder,
-    ) !ProcessingStatus {
-        return self.processNextInner(allocator, reader, writer, buffer, decoder, true);
-    }
-
-    pub fn process(
-        self: *DecoderState,
-        allocator: Allocator,
-        reader: anytype,
-        writer: anytype,
-        buffer: anytype,
-        decoder: *RangeDecoder,
-    ) !void {
-        while (true) {
-            if (self.unpacked_size) |unpacked_size| {
-                if (buffer.len >= unpacked_size) {
-                    break;
-                }
-            } else if (decoder.isFinished()) {
-                break;
-            }
-
-            if (try self.processNext(allocator, reader, writer, buffer, decoder) == .finished) {
-                break;
-            }
-        }
-
-        if (self.unpacked_size) |len| {
-            if (len != buffer.len) {
-                return error.CorruptInput;
-            }
-        }
-    }
-
-    fn decodeLiteral(
-        self: *DecoderState,
-        reader: anytype,
-        buffer: anytype,
-        decoder: *RangeDecoder,
-        update: bool,
-    ) !u8 {
-        const def_prev_byte = 0;
-        const prev_byte = @as(usize, buffer.lastOr(def_prev_byte));
-
-        var result: usize = 1;
-        const lit_state = ((buffer.len & ((@as(usize, 1) << self.lzma_props.lp) - 1)) << self.lzma_props.lc) +
-            (prev_byte >> (8 - self.lzma_props.lc));
-        const probs = try self.literal_probs.getMut(lit_state);
-
-        if (self.state >= 7) {
-            var match_byte = @as(usize, try buffer.lastN(self.rep[0] + 1));
-
-            while (result < 0x100) {
-                const match_bit = (match_byte >> 7) & 1;
-                match_byte <<= 1;
-                const bit = @boolToInt(try decoder.decodeBit(
-                    reader,
-                    &probs[((@as(usize, 1) + match_bit) << 8) + result],
-                    update,
-                ));
-                result = (result << 1) ^ bit;
-                if (match_bit != bit) {
-                    break;
-                }
-            }
-        }
-
-        while (result < 0x100) {
-            result = (result << 1) ^ @boolToInt(try decoder.decodeBit(reader, &probs[result], update));
-        }
-
-        return @truncate(u8, result - 0x100);
-    }
-
-    fn decodeDistance(
-        self: *DecoderState,
-        reader: anytype,
-        decoder: *RangeDecoder,
-        length: usize,
-        update: bool,
-    ) !usize {
-        const len_state = if (length > 3) 3 else length;
-
-        const pos_slot = @as(usize, try self.pos_slot_decoder[len_state].parse(reader, decoder, update));
-        if (pos_slot < 4)
-            return pos_slot;
-
-        const num_direct_bits = @intCast(u5, (pos_slot >> 1) - 1);
-        var result = (2 ^ (pos_slot & 1)) << num_direct_bits;
-
-        if (pos_slot < 14) {
-            result += try decoder.parseReverseBitTree(
-                reader,
-                num_direct_bits,
-                &self.pos_decoders,
-                result - pos_slot,
-                update,
-            );
-        } else {
-            result += @as(usize, try decoder.get(reader, num_direct_bits - 4)) << 4;
-            result += try self.align_decoder.parseReverse(reader, decoder, update);
-        }
-
-        return result;
-    }
-};
-
-pub const LzmaDecoder = struct {
-    params: LzmaParams,
-    memlimit: usize,
-    state: DecoderState,
-
-    pub fn init(allocator: Allocator, params: LzmaParams, memlimit: ?usize) !LzmaDecoder {
-        return LzmaDecoder{
-            .params = params,
-            .memlimit = memlimit orelse math.maxInt(usize),
-            .state = try DecoderState.init(allocator, params.properties, params.unpacked_size),
-        };
-    }
-
-    pub fn deinit(self: *LzmaDecoder, allocator: Allocator) void {
-        self.state.deinit(allocator);
-        self.* = undefined;
-    }
-
-    pub fn decompress(
-        self: *LzmaDecoder,
-        allocator: Allocator,
-        reader: anytype,
-        writer: anytype,
-    ) !void {
-        var buffer = LzCircularBuffer.init(self.params.dict_size, self.memlimit);
-        defer buffer.deinit(allocator);
-
-        var decoder = try RangeDecoder.init(reader);
-        try self.state.process(allocator, reader, writer, &buffer, &decoder);
-        try buffer.finish(writer);
-    }
-};
lib/std/compress/lzma/decode/rangecoder.zig
@@ -1,8 +1,5 @@
 const std = @import("../../../std.zig");
 const mem = std.mem;
-const Allocator = std.mem.Allocator;
-const ArrayListUnmanaged = std.ArrayListUnmanaged;
-const FixedBufferStream = std.io.FixedBufferStream;
 
 pub const RangeDecoder = struct {
     range: u32,
lib/std/compress/lzma/decode.zig
@@ -1,8 +1,17 @@
+const std = @import("../../std.zig");
+const assert = std.debug.assert;
+const math = std.math;
+const Allocator = std.mem.Allocator;
+
 pub const lzbuffer = @import("decode/lzbuffer.zig");
-pub const lzma = @import("decode/lzma.zig");
-pub const lzma2 = @import("decode/lzma2.zig");
 pub const rangecoder = @import("decode/rangecoder.zig");
 
+const LzCircularBuffer = lzbuffer.LzCircularBuffer;
+const BitTree = rangecoder.BitTree;
+const LenDecoder = rangecoder.LenDecoder;
+const RangeDecoder = rangecoder.RangeDecoder;
+const Vec2D = @import("vec2d.zig").Vec2D;
+
 pub const Options = struct {
     unpacked_size: UnpackedSize = .read_from_header,
     memlimit: ?usize = null,
@@ -14,3 +23,387 @@ pub const UnpackedSize = union(enum) {
     read_header_but_use_provided: ?u64,
     use_provided: ?u64,
 };
+
+const ProcessingStatus = enum {
+    continue_,
+    finished,
+};
+
+pub const Properties = struct {
+    lc: u4,
+    lp: u3,
+    pb: u3,
+
+    fn validate(self: Properties) void {
+        assert(self.lc <= 8);
+        assert(self.lp <= 4);
+        assert(self.pb <= 4);
+    }
+};
+
+pub const Params = struct {
+    properties: Properties,
+    dict_size: u32,
+    unpacked_size: ?u64,
+
+    pub fn readHeader(reader: anytype, options: Options) !Params {
+        var props = try reader.readByte();
+        if (props >= 225) {
+            return error.CorruptInput;
+        }
+
+        const lc = @intCast(u4, props % 9);
+        props /= 9;
+        const lp = @intCast(u3, props % 5);
+        props /= 5;
+        const pb = @intCast(u3, props);
+
+        const dict_size_provided = try reader.readIntLittle(u32);
+        const dict_size = math.max(0x1000, dict_size_provided);
+
+        const unpacked_size = switch (options.unpacked_size) {
+            .read_from_header => blk: {
+                const unpacked_size_provided = try reader.readIntLittle(u64);
+                const marker_mandatory = unpacked_size_provided == 0xFFFF_FFFF_FFFF_FFFF;
+                break :blk if (marker_mandatory)
+                    null
+                else
+                    unpacked_size_provided;
+            },
+            .read_header_but_use_provided => |x| blk: {
+                _ = try reader.readIntLittle(u64);
+                break :blk x;
+            },
+            .use_provided => |x| x,
+        };
+
+        return Params{
+            .properties = Properties{ .lc = lc, .lp = lp, .pb = pb },
+            .dict_size = dict_size,
+            .unpacked_size = unpacked_size,
+        };
+    }
+};
+
+pub const DecoderState = struct {
+    lzma_props: Properties,
+    unpacked_size: ?u64,
+    literal_probs: Vec2D(u16),
+    pos_slot_decoder: [4]BitTree(6),
+    align_decoder: BitTree(4),
+    pos_decoders: [115]u16,
+    is_match: [192]u16,
+    is_rep: [12]u16,
+    is_rep_g0: [12]u16,
+    is_rep_g1: [12]u16,
+    is_rep_g2: [12]u16,
+    is_rep_0long: [192]u16,
+    state: usize,
+    rep: [4]usize,
+    len_decoder: LenDecoder,
+    rep_len_decoder: LenDecoder,
+
+    pub fn init(
+        allocator: Allocator,
+        lzma_props: Properties,
+        unpacked_size: ?u64,
+    ) !DecoderState {
+        return .{
+            .lzma_props = lzma_props,
+            .unpacked_size = unpacked_size,
+            .literal_probs = try Vec2D(u16).init(allocator, 0x400, .{ @as(usize, 1) << (lzma_props.lc + lzma_props.lp), 0x300 }),
+            .pos_slot_decoder = .{.{}} ** 4,
+            .align_decoder = .{},
+            .pos_decoders = .{0x400} ** 115,
+            .is_match = .{0x400} ** 192,
+            .is_rep = .{0x400} ** 12,
+            .is_rep_g0 = .{0x400} ** 12,
+            .is_rep_g1 = .{0x400} ** 12,
+            .is_rep_g2 = .{0x400} ** 12,
+            .is_rep_0long = .{0x400} ** 192,
+            .state = 0,
+            .rep = .{0} ** 4,
+            .len_decoder = .{},
+            .rep_len_decoder = .{},
+        };
+    }
+
+    pub fn deinit(self: *DecoderState, allocator: Allocator) void {
+        self.literal_probs.deinit(allocator);
+        self.* = undefined;
+    }
+
+    pub fn resetState(self: *DecoderState, allocator: Allocator, new_props: Properties) !void {
+        new_props.validate();
+        if (self.lzma_props.lc + self.lzma_props.lp == new_props.lc + new_props.lp) {
+            self.literal_probs.fill(0x400);
+        } else {
+            self.literal_probs.deinit(allocator);
+            self.literal_probs = try Vec2D(u16).init(allocator, 0x400, .{ @as(usize, 1) << (new_props.lc + new_props.lp), 0x300 });
+        }
+
+        self.lzma_props = new_props;
+        for (self.pos_slot_decoder) |*t| t.reset();
+        self.align_decoder.reset();
+        self.pos_decoders = .{0x400} ** 115;
+        self.is_match = .{0x400} ** 192;
+        self.is_rep = .{0x400} ** 12;
+        self.is_rep_g0 = .{0x400} ** 12;
+        self.is_rep_g1 = .{0x400} ** 12;
+        self.is_rep_g2 = .{0x400} ** 12;
+        self.is_rep_0long = .{0x400} ** 192;
+        self.state = 0;
+        self.rep = .{0} ** 4;
+        self.len_decoder.reset();
+        self.rep_len_decoder.reset();
+    }
+
+    fn processNextInner(
+        self: *DecoderState,
+        allocator: Allocator,
+        reader: anytype,
+        writer: anytype,
+        buffer: anytype,
+        decoder: *RangeDecoder,
+        update: bool,
+    ) !ProcessingStatus {
+        const pos_state = buffer.len & ((@as(usize, 1) << self.lzma_props.pb) - 1);
+
+        if (!try decoder.decodeBit(
+            reader,
+            &self.is_match[(self.state << 4) + pos_state],
+            update,
+        )) {
+            const byte: u8 = try self.decodeLiteral(reader, buffer, decoder, update);
+
+            if (update) {
+                try buffer.appendLiteral(allocator, byte, writer);
+
+                self.state = if (self.state < 4)
+                    0
+                else if (self.state < 10)
+                    self.state - 3
+                else
+                    self.state - 6;
+            }
+            return .continue_;
+        }
+
+        var len: usize = undefined;
+        if (try decoder.decodeBit(reader, &self.is_rep[self.state], update)) {
+            if (!try decoder.decodeBit(reader, &self.is_rep_g0[self.state], update)) {
+                if (!try decoder.decodeBit(
+                    reader,
+                    &self.is_rep_0long[(self.state << 4) + pos_state],
+                    update,
+                )) {
+                    if (update) {
+                        self.state = if (self.state < 7) 9 else 11;
+                        const dist = self.rep[0] + 1;
+                        try buffer.appendLz(allocator, 1, dist, writer);
+                    }
+                    return .continue_;
+                }
+            } else {
+                const idx: usize = if (!try decoder.decodeBit(reader, &self.is_rep_g1[self.state], update))
+                    1
+                else if (!try decoder.decodeBit(reader, &self.is_rep_g2[self.state], update))
+                    2
+                else
+                    3;
+                if (update) {
+                    const dist = self.rep[idx];
+                    var i = idx;
+                    while (i > 0) : (i -= 1) {
+                        self.rep[i] = self.rep[i - 1];
+                    }
+                    self.rep[0] = dist;
+                }
+            }
+
+            len = try self.rep_len_decoder.decode(reader, decoder, pos_state, update);
+
+            if (update) {
+                self.state = if (self.state < 7) 8 else 11;
+            }
+        } else {
+            if (update) {
+                self.rep[3] = self.rep[2];
+                self.rep[2] = self.rep[1];
+                self.rep[1] = self.rep[0];
+            }
+
+            len = try self.len_decoder.decode(reader, decoder, pos_state, update);
+
+            if (update) {
+                self.state = if (self.state < 7) 7 else 10;
+            }
+
+            const rep_0 = try self.decodeDistance(reader, decoder, len, update);
+
+            if (update) {
+                self.rep[0] = rep_0;
+                if (self.rep[0] == 0xFFFF_FFFF) {
+                    if (decoder.isFinished()) {
+                        return .finished;
+                    }
+                    return error.CorruptInput;
+                }
+            }
+        }
+
+        if (update) {
+            len += 2;
+
+            const dist = self.rep[0] + 1;
+            try buffer.appendLz(allocator, len, dist, writer);
+        }
+
+        return .continue_;
+    }
+
+    fn processNext(
+        self: *DecoderState,
+        allocator: Allocator,
+        reader: anytype,
+        writer: anytype,
+        buffer: anytype,
+        decoder: *RangeDecoder,
+    ) !ProcessingStatus {
+        return self.processNextInner(allocator, reader, writer, buffer, decoder, true);
+    }
+
+    pub fn process(
+        self: *DecoderState,
+        allocator: Allocator,
+        reader: anytype,
+        writer: anytype,
+        buffer: anytype,
+        decoder: *RangeDecoder,
+    ) !void {
+        while (true) {
+            if (self.unpacked_size) |unpacked_size| {
+                if (buffer.len >= unpacked_size) {
+                    break;
+                }
+            } else if (decoder.isFinished()) {
+                break;
+            }
+
+            if (try self.processNext(allocator, reader, writer, buffer, decoder) == .finished) {
+                break;
+            }
+        }
+
+        if (self.unpacked_size) |len| {
+            if (len != buffer.len) {
+                return error.CorruptInput;
+            }
+        }
+    }
+
+    fn decodeLiteral(
+        self: *DecoderState,
+        reader: anytype,
+        buffer: anytype,
+        decoder: *RangeDecoder,
+        update: bool,
+    ) !u8 {
+        const def_prev_byte = 0;
+        const prev_byte = @as(usize, buffer.lastOr(def_prev_byte));
+
+        var result: usize = 1;
+        const lit_state = ((buffer.len & ((@as(usize, 1) << self.lzma_props.lp) - 1)) << self.lzma_props.lc) +
+            (prev_byte >> (8 - self.lzma_props.lc));
+        const probs = try self.literal_probs.getMut(lit_state);
+
+        if (self.state >= 7) {
+            var match_byte = @as(usize, try buffer.lastN(self.rep[0] + 1));
+
+            while (result < 0x100) {
+                const match_bit = (match_byte >> 7) & 1;
+                match_byte <<= 1;
+                const bit = @boolToInt(try decoder.decodeBit(
+                    reader,
+                    &probs[((@as(usize, 1) + match_bit) << 8) + result],
+                    update,
+                ));
+                result = (result << 1) ^ bit;
+                if (match_bit != bit) {
+                    break;
+                }
+            }
+        }
+
+        while (result < 0x100) {
+            result = (result << 1) ^ @boolToInt(try decoder.decodeBit(reader, &probs[result], update));
+        }
+
+        return @truncate(u8, result - 0x100);
+    }
+
+    fn decodeDistance(
+        self: *DecoderState,
+        reader: anytype,
+        decoder: *RangeDecoder,
+        length: usize,
+        update: bool,
+    ) !usize {
+        const len_state = if (length > 3) 3 else length;
+
+        const pos_slot = @as(usize, try self.pos_slot_decoder[len_state].parse(reader, decoder, update));
+        if (pos_slot < 4)
+            return pos_slot;
+
+        const num_direct_bits = @intCast(u5, (pos_slot >> 1) - 1);
+        var result = (2 ^ (pos_slot & 1)) << num_direct_bits;
+
+        if (pos_slot < 14) {
+            result += try decoder.parseReverseBitTree(
+                reader,
+                num_direct_bits,
+                &self.pos_decoders,
+                result - pos_slot,
+                update,
+            );
+        } else {
+            result += @as(usize, try decoder.get(reader, num_direct_bits - 4)) << 4;
+            result += try self.align_decoder.parseReverse(reader, decoder, update);
+        }
+
+        return result;
+    }
+};
+
+pub const Decoder = struct {
+    params: Params,
+    memlimit: usize,
+    state: DecoderState,
+
+    pub fn init(allocator: Allocator, params: Params, memlimit: ?usize) !Decoder {
+        return Decoder{
+            .params = params,
+            .memlimit = memlimit orelse math.maxInt(usize),
+            .state = try DecoderState.init(allocator, params.properties, params.unpacked_size),
+        };
+    }
+
+    pub fn deinit(self: *Decoder, allocator: Allocator) void {
+        self.state.deinit(allocator);
+        self.* = undefined;
+    }
+
+    pub fn decompress(
+        self: *Decoder,
+        allocator: Allocator,
+        reader: anytype,
+        writer: anytype,
+    ) !void {
+        var buffer = LzCircularBuffer.init(self.params.dict_size, self.memlimit);
+        defer buffer.deinit(allocator);
+
+        var decoder = try RangeDecoder.init(reader);
+        try self.state.process(allocator, reader, writer, &buffer, &decoder);
+        try buffer.finish(writer);
+    }
+};
lib/std/compress/lzma/lzma2_test.zig
@@ -1,27 +0,0 @@
-const std = @import("../../std.zig");
-const lzma = @import("../lzma.zig");
-
-fn testDecompress(compressed: []const u8, writer: anytype) !void {
-    const allocator = std.testing.allocator;
-    var stream = std.io.fixedBufferStream(compressed);
-    try lzma.lzma2Decompress(allocator, stream.reader(), writer);
-}
-
-fn testDecompressEqual(expected: []const u8, compressed: []const u8) !void {
-    const allocator = std.testing.allocator;
-    var decomp = std.ArrayList(u8).init(allocator);
-    defer decomp.deinit();
-    try testDecompress(compressed, decomp.writer());
-    try std.testing.expectEqualSlices(u8, expected, decomp.items);
-}
-
-fn testDecompressError(expected: anyerror, compressed: []const u8) !void {
-    return std.testing.expectError(expected, testDecompress(compressed, std.io.null_writer));
-}
-
-test {
-    try testDecompressEqual(
-        "Hello\nWorld!\n",
-        &[_]u8{ 0x01, 0x00, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x02, 0x00, 0x06, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x0A, 0x00 },
-    );
-}
lib/std/compress/lzma/lzma_test.zig → lib/std/compress/lzma/test.zig
@@ -4,7 +4,7 @@ const lzma = @import("../lzma.zig");
 fn testDecompress(compressed: []const u8, writer: anytype) !void {
     const allocator = std.testing.allocator;
     var stream = std.io.fixedBufferStream(compressed);
-    try lzma.lzmaDecompress(allocator, stream.reader(), writer, .{});
+    try lzma.decompress(allocator, stream.reader(), writer, .{});
 }
 
 fn testDecompressEqual(expected: []const u8, compressed: []const u8) !void {
@@ -19,7 +19,7 @@ fn testDecompressError(expected: anyerror, compressed: []const u8) !void {
     return std.testing.expectError(expected, testDecompress(compressed, std.io.null_writer));
 }
 
-test "decompress empty world" {
+test "LZMA: decompress empty world" {
     try testDecompressEqual(
         "",
         &[_]u8{
@@ -29,7 +29,7 @@ test "decompress empty world" {
     );
 }
 
-test "decompress hello world" {
+test "LZMA: decompress hello world" {
     try testDecompressEqual(
         "Hello world\n",
         &[_]u8{
@@ -40,7 +40,7 @@ test "decompress hello world" {
     );
 }
 
-test "decompress huge dict" {
+test "LZMA: decompress huge dict" {
     try testDecompressEqual(
         "Hello world\n",
         &[_]u8{
@@ -51,35 +51,35 @@ test "decompress huge dict" {
     );
 }
 
-test "unknown size with end of payload marker" {
+test "LZMA: unknown size with end of payload marker" {
     try testDecompressEqual(
         "Hello\nWorld!\n",
         @embedFile("testdata/good-unknown_size-with_eopm.lzma"),
     );
 }
 
-test "known size without end of payload marker" {
+test "LZMA: known size without end of payload marker" {
     try testDecompressEqual(
         "Hello\nWorld!\n",
         @embedFile("testdata/good-known_size-without_eopm.lzma"),
     );
 }
 
-test "known size with end of payload marker" {
+test "LZMA: known size with end of payload marker" {
     try testDecompressEqual(
         "Hello\nWorld!\n",
         @embedFile("testdata/good-known_size-with_eopm.lzma"),
     );
 }
 
-test "too big uncompressed size in header" {
+test "LZMA: too big uncompressed size in header" {
     try testDecompressError(
         error.CorruptInput,
         @embedFile("testdata/bad-too_big_size-with_eopm.lzma"),
     );
 }
 
-test "too small uncompressed size in header" {
+test "LZMA: too small uncompressed size in header" {
     try testDecompressError(
         error.CorruptInput,
         @embedFile("testdata/bad-too_small_size-without_eopm-3.lzma"),
lib/std/compress/lzma/decode/lzma2.zig → lib/std/compress/lzma2/decode.zig
@@ -1,20 +1,20 @@
-const std = @import("../../../std.zig");
+const std = @import("../../std.zig");
 const Allocator = std.mem.Allocator;
 
-const lzma = @import("lzma.zig");
-const DecoderState = lzma.DecoderState;
-const LzmaProperties = lzma.LzmaProperties;
-const LzAccumBuffer = @import("lzbuffer.zig").LzAccumBuffer;
-const RangeDecoder = @import("rangecoder.zig").RangeDecoder;
+const lzma = @import("../lzma.zig");
+const DecoderState = lzma.decode.DecoderState;
+const LzAccumBuffer = lzma.decode.lzbuffer.LzAccumBuffer;
+const Properties = lzma.decode.Properties;
+const RangeDecoder = lzma.decode.rangecoder.RangeDecoder;
 
-pub const Lzma2Decoder = struct {
+pub const Decoder = struct {
     lzma_state: DecoderState,
 
-    pub fn init(allocator: Allocator) !Lzma2Decoder {
-        return Lzma2Decoder{
+    pub fn init(allocator: Allocator) !Decoder {
+        return Decoder{
             .lzma_state = try DecoderState.init(
                 allocator,
-                LzmaProperties{
+                Properties{
                     .lc = 0,
                     .lp = 0,
                     .pb = 0,
@@ -24,13 +24,13 @@ pub const Lzma2Decoder = struct {
         };
     }
 
-    pub fn deinit(self: *Lzma2Decoder, allocator: Allocator) void {
+    pub fn deinit(self: *Decoder, allocator: Allocator) void {
         self.lzma_state.deinit(allocator);
         self.* = undefined;
     }
 
     pub fn decompress(
-        self: *Lzma2Decoder,
+        self: *Decoder,
         allocator: Allocator,
         reader: anytype,
         writer: anytype,
@@ -53,7 +53,7 @@ pub const Lzma2Decoder = struct {
     }
 
     fn parseLzma(
-        self: *Lzma2Decoder,
+        self: *Decoder,
         allocator: Allocator,
         reader: anytype,
         writer: anytype,
@@ -129,7 +129,7 @@ pub const Lzma2Decoder = struct {
                     return error.CorruptInput;
                 }
 
-                new_props = LzmaProperties{ .lc = lc, .lp = lp, .pb = pb };
+                new_props = Properties{ .lc = lc, .lp = lp, .pb = pb };
             }
 
             try self.lzma_state.resetState(allocator, new_props);
lib/std/compress/lzma.zig
@@ -1,36 +1,21 @@
 const std = @import("../std.zig");
 const Allocator = std.mem.Allocator;
-const FixedBufferStream = std.io.FixedBufferStream;
 
 pub const decode = @import("lzma/decode.zig");
-pub const LzmaParams = decode.lzma.LzmaParams;
-pub const LzmaDecoder = decode.lzma.LzmaDecoder;
-pub const Lzma2Decoder = decode.lzma2.Lzma2Decoder;
 
-pub fn lzmaDecompress(
+pub fn decompress(
     allocator: Allocator,
     reader: anytype,
     writer: anytype,
     options: decode.Options,
 ) !void {
-    const params = try LzmaParams.readHeader(reader, options);
-    var decoder = try LzmaDecoder.init(allocator, params, options.memlimit);
-    defer decoder.deinit(allocator);
-    return decoder.decompress(allocator, reader, writer);
-}
-
-pub fn lzma2Decompress(
-    allocator: Allocator,
-    reader: anytype,
-    writer: anytype,
-) !void {
-    var decoder = try Lzma2Decoder.init(allocator);
+    const params = try decode.Params.readHeader(reader, options);
+    var decoder = try decode.Decoder.init(allocator, params, options.memlimit);
     defer decoder.deinit(allocator);
     return decoder.decompress(allocator, reader, writer);
 }
 
 test {
-    _ = @import("lzma/lzma_test.zig");
-    _ = @import("lzma/lzma2_test.zig");
+    _ = @import("lzma/test.zig");
     _ = @import("lzma/vec2d.zig");
 }
lib/std/compress/lzma2.zig
@@ -0,0 +1,26 @@
+const std = @import("../std.zig");
+const Allocator = std.mem.Allocator;
+
+pub const decode = @import("lzma2/decode.zig");
+
+pub fn decompress(
+    allocator: Allocator,
+    reader: anytype,
+    writer: anytype,
+) !void {
+    var decoder = try decode.Decoder.init(allocator);
+    defer decoder.deinit(allocator);
+    return decoder.decompress(allocator, reader, writer);
+}
+
+test {
+    const expected = "Hello\nWorld!\n";
+    const compressed = &[_]u8{ 0x01, 0x00, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x02, 0x00, 0x06, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x0A, 0x00 };
+
+    const allocator = std.testing.allocator;
+    var decomp = std.ArrayList(u8).init(allocator);
+    defer decomp.deinit();
+    var stream = std.io.fixedBufferStream(compressed);
+    try decompress(allocator, stream.reader(), decomp.writer());
+    try std.testing.expectEqualSlices(u8, expected, decomp.items);
+}
lib/std/compress.zig
@@ -3,6 +3,7 @@ const std = @import("std.zig");
 pub const deflate = @import("compress/deflate.zig");
 pub const gzip = @import("compress/gzip.zig");
 pub const lzma = @import("compress/lzma.zig");
+pub const lzma2 = @import("compress/lzma2.zig");
 pub const xz = @import("compress/xz.zig");
 pub const zlib = @import("compress/zlib.zig");
 
@@ -40,6 +41,7 @@ test {
     _ = deflate;
     _ = gzip;
     _ = lzma;
+    _ = lzma2;
     _ = xz;
     _ = zlib;
 }