mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 02:48:50 +00:00
123 lines
4.8 KiB
Zig
123 lines
4.8 KiB
Zig
pub const Decompressor = union(enum) {
|
|
zlib: *Zlib.ZlibReaderArrayList,
|
|
brotli: *Brotli.BrotliReaderArrayList,
|
|
zstd: *zstd.ZstdReaderArrayList,
|
|
none: void,
|
|
|
|
pub fn deinit(this: *Decompressor) void {
|
|
switch (this.*) {
|
|
inline .brotli, .zlib, .zstd => |that| {
|
|
that.deinit();
|
|
this.* = .{ .none = {} };
|
|
},
|
|
.none => {},
|
|
}
|
|
}
|
|
|
|
pub fn updateBuffers(this: *Decompressor, encoding: Encoding, buffer: []const u8, body_out_str: *MutableString) !void {
|
|
if (!encoding.isCompressed()) {
|
|
return;
|
|
}
|
|
|
|
if (this.* == .none) {
|
|
switch (encoding) {
|
|
.gzip, .deflate => {
|
|
this.* = .{
|
|
.zlib = try Zlib.ZlibReaderArrayList.initWithOptionsAndListAllocator(
|
|
buffer,
|
|
&body_out_str.list,
|
|
body_out_str.allocator,
|
|
bun.http.default_allocator,
|
|
.{
|
|
// zlib.MAX_WBITS = 15
|
|
// to (de-)compress deflate format, use wbits = -zlib.MAX_WBITS
|
|
// to (de-)compress deflate format with headers we use wbits = 0 (we can detect the first byte using 120)
|
|
// to (de-)compress gzip format, use wbits = zlib.MAX_WBITS | 16
|
|
.windowBits = if (encoding == Encoding.gzip) Zlib.MAX_WBITS | 16 else (if (buffer.len > 1 and buffer[0] == 120) 0 else -Zlib.MAX_WBITS),
|
|
},
|
|
),
|
|
};
|
|
return;
|
|
},
|
|
.brotli => {
|
|
this.* = .{
|
|
.brotli = try Brotli.BrotliReaderArrayList.newWithOptions(
|
|
buffer,
|
|
&body_out_str.list,
|
|
body_out_str.allocator,
|
|
.{},
|
|
),
|
|
};
|
|
return;
|
|
},
|
|
.zstd => {
|
|
this.* = .{
|
|
.zstd = try zstd.ZstdReaderArrayList.initWithListAllocator(
|
|
buffer,
|
|
&body_out_str.list,
|
|
body_out_str.allocator,
|
|
bun.http.default_allocator,
|
|
),
|
|
};
|
|
return;
|
|
},
|
|
else => @panic("Invalid encoding. This code should not be reachable"),
|
|
}
|
|
}
|
|
|
|
switch (this.*) {
|
|
.zlib => |reader| {
|
|
bun.assert(reader.zlib.avail_in == 0);
|
|
reader.zlib.next_in = buffer.ptr;
|
|
reader.zlib.avail_in = @as(u32, @truncate(buffer.len));
|
|
|
|
const initial = body_out_str.list.items.len;
|
|
body_out_str.list.expandToCapacity();
|
|
if (body_out_str.list.capacity == initial) {
|
|
try body_out_str.list.ensureUnusedCapacity(body_out_str.allocator, 4096);
|
|
body_out_str.list.expandToCapacity();
|
|
}
|
|
reader.list = body_out_str.list;
|
|
reader.zlib.next_out = @ptrCast(&body_out_str.list.items[initial]);
|
|
reader.zlib.avail_out = @as(u32, @truncate(body_out_str.list.capacity - initial));
|
|
// we reset the total out so we can track how much we decompressed this time
|
|
reader.zlib.total_out = @truncate(initial);
|
|
},
|
|
.brotli => |reader| {
|
|
reader.input = buffer;
|
|
reader.total_in = 0;
|
|
|
|
const initial = body_out_str.list.items.len;
|
|
reader.list = body_out_str.list;
|
|
reader.total_out = @truncate(initial);
|
|
},
|
|
.zstd => |reader| {
|
|
reader.input = buffer;
|
|
reader.total_in = 0;
|
|
|
|
const initial = body_out_str.list.items.len;
|
|
reader.list = body_out_str.list;
|
|
reader.total_out = @truncate(initial);
|
|
},
|
|
else => @panic("Invalid encoding. This code should not be reachable"),
|
|
}
|
|
}
|
|
|
|
pub fn readAll(this: *Decompressor, is_done: bool) !void {
|
|
switch (this.*) {
|
|
.zlib => |zlib| try zlib.readAll(),
|
|
.brotli => |brotli| try brotli.readAll(is_done),
|
|
.zstd => |reader| try reader.readAll(is_done),
|
|
.none => {},
|
|
}
|
|
}
|
|
};
|
|
|
|
const Zlib = @import("../zlib.zig");
|
|
const Encoding = @import("./Encoding.zig").Encoding;
|
|
|
|
const bun = @import("bun");
|
|
const Brotli = bun.brotli;
|
|
const MutableString = bun.MutableString;
|
|
const zstd = bun.zstd;
|