diff options
Diffstat (limited to 'src/node_module_bundle.zig')
-rw-r--r-- | src/node_module_bundle.zig | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/node_module_bundle.zig b/src/node_module_bundle.zig new file mode 100644 index 000000000..11150f376 --- /dev/null +++ b/src/node_module_bundle.zig @@ -0,0 +1,69 @@ +const Api = @import("./api/schema.zig").Api; +const std = @import("std"); +usingnamespace @import("global.zig"); + +pub const NodeModuleBundle = struct { + container: *Api.JavascriptBundleContainer, + bundle: *Api.JavascriptBundle, + allocator: *std.mem.Allocator, + fd: FileDescriptorType = 0, + + pub const magic_bytes = "#!/usr/bin/env speedy\n\n"; + threadlocal var jsbundle_prefix: [magic_bytes.len + 5]u8 = undefined; + + pub fn getCodeEndPosition(stream: anytype, comptime needs_seek: bool) !u32 { + if (needs_seek) try stream.seekTo(0); + + const read_bytes = try stream.read(&jsbundle_prefix); + if (read_bytes != jsbundle_prefix.len) { + return error.JSBundleBadHeaderTooShort; + } + + return std.mem.readIntNative(u32, jsbundle_prefix[magic_bytes.len .. magic_bytes.len + 4]); + } + + pub fn loadBundle(allocator: *std.mem.Allocator, stream: anytype) !NodeModuleBundle { + const end = try getCodeEndPosition(stream); + try stream.seekTo(end + 1); + var reader = stream.reader(); + var container = try Api.JavascriptBundleContainer.decode(allocator, reader); + return NodeModuleBundle{ + .allocator = allocator, + .container = container, + .bundle = container.bundle, + .fd = if (std.meta.trait.hasField("handle")(stream)) stream.handle else 0, + }; + } + + pub fn printBundle( + comptime StreamType: type, + input: StreamType, + comptime DestinationStreamType: type, + output: DestinationStreamType, + ) !void { + const BufferStreamContext = struct { + pub fn run(in: StreamType, out: DestinationStreamType, end_at: u32) !void { + var buf: [4096]u8 = undefined; + var remain = @intCast(i64, end_at); + var read_amount: i64 = @intCast(i64, in.read(&buf) catch 0); + while (remain > 0 and read_amount > 0) { + remain -= @intCast(i64, try out.write(buf[0..@intCast(usize, std.math.min(read_amount, remain))])); + read_amount = @intCast(i64, in.read(&buf) catch 0); + } + + _ = try out.write(buf[0..@intCast(usize, remain + 1)]); + } + }; + if (isMac) { + // darwin only allows reading ahead on/off, not specific amount + _ = std.os.fcntl(input.handle, std.os.F_RDAHEAD, 1) catch 0; + } + const end = try getCodeEndPosition(input, false); + + try BufferStreamContext.run( + input, + output, + end, + ); + } +}; |