Files
bun.sh/src/io/source.zig
2024-02-20 20:07:06 -03:00

155 lines
4.4 KiB
Zig

const std = @import("std");
const bun = @import("root").bun;
const uv = bun.windows.libuv;
const log = bun.Output.scoped(.PipeSource, false);
pub const Source = union(enum) {
pipe: *Pipe,
tty: *Tty,
file: *File,
const Pipe = uv.Pipe;
const Tty = uv.uv_tty_t;
pub const File = struct {
fs: uv.fs_t,
iov: uv.uv_buf_t,
file: uv.uv_file,
};
pub fn isClosed(this: Source) bool {
switch (this) {
.pipe => |pipe| return pipe.isClosed(),
.tty => |tty| return tty.isClosed(),
.file => |file| return file.file == -1,
}
}
pub fn isActive(this: Source) bool {
switch (this) {
.pipe => |pipe| return pipe.isActive(),
.tty => |tty| return tty.isActive(),
.file => return true,
}
}
pub fn getHandle(this: Source) *uv.Handle {
switch (this) {
.pipe => return @ptrCast(this.pipe),
.tty => return @ptrCast(this.tty),
.file => unreachable,
}
}
pub fn toStream(this: Source) *uv.uv_stream_t {
switch (this) {
.pipe => return @ptrCast(this.pipe),
.tty => return @ptrCast(this.tty),
.file => unreachable,
}
}
pub fn getFd(this: Source) bun.FileDescriptor {
switch (this) {
.pipe => return this.pipe.fd(),
.tty => return this.tty.fd(),
.file => return bun.FDImpl.fromUV(this.file.file).encode(),
}
}
pub fn setData(this: Source, data: ?*anyopaque) void {
switch (this) {
.pipe => this.pipe.data = data,
.tty => this.tty.data = data,
.file => this.file.fs.data = data,
}
}
pub fn getData(this: Source) ?*anyopaque {
switch (this) {
.pipe => |pipe| return pipe.data,
.tty => |tty| return tty.data,
.file => |file| return file.fs.data,
}
}
pub fn ref(this: Source) void {
switch (this) {
.pipe => this.pipe.ref(),
.tty => this.tty.ref(),
.file => return,
}
}
pub fn unref(this: Source) void {
switch (this) {
.pipe => this.pipe.unref(),
.tty => this.tty.unref(),
.file => return,
}
}
pub fn hasRef(this: Source) bool {
switch (this) {
.pipe => return this.pipe.hasRef(),
.tty => return this.tty.hasRef(),
.file => return false,
}
}
pub fn openPipe(loop: *uv.Loop, fd: bun.FileDescriptor, ipc: bool) bun.JSC.Maybe(*Source.Pipe) {
log("openPipe (fd = {})", .{fd});
const pipe = bun.default_allocator.create(Source.Pipe) catch bun.outOfMemory();
switch (pipe.init(loop, ipc)) {
.err => |err| {
return .{ .err = err };
},
else => {},
}
const file_fd = bun.uvfdcast(fd);
return switch (pipe.open(file_fd)) {
.err => |err| .{
.err = err,
},
.result => .{
.result = pipe,
},
};
}
pub fn openTty(loop: *uv.Loop, fd: bun.FileDescriptor) bun.JSC.Maybe(*Source.Tty) {
log("openTTY (fd = {})", .{fd});
const tty = bun.default_allocator.create(Source.Tty) catch bun.outOfMemory();
return switch (tty.init(loop, bun.uvfdcast(fd))) {
.err => |err| .{ .err = err },
.result => .{ .result = tty },
};
}
pub fn openFile(fd: bun.FileDescriptor) bun.JSC.Maybe(*Source.File) {
log("openFile (fd = {})", .{fd});
const file = bun.default_allocator.create(Source.File) catch bun.outOfMemory();
file.* = std.mem.zeroes(Source.File);
file.file = bun.uvfdcast(fd);
return .{ .result = file };
}
pub fn open(loop: *uv.Loop, fd: bun.FileDescriptor) bun.JSC.Maybe(Source) {
log("open (fd = {})", .{fd});
const rc = bun.windows.GetFileType(fd.cast());
if (rc == bun.windows.FILE_TYPE_CHAR) .{ .tty = switch (openTty(loop, fd)) {
.result => |tty| return .{ .result = .{ .tty = tty } },
.err => |err| return .{ .err = err },
} } else .{
.file = switch (openFile(fd)) {
.result => |file| return .{ .result = .{ .file = file } },
.err => |err| return .{ .err = err },
},
};
}
};