Function drain [src]

Prototype

pub fn drain(io_w: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize

Parameters

io_w: *std.Io.Writerdata: []const []const u8splat: usize

Source

pub 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 handle = w.file.handle; const buffered = io_w.buffered(); if (is_windows) switch (w.mode) { .positional, .positional_reading => { if (buffered.len != 0) { const n = windows.WriteFile(handle, buffered, w.pos) catch |err| { w.err = err; return error.WriteFailed; }; w.pos += n; return io_w.consume(n); } for (data[0 .. data.len - 1]) |buf| { if (buf.len == 0) continue; const n = windows.WriteFile(handle, buf, w.pos) catch |err| { w.err = err; return error.WriteFailed; }; w.pos += n; return io_w.consume(n); } const pattern = data[data.len - 1]; if (pattern.len == 0 or splat == 0) return 0; const n = windows.WriteFile(handle, pattern, w.pos) catch |err| { w.err = err; return error.WriteFailed; }; w.pos += n; return io_w.consume(n); }, .streaming, .streaming_reading => { if (buffered.len != 0) { const n = windows.WriteFile(handle, buffered, null) catch |err| { w.err = err; return error.WriteFailed; }; w.pos += n; return io_w.consume(n); } for (data[0 .. data.len - 1]) |buf| { if (buf.len == 0) continue; const n = windows.WriteFile(handle, buf, null) catch |err| { w.err = err; return error.WriteFailed; }; w.pos += n; return io_w.consume(n); } const pattern = data[data.len - 1]; if (pattern.len == 0 or splat == 0) return 0; const n = windows.WriteFile(handle, pattern, null) catch |err| { w.err = err; return error.WriteFailed; }; w.pos += n; return io_w.consume(n); }, .failure => return error.WriteFailed, }; var iovecs: [max_buffers_len]std.posix.iovec_const = undefined; var len: usize = 0; if (buffered.len > 0) { iovecs[len] = .{ .base = buffered.ptr, .len = buffered.len }; len += 1; } for (data[0 .. data.len - 1]) |d| { if (d.len == 0) continue; iovecs[len] = .{ .base = d.ptr, .len = d.len }; len += 1; if (iovecs.len - len == 0) break; } const pattern = data[data.len - 1]; if (iovecs.len - len != 0) switch (splat) { 0 => {}, 1 => if (pattern.len != 0) { iovecs[len] = .{ .base = pattern.ptr, .len = pattern.len }; len += 1; }, else => switch (pattern.len) { 0 => {}, 1 => { const splat_buffer_candidate = io_w.buffer[io_w.end..]; var backup_buffer: [64]u8 = undefined; const splat_buffer = if (splat_buffer_candidate.len >= backup_buffer.len) splat_buffer_candidate else &backup_buffer; const memset_len = @min(splat_buffer.len, splat); const buf = splat_buffer[0..memset_len]; @memset(buf, pattern[0]); iovecs[len] = .{ .base = buf.ptr, .len = buf.len }; len += 1; var remaining_splat = splat - buf.len; while (remaining_splat > splat_buffer.len and iovecs.len - len != 0) { assert(buf.len == splat_buffer.len); iovecs[len] = .{ .base = splat_buffer.ptr, .len = splat_buffer.len }; len += 1; remaining_splat -= splat_buffer.len; } if (remaining_splat > 0 and iovecs.len - len != 0) { iovecs[len] = .{ .base = splat_buffer.ptr, .len = remaining_splat }; len += 1; } }, else => for (0..splat) |_| { iovecs[len] = .{ .base = pattern.ptr, .len = pattern.len }; len += 1; if (iovecs.len - len == 0) break; }, }, }; if (len == 0) return 0; switch (w.mode) { .positional, .positional_reading => { const n = std.posix.pwritev(handle, iovecs[0..len], w.pos) catch |err| switch (err) { error.Unseekable => { w.mode = w.mode.toStreaming(); const pos = w.pos; if (pos != 0) { w.pos = 0; w.seekTo(@intCast(pos)) catch { w.mode = .failure; return error.WriteFailed; }; } return 0; }, else => |e| { w.err = e; return error.WriteFailed; }, }; w.pos += n; return io_w.consume(n); }, .streaming, .streaming_reading => { const n = std.posix.writev(handle, iovecs[0..len]) catch |err| { w.err = err; return error.WriteFailed; }; w.pos += n; return io_w.consume(n); }, .failure => return error.WriteFailed, } }