const std = @import("std"); const gcat = @import("gatorcat"); const Writer = @This(); const assert = std.debug.assert; interface: std.Io.Writer, socket: gcat.nic.RawSocket, alloc: std.mem.Allocator, fn drain(io_w: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize { const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w)); const buffered = io_w.buffered(); var res: usize = 0; if (buffered.len > 0) { w.socket.linkLayer().send(buffered) catch return error.WriteFailed; _ = io_w.consumeAll(); } for (data[0 .. data.len - 1]) |d| { w.socket.linkLayer().send(d) catch return error.WriteFailed; res += d.len; } if (splat > 0 and data[data.len - 1].len > 0) { var splatBuffer: std.ArrayList(u8) = .empty; defer splatBuffer.deinit(w.alloc); for (0..splat) |_| { splatBuffer.appendSlice(w.alloc, data[data.len - 1]) catch return error.WriteFailed; } w.socket.linkLayer().send(splatBuffer.items) catch return error.WriteFailed; } return res; } pub fn init(interface_name: [:0]const u8, buffer: []u8, alloc: std.mem.Allocator) !Writer { return .{ .interface = .{ .vtable = &.{ .drain = drain }, .buffer = buffer, }, .socket = try .init(interface_name), .alloc = alloc, }; }