const std = @import("std"); const Io = std.Io; const uefi = std.os.uefi; const Writer = @This(); interface: Io.Writer, protocol: *uefi.protocol.SimpleTextOutput, pub fn init(buffer: []u8, protocol: *uefi.protocol.SimpleTextOutput) Writer { return .{ .protocol = protocol, .interface = .{ .buffer = buffer, .vtable = &.{ .drain = drainFn }, }, }; } pub fn stdout() Writer { return .init(&.{}, uefi.system_table.con_out.?); } pub fn stderr() Writer { return .init(&.{}, uefi.system_table.std_err.?); } pub fn write(self: *Writer, data: []const u8) !void { var buffer: [64:0]u16 = undefined; var buflen: usize = 0; for (data) |b| { buffer[buflen] = @intCast(b); buflen += 1; if (buflen == buffer.len) { _ = self.protocol.outputString(&buffer) catch unreachable; buflen = 0; } } if (buflen > 0) { buffer[buflen] = 0; _ = self.protocol.outputString(buffer[0..buflen :0]) catch unreachable; } } fn drainFn(io_w: *Io.Writer, data: []const []const u8, splat: usize) Io.Writer.Error!usize { const self: *Writer = @fieldParentPtr("interface", io_w); { const buf = io_w.buffered(); if (buf.len > 0) { try self.write(buf); _ = io_w.consumeAll(); } } var written: usize = 0; if (data.len > 1) { for (data[0 .. data.len - 1]) |buf| { try self.write(buf); written += buf.len; } } const buf = data[data.len - 1]; for (0..splat) |_| { try self.write(buf); written += buf.len; } return written; }