aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bun.js/base.zig10
-rw-r--r--src/compress.zig103
-rw-r--r--src/deps/brotli.zig45
-rw-r--r--src/stream_tester.zig59
4 files changed, 139 insertions, 78 deletions
diff --git a/src/bun.js/base.zig b/src/bun.js/base.zig
index 535c08395..b9dba8b37 100644
--- a/src/bun.js/base.zig
+++ b/src/bun.js/base.zig
@@ -1784,6 +1784,16 @@ pub const ArrayBuffer = extern struct {
};
}
+ pub fn createFromLength(globalThis: *JSC.JSGlobalObject, len: usize, comptime kind: BinaryType) JSValue {
+ JSC.markBinding(@src());
+ return switch (comptime kind) {
+ .Uint8Array => Bun__createUint8ArrayForCopy(globalThis, null, len, false),
+ .Buffer => Bun__createUint8ArrayForCopy(globalThis, null, len, true),
+ .ArrayBuffer => Bun__createArrayBufferForCopy(globalThis, null, len),
+ else => @compileError("Not implemented yet"),
+ };
+ }
+
pub fn createEmpty(globalThis: *JSC.JSGlobalObject, comptime kind: JSC.JSValue.JSType) JSValue {
JSC.markBinding(@src());
diff --git a/src/compress.zig b/src/compress.zig
index dd882849e..c2470dfa4 100644
--- a/src/compress.zig
+++ b/src/compress.zig
@@ -3,9 +3,12 @@ const std = @import("std");
const zlib = @import("./zlib.zig");
const brotli = bun.brotli;
+const String = bun.String;
+
pub const Error = struct {
- code: bun.String = bun.String.empty,
- message: bun.String = bun.String.empty,
+ // To workaround a zig compiler bug, we avoid using String here.
+ code: []const u8,
+ message: []const u8,
};
pub const Ownership = enum { transfer, must_copy };
@@ -31,84 +34,42 @@ pub const Controller = struct {
this.pull_fn(this.ctx);
}
- pub fn init(comptime Context: type, context: Context) Controller {
+ pub fn init(comptime ContextType: type, context: ContextType) Controller {
+ const Context = std.meta.Child(ContextType);
return Controller{
.ctx = @ptrCast(*anyopaque, context),
.closed = @ptrCast(*bool, &context.closed),
- .receive_data_fn = @ptrCast(*const fn (*anyopaque, []const u8, Ownership, Completion) void, Context.onData),
- .receive_error_fn = @ptrCast(*const fn (*anyopaque, Error) void, Context.onError),
- .pull_fn = @ptrCast(*const fn (*anyopaque) void, Context.onPull),
+ .receive_data_fn = @ptrCast(*const fn (*anyopaque, []const u8, Ownership, Completion) void, &Context.onData),
+ .receive_error_fn = @ptrCast(*const fn (*anyopaque, Error) void, &Context.onError),
+ .pull_fn = @ptrCast(*const fn (*anyopaque) void, &Context.onPull),
};
}
};
-pub const CLIFileStreamCompressor = struct {
- input: std.fs.File,
- output: std.fs.File,
- closed: bool = false,
-
- ready_for_more: bool = false,
- has_more_output: bool = true,
-
- pub fn controller(this: *CLIFileStreamCompressor) Controller {
- return Controller.init(*CLIFileStreamCompressor, this);
- }
-
- pub fn onData(this: *CLIFileStreamCompressor, bytes: []const u8, _: Ownership, completion: Completion) void {
- std.debug.assert(!this.closed);
- this.output.writeAll(bytes) catch @panic("failed to write to file");
- if (completion == Completion.last) {
- this.ready_for_more = false;
- }
- }
-
- pub fn onError(this: *CLIFileStreamCompressor, err: Error) void {
- std.debug.assert(!this.closed);
- std.debug.panic("Error: {}\n{}", .{ err.code, err.message });
- }
-
- pub fn onPull(this: *CLIFileStreamCompressor) void {
- this.ready_for_more = true;
- }
-
- pub fn init(path: []const u8) !CLIFileStreamCompressor {
- var file = try std.fs.cwd().openFile(path, .{ .mode = .read_write });
- return CLIFileStreamCompressor{ .input = file, .output = std.io.getStdOut() };
- }
-
- pub fn run(this: *CLIFileStreamCompressor, stream: *Compressor) !void {
- this.ready_for_more = true;
- const ctrl = this.controller();
-
- while (this.has_more_output) {
- var buffer: [64 * 1024]u8 = undefined;
- var to_read: []u8 = buffer[0..try this.input.readAll(&buffer)];
- this.has_more_output = to_read.len != 0;
- if (this.has_more_output) {
- stream.write(to_read, ctrl);
- }
- }
-
- stream.end(ctrl);
- }
-};
-
pub const Compressor = union(enum) {
BrotliEncoder: Brotli.Encoder,
BrotliDecoder: Brotli.Decoder,
pub fn write(this: *Compressor, data: []const u8, controller: Controller) void {
- return switch (this) {
- .BrotliEncoder => this.BrotliEncoder.write(data, controller),
- .BrotliDecoder => this.BrotliDecoder.write(data, controller),
- };
+ switch (this.*) {
+ .BrotliEncoder => {
+ this.BrotliEncoder.write(data, controller);
+ },
+ .BrotliDecoder => {
+ this.BrotliDecoder.write(data, controller);
+ },
+ }
}
- pub fn end(this: *Compressor) void {
- return switch (this) {
- .BrotliEncoder => this.BrotliEncoder.end(),
- .BrotliDecoder => this.BrotliDecoder.end(),
- };
+ pub fn end(this: *Compressor, controller: Controller) void {
+ switch (this.*) {
+ .BrotliEncoder => {
+ this.BrotliEncoder.end(controller);
+ },
+ .BrotliDecoder => {
+ this.BrotliDecoder.end(controller);
+ },
+ }
}
pub fn initWithType(comptime Type: type, value: Type) !*Compressor {
@@ -157,7 +118,7 @@ pub const Brotli = struct {
controller.enqueue(
taken,
.must_copy,
- false,
+ .not_last,
);
if (!state.hasMoreOutput())
@@ -195,8 +156,8 @@ pub const Brotli = struct {
.@"error" => {
const code = state.getErrorCode();
controller.fail(Error{
- .code = bun.String.static(code.code()),
- .message = bun.String.static(code.message()),
+ .code = code.code(),
+ .message = code.message(),
});
return;
},
@@ -233,9 +194,7 @@ pub const Brotli = struct {
pub fn end(this: *Decoder, controller: Controller) void {
var state = this.state orelse return;
this.state = null;
- consume(state, controller);
- std.debug.assert(state.finish(null, null, null));
- consume(state, controller);
+ consume(state, controller, true);
state.deinit();
}
};
diff --git a/src/deps/brotli.zig b/src/deps/brotli.zig
index f6bcfe310..141e221f8 100644
--- a/src/deps/brotli.zig
+++ b/src/deps/brotli.zig
@@ -42,16 +42,51 @@ pub const BrotliDecoderState = opaque {
return BrotliDecoderSetParameter(self, param, value) == BROTLI_TRUE;
}
- pub fn write(self: *BrotliDecoderState, input: *[]const u8, output: *[]u8, total_size: ?*usize) BrotliDecoderResult {
- return BrotliDecoderDecompressStream(self, &input.len, &input.ptr, &output.len, &output.ptr, total_size);
+ pub fn write(self: *BrotliDecoderState, input: ?*[]const u8, output: ?*[]u8, total_size: ?*usize) BrotliDecoderResult {
+ var input_len: usize = 0;
+ var input_ptr: ?[*]const u8 = null;
+
+ var output_len: usize = 0;
+ var output_ptr: ?[*]u8 = null;
+
+ if (input) |in| {
+ input_len = in.len;
+ input_ptr = in.ptr;
+ }
+
+ if (output) |out| {
+ output_len = out.len;
+ output_ptr = out.ptr;
+ }
+
+ defer {
+ if (input) |in| {
+ in.len = input_len;
+ if (input_ptr != null)
+ in.ptr = input_ptr.?;
+ }
+
+ if (output) |out| {
+ out.len = output_len;
+ if (output_ptr != null)
+ out.ptr = output_ptr.?;
+ }
+ }
+ return BrotliDecoderDecompressStream(self, &input_len, &input_ptr, &output_len, &output_ptr, total_size);
}
pub fn getErrorCode(self: *const BrotliDecoderState) BrotliDecoderErrorCode {
return BrotliDecoderGetErrorCode(self);
}
- pub fn hasMoreOutput(self: *BrotliEncoderState) bool {
- return BrotliEncoderHasMoreOutput(self) == BROTLI_TRUE;
+ pub fn hasMoreOutput(self: *const BrotliDecoderState) bool {
+ return BrotliDecoderHasMoreOutput(self) == BROTLI_TRUE;
+ }
+
+ pub fn take(self: *BrotliDecoderState, requested: usize) []const u8 {
+ var size: usize = requested;
+ var ptr = BrotliDecoderTakeOutput(self, &size) orelse return "";
+ return ptr[0..size];
}
};
@@ -291,7 +326,7 @@ pub extern fn BrotliDecoderAttachDictionary(state: ?*BrotliDecoderState, @"type"
pub extern fn BrotliDecoderCreateInstance(alloc_func: brotli_alloc_func, free_func: brotli_free_func, @"opaque": ?*anyopaque) *BrotliDecoderState;
pub extern fn BrotliDecoderDestroyInstance(state: ?*BrotliDecoderState) void;
pub extern fn BrotliDecoderDecompress(encoded_size: usize, encoded_buffer: [*]const u8, decoded_size: *usize, decoded_buffer: [*]u8) BrotliDecoderResult;
-pub extern fn BrotliDecoderDecompressStream(state: *BrotliDecoderState, available_in: *usize, next_in: *[*]const u8, available_out: *usize, next_out: *[*]u8, total_out: ?*usize) BrotliDecoderResult;
+pub extern fn BrotliDecoderDecompressStream(state: *BrotliDecoderState, available_in: *usize, next_in: *?[*]const u8, available_out: *usize, next_out: *?[*]u8, total_out: ?*usize) BrotliDecoderResult;
pub extern fn BrotliDecoderHasMoreOutput(state: *const BrotliDecoderState) c_int;
pub extern fn BrotliDecoderTakeOutput(state: *BrotliDecoderState, size: *usize) ?[*]const u8;
pub extern fn BrotliDecoderIsUsed(state: ?*const BrotliDecoderState) c_int;
diff --git a/src/stream_tester.zig b/src/stream_tester.zig
index a6912bd27..4ad4753cc 100644
--- a/src/stream_tester.zig
+++ b/src/stream_tester.zig
@@ -2,9 +2,66 @@ const compress = @import("./compress.zig");
pub const bun = @import("./bun.zig");
const std = @import("std");
+const Controller = compress.Controller;
+const Completion = compress.Completion;
+const Ownership = compress.Ownership;
+const Error = compress.Error;
+
+pub const CLIFileStreamCompressor = struct {
+ input: std.fs.File,
+ output: std.fs.File,
+ closed: bool = false,
+
+ ready_for_more: bool = false,
+ has_more_output: bool = true,
+
+ pub fn controller(this: *CLIFileStreamCompressor) Controller {
+ return Controller.init(*CLIFileStreamCompressor, this);
+ }
+
+ pub fn onData(this: *CLIFileStreamCompressor, bytes: []const u8, _: Ownership, completion: Completion) void {
+ std.debug.assert(!this.closed);
+ this.output.writeAll(bytes) catch @panic("failed to write to file");
+ if (completion == Completion.last) {
+ this.ready_for_more = false;
+ }
+ }
+
+ pub fn onError(this: *CLIFileStreamCompressor, err: Error) void {
+ _ = err;
+ std.debug.assert(!this.closed);
+ // std.debug.panic("Error: {}\n{}", .{ err.code, err.message });
+ }
+
+ pub fn onPull(this: *CLIFileStreamCompressor) void {
+ this.ready_for_more = true;
+ }
+
+ pub fn init(path: []const u8) !CLIFileStreamCompressor {
+ var file = try std.fs.cwd().openFile(path, .{ .mode = .read_write });
+ return CLIFileStreamCompressor{ .input = file, .output = std.io.getStdOut() };
+ }
+
+ pub fn run(this: *CLIFileStreamCompressor, stream: *compress.Compressor) !void {
+ this.ready_for_more = true;
+ const ctrl = this.controller();
+
+ while (this.has_more_output) {
+ var buffer: [64 * 1024]u8 = undefined;
+ var to_read: []const u8 = buffer[0..try this.input.readAll(&buffer)];
+ this.has_more_output = to_read.len != 0;
+ if (this.has_more_output) {
+ stream.write(to_read, ctrl);
+ }
+ }
+
+ stream.end(ctrl);
+ }
+};
+
pub fn main() anyerror!void {
const path: []const u8 = std.mem.span(std.os.argv[std.os.argv.len - 1]);
- var file_stream = try compress.CLIFileStreamCompressor.init(path);
+ var file_stream = try CLIFileStreamCompressor.init(path);
var stream: *compress.Compressor = if (bun.strings.endsWith(path, ".br"))
try compress.Compressor.init(compress.Brotli.Decoder.initWithoutOptions())
else