| ... | @@ -2104,7 +2104,6 @@ pub const Stream = struct { | ... | @@ -2104,7 +2104,6 @@ pub const Stream = struct { |
| 2104 | fn drain(io_w: *io.Writer, data: []const []const u8, splat: usize) io.Writer.Error!usize { | 2104 | fn drain(io_w: *io.Writer, data: []const []const u8, splat: usize) io.Writer.Error!usize { |
| 2105 | const w: *Writer = @fieldParentPtr("interface", io_w); | 2105 | const w: *Writer = @fieldParentPtr("interface", io_w); |
| 2106 | const buffered = io_w.buffered(); | 2106 | const buffered = io_w.buffered(); |
| 2107 | var splat_buffer: [splat_buffer_len]u8 = undefined; | | |
| 2108 | var iovecs: [max_buffers_len]std.posix.iovec_const = undefined; | 2107 | var iovecs: [max_buffers_len]std.posix.iovec_const = undefined; |
| 2109 | var msg: posix.msghdr_const = msg: { | 2108 | var msg: posix.msghdr_const = msg: { |
| 2110 | var i: usize = 0; | 2109 | var i: usize = 0; |
| ... | @@ -2115,7 +2114,7 @@ pub const Stream = struct { | ... | @@ -2115,7 +2114,7 @@ pub const Stream = struct { |
| 2115 | }; | 2114 | }; |
| 2116 | i += 1; | 2115 | i += 1; |
| 2117 | } | 2116 | } |
| 2118 | for (data[0..data.len]) |bytes| { | 2117 | for (data) |bytes| { |
| 2119 | // OS checks ptr addr before length so zero length vectors must be omitted. | 2118 | // OS checks ptr addr before length so zero length vectors must be omitted. |
| 2120 | if (bytes.len == 0) continue; | 2119 | if (bytes.len == 0) continue; |
| 2121 | iovecs[i] = .{ | 2120 | iovecs[i] = .{ |
| ... | @@ -2135,38 +2134,48 @@ pub const Stream = struct { | ... | @@ -2135,38 +2134,48 @@ pub const Stream = struct { |
| 2135 | .flags = 0, | 2134 | .flags = 0, |
| 2136 | }; | 2135 | }; |
| 2137 | }; | 2136 | }; |
| 2138 | const pattern = data[data.len - 1]; | 2137 | if (data.len != 0) { |
| 2139 | switch (splat) { | 2138 | const pattern = data[data.len - 1]; |
| 2140 | 0 => msg.iovlen -= 1, | 2139 | switch (splat) { |
| 2141 | 1 => {}, | 2140 | 0 => if (msg.iovlen != 0 and iovecs[msg.iovlen - 1].base == data[data.len - 1].ptr) { |
| 2142 | else => switch (pattern.len) { | 2141 | msg.iovlen -= 1; |
| 2143 | 0 => {}, | 2142 | }, |
| 2144 | 1 => { | 2143 | 1 => {}, |
| 2145 | // Replace the 1-byte buffer with a bigger one. | 2144 | else => switch (pattern.len) { |
| 2146 | const memset_len = @min(splat_buffer.len, splat); | 2145 | 0 => {}, |
| 2147 | const buf = splat_buffer[0..memset_len]; | 2146 | 1 => memset: { |
| 2148 | @memset(buf, pattern[0]); | 2147 | // Replace the 1-byte buffer with a bigger one. |
| 2149 | iovecs[msg.iovlen - 1] = .{ .base = buf.ptr, .len = buf.len }; | 2148 | if (msg.iovlen != 0 and iovecs[msg.iovlen - 1].base == data[data.len - 1].ptr) |
| 2150 | var remaining_splat = splat - buf.len; | 2149 | msg.iovlen -= 1; |
| 2151 | while (remaining_splat > splat_buffer.len and msg.iovlen < iovecs.len) { | 2150 | if (iovecs.len - msg.iovlen == 0) break :memset; |
| 2152 | iovecs[msg.iovlen] = .{ .base = &splat_buffer, .len = splat_buffer.len }; | 2151 | const splat_buffer = io_w.buffer[io_w.end..]; |
| 2153 | remaining_splat -= splat_buffer.len; | 2152 | const memset_len = @min(splat_buffer.len, splat); |
| | 2153 | const buf = splat_buffer[0..memset_len]; |
| | 2154 | @memset(buf, pattern[0]); |
| | 2155 | iovecs[msg.iovlen] = .{ .base = buf.ptr, .len = buf.len }; |
| 2154 | msg.iovlen += 1; | 2156 | msg.iovlen += 1; |
| 2155 | } | 2157 | var remaining_splat = splat - buf.len; |
| 2156 | if (remaining_splat > 0 and msg.iovlen < iovecs.len) { | 2158 | while (remaining_splat > splat_buffer.len and iovecs.len - msg.iovlen != 0) { |
| 2157 | iovecs[msg.iovlen] = .{ .base = &splat_buffer, .len = remaining_splat }; | 2159 | assert(buf.len == splat_buffer.len); |
| | 2160 | iovecs[msg.iovlen] = .{ .base = splat_buffer.ptr, .len = splat_buffer.len }; |
| | 2161 | msg.iovlen += 1; |
| | 2162 | remaining_splat -= splat_buffer.len; |
| | 2163 | } |
| | 2164 | if (remaining_splat > 0 and iovecs.len - msg.iovlen != 0) { |
| | 2165 | iovecs[msg.iovlen] = .{ .base = splat_buffer.ptr, .len = remaining_splat }; |
| | 2166 | msg.iovlen += 1; |
| | 2167 | } |
| | 2168 | }, |
| | 2169 | else => for (0..splat - 1) |_| { |
| | 2170 | if (iovecs.len - msg.iovlen == 0) break; |
| | 2171 | iovecs[msg.iovlen] = .{ |
| | 2172 | .base = pattern.ptr, |
| | 2173 | .len = pattern.len, |
| | 2174 | }; |
| 2158 | msg.iovlen += 1; | 2175 | msg.iovlen += 1; |
| 2159 | } | 2176 | }, |
| 2160 | }, | 2177 | }, |
| 2161 | else => for (0..splat - 1) |_| { | 2178 | } |
| 2162 | if (iovecs.len - msg.iovlen == 0) break; | | |
| 2163 | iovecs[msg.iovlen] = .{ | | |
| 2164 | .base = pattern.ptr, | | |
| 2165 | .len = pattern.len, | | |
| 2166 | }; | | |
| 2167 | msg.iovlen += 1; | | |
| 2168 | }, | | |
| 2169 | }, | | |
| 2170 | } | 2179 | } |
| 2171 | const flags = posix.MSG.NOSIGNAL; | 2180 | const flags = posix.MSG.NOSIGNAL; |
| 2172 | return io_w.consume(std.posix.sendmsg(w.file_writer.file.handle, &msg, flags) catch |err| { | 2181 | return io_w.consume(std.posix.sendmsg(w.file_writer.file.handle, &msg, flags) catch |err| { |