Skip to content

Commit adb70aa

Browse files
std.io: add AnyStream
- replace Reader `fn read(ctx, buffer: []u8)` with `readv(ctx, iovecs: []std.posix.iovec)` - replace Writer `fn write(ctx, buffer: []const u8)` with `writev(ctx, iovecs: []std.posix.iovec_const)`
1 parent 19b6995 commit adb70aa

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+754
-1159
lines changed

lib/std/array_list.zig

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
344344
@compileError("The Writer interface is only defined for ArrayList(u8) " ++
345345
"but the given type is ArrayList(" ++ @typeName(T) ++ ")")
346346
else
347-
std.io.Writer(*Self, Allocator.Error, appendWrite);
347+
std.io.Writer(*Self, Allocator.Error, appendWritev);
348348

349349
/// Initializes a Writer which will append to the list.
350350
pub fn writer(self: *Self) Writer {
@@ -354,9 +354,13 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
354354
/// Same as `append` except it returns the number of bytes written, which is always the same
355355
/// as `m.len`. The purpose of this function existing is to match `std.io.Writer` API.
356356
/// Invalidates element pointers if additional memory is needed.
357-
fn appendWrite(self: *Self, m: []const u8) Allocator.Error!usize {
358-
try self.appendSlice(m);
359-
return m.len;
357+
fn appendWritev(self: *Self, iov: []std.posix.iovec_const) Allocator.Error!usize {
358+
var written: usize = 0;
359+
for (iov) |v| {
360+
try self.appendSlice(v.iov_base[0..v.iov_len]);
361+
written += v.iov_len;
362+
}
363+
return written;
360364
}
361365

362366
/// Append a value to the list `n` times.
@@ -930,7 +934,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
930934
@compileError("The Writer interface is only defined for ArrayList(u8) " ++
931935
"but the given type is ArrayList(" ++ @typeName(T) ++ ")")
932936
else
933-
std.io.Writer(WriterContext, Allocator.Error, appendWrite);
937+
std.io.Writer(WriterContext, Allocator.Error, appendWritev);
934938

935939
/// Initializes a Writer which will append to the list.
936940
pub fn writer(self: *Self, allocator: Allocator) Writer {
@@ -941,12 +945,16 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
941945
/// which is always the same as `m.len`. The purpose of this function
942946
/// existing is to match `std.io.Writer` API.
943947
/// Invalidates element pointers if additional memory is needed.
944-
fn appendWrite(context: WriterContext, m: []const u8) Allocator.Error!usize {
945-
try context.self.appendSlice(context.allocator, m);
946-
return m.len;
948+
fn appendWritev(context: WriterContext, iov: []std.posix.iovec_const) Allocator.Error!usize {
949+
var written: usize = 0;
950+
for (iov) |v| {
951+
try context.self.appendSlice(context.allocator, v.iov_base[0..v.iov_len]);
952+
written += v.iov_len;
953+
}
954+
return written;
947955
}
948956

949-
pub const FixedWriter = std.io.Writer(*Self, Allocator.Error, appendWriteFixed);
957+
pub const FixedWriter = std.io.Writer(*Self, Allocator.Error, appendWritevFixed);
950958

951959
/// Initializes a Writer which will append to the list but will return
952960
/// `error.OutOfMemory` rather than increasing capacity.
@@ -955,13 +963,18 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
955963
}
956964

957965
/// The purpose of this function existing is to match `std.io.Writer` API.
958-
fn appendWriteFixed(self: *Self, m: []const u8) error{OutOfMemory}!usize {
959-
const available_capacity = self.capacity - self.items.len;
960-
if (m.len > available_capacity)
961-
return error.OutOfMemory;
962-
963-
self.appendSliceAssumeCapacity(m);
964-
return m.len;
966+
fn appendWritevFixed(self: *Self, iov: []std.posix.iovec_const) error{OutOfMemory}!usize {
967+
var written: usize = 0;
968+
for (iov) |v| {
969+
const m = v.iov_base[0..v.iov_len];
970+
const available_capacity = self.capacity - self.items.len;
971+
if (m.len > available_capacity)
972+
return error.OutOfMemory;
973+
974+
self.appendSliceAssumeCapacity(m);
975+
written += m.len;
976+
}
977+
return written;
965978
}
966979

967980
/// Append a value to the list `n` times.

lib/std/bounded_array.zig

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ pub fn BoundedArrayAligned(
271271
@compileError("The Writer interface is only defined for BoundedArray(u8, ...) " ++
272272
"but the given type is BoundedArray(" ++ @typeName(T) ++ ", ...)")
273273
else
274-
std.io.Writer(*Self, error{Overflow}, appendWrite);
274+
std.io.Writer(*Self, error{Overflow}, appendWritev);
275275

276276
/// Initializes a writer which will write into the array.
277277
pub fn writer(self: *Self) Writer {
@@ -280,9 +280,14 @@ pub fn BoundedArrayAligned(
280280

281281
/// Same as `appendSlice` except it returns the number of bytes written, which is always the same
282282
/// as `m.len`. The purpose of this function existing is to match `std.io.Writer` API.
283-
fn appendWrite(self: *Self, m: []const u8) error{Overflow}!usize {
284-
try self.appendSlice(m);
285-
return m.len;
283+
fn appendWritev(self: *Self, iov: []std.posix.iovec_const) error{Overflow}!usize {
284+
var written: usize = 0;
285+
for (iov) |v| {
286+
const m = v.iov_base[0..v.iov_len];
287+
try self.appendSlice(m);
288+
written += m.len;
289+
}
290+
return written;
286291
}
287292
};
288293
}

lib/std/compress.zig

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,18 @@ pub fn HashedReader(
1919
hasher: HasherType,
2020

2121
pub const Error = ReaderType.Error;
22-
pub const Reader = std.io.Reader(*@This(), Error, read);
22+
pub const Reader = std.io.Reader(*@This(), Error, readv);
2323

24-
pub fn read(self: *@This(), buf: []u8) Error!usize {
25-
const amt = try self.child_reader.read(buf);
26-
self.hasher.update(buf[0..amt]);
27-
return amt;
24+
pub fn readv(self: *@This(), iov: []std.posix.iovec) Error!usize {
25+
const n_read = try self.child_reader.readv(iov);
26+
var hashed_amt: usize = 0;
27+
for (iov) |v| {
28+
const to_hash = @min(n_read - hashed_amt, v.iov_len);
29+
if (to_hash == 0) break;
30+
self.hasher.update(v.iov_base[0..to_hash]);
31+
hashed_amt += to_hash;
32+
}
33+
return n_read;
2834
}
2935

3036
pub fn reader(self: *@This()) Reader {
@@ -51,10 +57,16 @@ pub fn HashedWriter(
5157
pub const Error = WriterType.Error;
5258
pub const Writer = std.io.Writer(*@This(), Error, write);
5359

54-
pub fn write(self: *@This(), buf: []const u8) Error!usize {
55-
const amt = try self.child_writer.write(buf);
56-
self.hasher.update(buf[0..amt]);
57-
return amt;
60+
pub fn write(self: *@This(), iov: []std.posix.iovec_const) Error!usize {
61+
const n_written = try self.child_writer.writev(iov);
62+
var hashed_amt: usize = 0;
63+
for (iov) |v| {
64+
const to_hash = @min(n_written - hashed_amt, v.iov_len);
65+
if (to_hash == 0) break;
66+
self.hasher.update(v.iov_base[0..to_hash]);
67+
hashed_amt += to_hash;
68+
}
69+
return n_written;
5870
}
5971

6072
pub fn writer(self: *@This()) Writer {

lib/std/compress/flate/deflate.zig

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -354,16 +354,20 @@ fn Deflate(comptime container: Container, comptime WriterType: type, comptime Bl
354354
}
355355

356356
// Writer interface
357-
358-
pub const Writer = io.Writer(*Self, Error, write);
357+
pub const Writer = io.Writer(*Self, Error, writev);
359358
pub const Error = BlockWriterType.Error;
360359

361360
/// Write `input` of uncompressed data.
362361
/// See compress.
363-
pub fn write(self: *Self, input: []const u8) !usize {
364-
var fbs = io.fixedBufferStream(input);
365-
try self.compress(fbs.reader());
366-
return input.len;
362+
pub fn writev(self: *Self, iov: []std.posix.iovec_const) !usize {
363+
var written: usize = 0;
364+
for (iov) |v| {
365+
const input = v.iov_base[0..v.iov_len];
366+
var fbs = io.fixedBufferStream(input);
367+
try self.compress(fbs.reader());
368+
written += input.len;
369+
}
370+
return written;
367371
}
368372

369373
pub fn writer(self: *Self) Writer {
@@ -558,7 +562,7 @@ test "tokenization" {
558562
const cww = cw.writer();
559563
var df = try Deflate(container, @TypeOf(cww), TestTokenWriter).init(cww, .{});
560564

561-
_ = try df.write(c.data);
565+
_ = try df.writer().write(c.data);
562566
try df.flush();
563567

564568
// df.token_writer.show();
@@ -579,6 +583,8 @@ const TestTokenWriter = struct {
579583
pos: usize = 0,
580584
actual: [128]Token = undefined,
581585

586+
pub const Error = error{};
587+
582588
pub fn init(_: anytype) Self {
583589
return .{};
584590
}

lib/std/compress/flate/inflate.zig

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ pub fn Inflate(comptime container: Container, comptime LookaheadType: type, comp
325325
/// Returns decompressed data from internal sliding window buffer.
326326
/// Returned buffer can be any length between 0 and `limit` bytes. 0
327327
/// returned bytes means end of stream reached. With limit=0 returns as
328-
/// much data it can. It newer will be more than 65536 bytes, which is
328+
/// much data it can. It never will be more than 65536 bytes, which is
329329
/// size of internal buffer.
330330
pub fn get(self: *Self, limit: usize) Error![]const u8 {
331331
while (true) {
@@ -340,16 +340,19 @@ pub fn Inflate(comptime container: Container, comptime LookaheadType: type, comp
340340
}
341341

342342
// Reader interface
343-
344-
pub const Reader = std.io.Reader(*Self, Error, read);
343+
pub const Reader = std.io.Reader(*Self, Error, readv);
345344

346345
/// Returns the number of bytes read. It may be less than buffer.len.
347346
/// If the number of bytes read is 0, it means end of stream.
348347
/// End of stream is not an error condition.
349-
pub fn read(self: *Self, buffer: []u8) Error!usize {
350-
const out = try self.get(buffer.len);
351-
@memcpy(buffer[0..out.len], out);
352-
return out.len;
348+
pub fn readv(self: *Self, iov: []std.posix.iovec) Error!usize {
349+
var read: usize = 0;
350+
for (iov) |v| {
351+
const out = try self.get(v.iov_len);
352+
@memcpy(v.iov_base[0..out.len], out);
353+
read += out.len;
354+
}
355+
return read;
353356
}
354357

355358
pub fn reader(self: *Self) Reader {

lib/std/compress/lzma.zig

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub fn Decompress(comptime ReaderType: type) type {
3030
Allocator.Error ||
3131
error{ CorruptInput, EndOfStream, Overflow };
3232

33-
pub const Reader = std.io.Reader(*Self, Error, read);
33+
pub const Reader = std.io.Reader(*Self, Error, readv);
3434

3535
allocator: Allocator,
3636
in_reader: ReaderType,
@@ -63,23 +63,28 @@ pub fn Decompress(comptime ReaderType: type) type {
6363
self.* = undefined;
6464
}
6565

66-
pub fn read(self: *Self, output: []u8) Error!usize {
66+
pub fn readv(self: *Self, iov: []std.posix.iovec) Error!usize {
6767
const writer = self.to_read.writer(self.allocator);
68-
while (self.to_read.items.len < output.len) {
69-
switch (try self.state.process(self.allocator, self.in_reader, writer, &self.buffer, &self.decoder)) {
70-
.continue_ => {},
71-
.finished => {
72-
try self.buffer.finish(writer);
73-
break;
74-
},
68+
var n_read: usize = 0;
69+
for (iov) |v| {
70+
const output = v.iov_base[0..v.iov_len];
71+
while (self.to_read.items.len < output.len) {
72+
switch (try self.state.process(self.allocator, self.in_reader, writer, &self.buffer, &self.decoder)) {
73+
.continue_ => {},
74+
.finished => {
75+
try self.buffer.finish(writer);
76+
break;
77+
},
78+
}
7579
}
80+
const input = self.to_read.items;
81+
const n = @min(input.len, output.len);
82+
@memcpy(output[0..n], input[0..n]);
83+
@memcpy(input[0 .. input.len - n], input[n..]);
84+
self.to_read.shrinkRetainingCapacity(input.len - n);
85+
n_read += n;
7686
}
77-
const input = self.to_read.items;
78-
const n = @min(input.len, output.len);
79-
@memcpy(output[0..n], input[0..n]);
80-
@memcpy(input[0 .. input.len - n], input[n..]);
81-
self.to_read.shrinkRetainingCapacity(input.len - n);
82-
return n;
87+
return n_read;
8388
}
8489
};
8590
}

lib/std/compress/xz.zig

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub fn Decompress(comptime ReaderType: type) type {
3434
const Self = @This();
3535

3636
pub const Error = ReaderType.Error || block.Decoder(ReaderType).Error;
37-
pub const Reader = std.io.Reader(*Self, Error, read);
37+
pub const Reader = std.io.Reader(*Self, Error, readv);
3838

3939
allocator: Allocator,
4040
block_decoder: block.Decoder(ReaderType),
@@ -71,7 +71,10 @@ pub fn Decompress(comptime ReaderType: type) type {
7171
return .{ .context = self };
7272
}
7373

74-
pub fn read(self: *Self, buffer: []u8) Error!usize {
74+
pub fn readv(self: *Self, iov: []std.posix.iovec) Error!usize {
75+
if (iov.len == 0) return 0;
76+
const first = iov[0];
77+
const buffer = first.iov_base[0..first.iov_len];
7578
if (buffer.len == 0)
7679
return 0;
7780

lib/std/compress/zstandard.zig

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub fn Decompressor(comptime ReaderType: type) type {
5050
OutOfMemory,
5151
};
5252

53-
pub const Reader = std.io.Reader(*Self, Error, read);
53+
pub const Reader = std.io.Reader(*Self, Error, readv);
5454

5555
pub fn init(source: ReaderType, options: DecompressorOptions) Self {
5656
return .{
@@ -105,7 +105,10 @@ pub fn Decompressor(comptime ReaderType: type) type {
105105
return .{ .context = self };
106106
}
107107

108-
pub fn read(self: *Self, buffer: []u8) Error!usize {
108+
pub fn readv(self: *Self, iov: []std.posix.iovec) Error!usize {
109+
if (iov.len == 0) return 0;
110+
const first = iov[0];
111+
const buffer = first.iov_base[0..first.iov_len];
109112
if (buffer.len == 0) return 0;
110113

111114
var size: usize = 0;

lib/std/compress/zstandard/readers.zig

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pub const ReversedByteReader = struct {
44
remaining_bytes: usize,
55
bytes: []const u8,
66

7-
const Reader = std.io.Reader(*ReversedByteReader, error{}, readFn);
7+
const Reader = std.io.Reader(*ReversedByteReader, error{}, readvFn);
88

99
pub fn init(bytes: []const u8) ReversedByteReader {
1010
return .{
@@ -17,7 +17,11 @@ pub const ReversedByteReader = struct {
1717
return .{ .context = self };
1818
}
1919

20-
fn readFn(ctx: *ReversedByteReader, buffer: []u8) !usize {
20+
fn readvFn(ctx: *ReversedByteReader, iov: []std.posix.iovec) !usize {
21+
if (iov.len == 0) return 0;
22+
const first = iov[0];
23+
const buffer = first.iov_base[0..first.iov_len];
24+
std.debug.assert(buffer.len > 0);
2125
if (ctx.remaining_bytes == 0) return 0;
2226
const byte_index = ctx.remaining_bytes - 1;
2327
buffer[0] = ctx.bytes[byte_index];

lib/std/crypto/sha2.zig

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,11 +392,15 @@ fn Sha2x32(comptime params: Sha2Params32) type {
392392
}
393393

394394
pub const Error = error{};
395-
pub const Writer = std.io.Writer(*Self, Error, write);
395+
pub const Writer = std.io.Writer(*Self, Error, writev);
396396

397-
fn write(self: *Self, bytes: []const u8) Error!usize {
398-
self.update(bytes);
399-
return bytes.len;
397+
fn writev(self: *Self, iov: []std.posix.iovec_const) Error!usize {
398+
var written: usize = 0;
399+
for (iov) |v| {
400+
self.update(v.iov_base[0..v.iov_len]);
401+
written += v.iov_len;
402+
}
403+
return written;
400404
}
401405

402406
pub fn writer(self: *Self) Writer {

lib/std/crypto/siphash.zig

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,11 +240,15 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
240240
}
241241

242242
pub const Error = error{};
243-
pub const Writer = std.io.Writer(*Self, Error, write);
243+
pub const Writer = std.io.Writer(*Self, Error, writev);
244244

245-
fn write(self: *Self, bytes: []const u8) Error!usize {
246-
self.update(bytes);
247-
return bytes.len;
245+
fn writev(self: *Self, iov: []std.posix.iovec_const) Error!usize {
246+
var written: usize = 0;
247+
for (iov) |v| {
248+
self.update(v.iov_base[0..v.iov_len]);
249+
written += v.iov_len;
250+
}
251+
return written;
248252
}
249253

250254
pub fn writer(self: *Self) Writer {

0 commit comments

Comments
 (0)