Skip to content
2 changes: 1 addition & 1 deletion lib/compiler/objcopy.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1285,7 +1285,7 @@ const ElfFileHelper = struct {
for (consolidated.items) |cmd| {
switch (cmd) {
.write_data => |data| {
var iovec = [_]std.posix.iovec_const{.{ .iov_base = data.data.ptr, .iov_len = data.data.len }};
var iovec = [_]std.io.WriteBuffers{.{ .ptr = data.data.ptr, .len = data.data.len }};
try out_file.pwritevAll(&iovec, data.out_offset);
},
.copy_range => |range| {
Expand Down
45 changes: 29 additions & 16 deletions lib/std/array_list.zig
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
@compileError("The Writer interface is only defined for ArrayList(u8) " ++
"but the given type is ArrayList(" ++ @typeName(T) ++ ")")
else
std.io.Writer(*Self, Allocator.Error, appendWrite);
std.io.Writer(*Self, Allocator.Error, appendWritev);

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

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

/// Initializes a Writer which will append to the list.
pub fn writer(self: *Self, allocator: Allocator) Writer {
Expand All @@ -941,12 +945,16 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// which is always the same as `m.len`. The purpose of this function
/// existing is to match `std.io.Writer` API.
/// Invalidates element pointers if additional memory is needed.
fn appendWrite(context: WriterContext, m: []const u8) Allocator.Error!usize {
try context.self.appendSlice(context.allocator, m);
return m.len;
fn appendWritev(context: WriterContext, iov: []std.io.WriteBuffers) Allocator.Error!usize {
var written: usize = 0;
for (iov) |v| {
try context.self.appendSlice(context.allocator, v.ptr[0..v.len]);
written += v.len;
}
return written;
}

pub const FixedWriter = std.io.Writer(*Self, Allocator.Error, appendWriteFixed);
pub const FixedWriter = std.io.Writer(*Self, Allocator.Error, appendWritevFixed);

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

/// The purpose of this function existing is to match `std.io.Writer` API.
fn appendWriteFixed(self: *Self, m: []const u8) error{OutOfMemory}!usize {
const available_capacity = self.capacity - self.items.len;
if (m.len > available_capacity)
return error.OutOfMemory;

self.appendSliceAssumeCapacity(m);
return m.len;
fn appendWritevFixed(self: *Self, iov: []std.io.WriteBuffers) error{OutOfMemory}!usize {
var written: usize = 0;
for (iov) |v| {
const m = v.ptr[0..v.len];
const available_capacity = self.capacity - self.items.len;
if (m.len > available_capacity)
return error.OutOfMemory;

self.appendSliceAssumeCapacity(m);
written += m.len;
}
return written;
}

/// Append a value to the list `n` times.
Expand Down
13 changes: 9 additions & 4 deletions lib/std/bounded_array.zig
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ pub fn BoundedArrayAligned(
@compileError("The Writer interface is only defined for BoundedArray(u8, ...) " ++
"but the given type is BoundedArray(" ++ @typeName(T) ++ ", ...)")
else
std.io.Writer(*Self, error{Overflow}, appendWrite);
std.io.Writer(*Self, error{Overflow}, appendWritev);

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

/// Same as `appendSlice` except it returns the number of bytes written, which is always the same
/// as `m.len`. The purpose of this function existing is to match `std.io.Writer` API.
fn appendWrite(self: *Self, m: []const u8) error{Overflow}!usize {
try self.appendSlice(m);
return m.len;
fn appendWritev(self: *Self, iov: []std.io.WriteBuffers) error{Overflow}!usize {
var written: usize = 0;
for (iov) |v| {
const m = v.ptr[0..v.len];
try self.appendSlice(m);
written += m.len;
}
return written;
}
};
}
Expand Down
4 changes: 2 additions & 2 deletions lib/std/c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ const std = @import("std");
const builtin = @import("builtin");
const c = @This();
const page_size = std.mem.page_size;
const iovec = std.posix.iovec;
const iovec_const = std.posix.iovec_const;
const iovec = std.io.ReadBuffers;
const iovec_const = std.io.WriteBuffers;
const wasi = @import("c/wasi.zig");
const native_abi = builtin.abi;
const native_arch = builtin.cpu.arch;
Expand Down
30 changes: 21 additions & 9 deletions lib/std/compress.zig
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,18 @@ pub fn HashedReader(
hasher: HasherType,

pub const Error = ReaderType.Error;
pub const Reader = std.io.Reader(*@This(), Error, read);
pub const Reader = std.io.Reader(*@This(), Error, readv);

pub fn read(self: *@This(), buf: []u8) Error!usize {
const amt = try self.child_reader.read(buf);
self.hasher.update(buf[0..amt]);
return amt;
pub fn readv(self: *@This(), iov: []std.io.ReadBuffers) Error!usize {
const n_read = try self.child_reader.readv(iov);
var hashed_amt: usize = 0;
for (iov) |v| {
const to_hash = @min(n_read - hashed_amt, v.len);
if (to_hash == 0) break;
self.hasher.update(v.ptr[0..to_hash]);
hashed_amt += to_hash;
}
return n_read;
}

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

pub fn write(self: *@This(), buf: []const u8) Error!usize {
const amt = try self.child_writer.write(buf);
self.hasher.update(buf[0..amt]);
return amt;
pub fn write(self: *@This(), iov: []std.io.WriteBuffers) Error!usize {
const n_written = try self.child_writer.writev(iov);
var hashed_amt: usize = 0;
for (iov) |v| {
const to_hash = @min(n_written - hashed_amt, v.len);
if (to_hash == 0) break;
self.hasher.update(v.ptr[0..to_hash]);
hashed_amt += to_hash;
}
return n_written;
}

pub fn writer(self: *@This()) Writer {
Expand Down
20 changes: 13 additions & 7 deletions lib/std/compress/flate/deflate.zig
Original file line number Diff line number Diff line change
Expand Up @@ -354,16 +354,20 @@ fn Deflate(comptime container: Container, comptime WriterType: type, comptime Bl
}

// Writer interface

pub const Writer = io.Writer(*Self, Error, write);
pub const Writer = io.Writer(*Self, Error, writev);
pub const Error = BlockWriterType.Error;

/// Write `input` of uncompressed data.
/// See compress.
pub fn write(self: *Self, input: []const u8) !usize {
var fbs = io.fixedBufferStream(input);
try self.compress(fbs.reader());
return input.len;
pub fn writev(self: *Self, iov: []std.io.WriteBuffers) !usize {
var written: usize = 0;
for (iov) |v| {
const input = v.ptr[0..v.len];
var fbs = io.fixedBufferStream(input);
try self.compress(fbs.reader());
written += input.len;
}
return written;
}

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

_ = try df.write(c.data);
_ = try df.writer().write(c.data);
try df.flush();

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

pub const Error = error{};

pub fn init(_: anytype) Self {
return .{};
}
Expand Down
8 changes: 5 additions & 3 deletions lib/std/compress/flate/inflate.zig
Original file line number Diff line number Diff line change
Expand Up @@ -340,13 +340,15 @@ pub fn Inflate(comptime container: Container, comptime LookaheadType: type, comp
}

// Reader interface

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

/// Returns the number of bytes read. It may be less than buffer.len.
/// If the number of bytes read is 0, it means end of stream.
/// End of stream is not an error condition.
pub fn read(self: *Self, buffer: []u8) Error!usize {
pub fn readv(self: *Self, iovecs: []std.io.ReadBuffers) Error!usize {
if (iovecs.len == 0) return 0;
const first = iovecs[0];
const buffer = first.ptr[0..first.len];
const out = try self.get(buffer.len);
@memcpy(buffer[0..out.len], out);
return out.len;
Expand Down
8 changes: 6 additions & 2 deletions lib/std/compress/lzma.zig
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub fn Decompress(comptime ReaderType: type) type {
Allocator.Error ||
error{ CorruptInput, EndOfStream, Overflow };

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

allocator: Allocator,
in_reader: ReaderType,
Expand Down Expand Up @@ -63,7 +63,11 @@ pub fn Decompress(comptime ReaderType: type) type {
self.* = undefined;
}

pub fn read(self: *Self, output: []u8) Error!usize {
pub fn readv(self: *Self, iovecs: []std.io.ReadBuffers) Error!usize {
if (iovecs.len == 0) return 0;
const first = iovecs[0];
const output = first.ptr[0..first.len];

const writer = self.to_read.writer(self.allocator);
while (self.to_read.items.len < output.len) {
switch (try self.state.process(self.allocator, self.in_reader, writer, &self.buffer, &self.decoder)) {
Expand Down
7 changes: 5 additions & 2 deletions lib/std/compress/xz.zig
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub fn Decompress(comptime ReaderType: type) type {
const Self = @This();

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

allocator: Allocator,
block_decoder: block.Decoder(ReaderType),
Expand Down Expand Up @@ -71,7 +71,10 @@ pub fn Decompress(comptime ReaderType: type) type {
return .{ .context = self };
}

pub fn read(self: *Self, buffer: []u8) Error!usize {
pub fn readv(self: *Self, iov: []std.io.ReadBuffers) Error!usize {
if (iov.len == 0) return 0;
const first = iov[0];
const buffer = first.ptr[0..first.len];
if (buffer.len == 0)
return 0;

Expand Down
7 changes: 5 additions & 2 deletions lib/std/compress/zstandard.zig
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub fn Decompressor(comptime ReaderType: type) type {
OutOfMemory,
};

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

pub fn init(source: ReaderType, options: DecompressorOptions) Self {
return .{
Expand Down Expand Up @@ -105,7 +105,10 @@ pub fn Decompressor(comptime ReaderType: type) type {
return .{ .context = self };
}

pub fn read(self: *Self, buffer: []u8) Error!usize {
pub fn readv(self: *Self, iov: []std.io.ReadBuffers) Error!usize {
if (iov.len == 0) return 0;
const first = iov[0];
const buffer = first.ptr[0..first.len];
if (buffer.len == 0) return 0;

var size: usize = 0;
Expand Down
8 changes: 6 additions & 2 deletions lib/std/compress/zstandard/readers.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub const ReversedByteReader = struct {
remaining_bytes: usize,
bytes: []const u8,

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

pub fn init(bytes: []const u8) ReversedByteReader {
return .{
Expand All @@ -17,9 +17,13 @@ pub const ReversedByteReader = struct {
return .{ .context = self };
}

fn readFn(ctx: *ReversedByteReader, buffer: []u8) !usize {
fn readvFn(ctx: *ReversedByteReader, iov: []std.io.ReadBuffers) !usize {
if (iov.len == 0) return 0;
const first = iov[0];
const buffer = first.ptr[0..first.len];
if (ctx.remaining_bytes == 0) return 0;
const byte_index = ctx.remaining_bytes - 1;
std.debug.assert(buffer.len > 0);
buffer[0] = ctx.bytes[byte_index];
// buffer[0] = @bitReverse(ctx.bytes[byte_index]);
ctx.remaining_bytes = byte_index;
Expand Down
12 changes: 8 additions & 4 deletions lib/std/crypto/sha2.zig
Original file line number Diff line number Diff line change
Expand Up @@ -392,11 +392,15 @@ fn Sha2x32(comptime params: Sha2Params32) type {
}

pub const Error = error{};
pub const Writer = std.io.Writer(*Self, Error, write);
pub const Writer = std.io.Writer(*Self, Error, writev);

fn write(self: *Self, bytes: []const u8) Error!usize {
self.update(bytes);
return bytes.len;
fn writev(self: *Self, iov: []std.io.WriteBuffers) Error!usize {
var written: usize = 0;
for (iov) |v| {
self.update(v.ptr[0..v.len]);
written += v.len;
}
return written;
}

pub fn writer(self: *Self) Writer {
Expand Down
12 changes: 8 additions & 4 deletions lib/std/crypto/siphash.zig
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,15 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
}

pub const Error = error{};
pub const Writer = std.io.Writer(*Self, Error, write);
pub const Writer = std.io.Writer(*Self, Error, writev);

fn write(self: *Self, bytes: []const u8) Error!usize {
self.update(bytes);
return bytes.len;
fn writev(self: *Self, iov: []std.io.WriteBuffers) Error!usize {
var written: usize = 0;
for (iov) |v| {
self.update(v.ptr[0..v.len]);
written += v.len;
}
return written;
}

pub fn writer(self: *Self) Writer {
Expand Down
9 changes: 5 additions & 4 deletions lib/std/crypto/tls.zig
Original file line number Diff line number Diff line change
Expand Up @@ -460,24 +460,25 @@ pub const Decoder = struct {
}

/// Use this function to increase `their_end`.
pub fn readAtLeast(d: *Decoder, stream: anytype, their_amt: usize) !void {
pub fn readAtLeast(d: *Decoder, reader: std.io.AnyReader, their_amt: usize) !void {
assert(!d.disable_reads);
const existing_amt = d.cap - d.idx;
d.their_end = d.idx + their_amt;
if (their_amt <= existing_amt) return;
const request_amt = their_amt - existing_amt;
const dest = d.buf[d.cap..];
if (request_amt > dest.len) return error.TlsRecordOverflow;
const actual_amt = try stream.readAtLeast(dest, request_amt);

const actual_amt = try reader.readAtLeast(dest, request_amt);
if (actual_amt < request_amt) return error.TlsConnectionTruncated;
d.cap += actual_amt;
}

/// Same as `readAtLeast` but also increases `our_end` by exactly `our_amt`.
/// Use when `our_amt` is calculated by us, not by them.
pub fn readAtLeastOurAmt(d: *Decoder, stream: anytype, our_amt: usize) !void {
pub fn readAtLeastOurAmt(d: *Decoder, reader: std.io.AnyReader, our_amt: usize) !void {
assert(!d.disable_reads);
try readAtLeast(d, stream, our_amt);
try d.readAtLeast(reader, our_amt);
d.our_end = d.idx + our_amt;
}

Expand Down
Loading