mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
update some stuff to std.io API
This commit is contained in:
parent
52b3275eb2
commit
af24e722fb
@ -588,7 +588,7 @@ pub fn panicExtra(
|
||||
// a minor annoyance with this is that it will result in the NoSpaceLeft
|
||||
// error being part of the @panic stack trace (but that error should
|
||||
// only happen rarely)
|
||||
const msg = if (bw.print(format, args)) |_| bw.getWritten() else |_| blk: {
|
||||
const msg = if (bw.print(format, args)) |_| bw.buffered() else |_| blk: {
|
||||
@memcpy(buf[size..], trunc_msg);
|
||||
break :blk &buf;
|
||||
};
|
||||
|
||||
@ -2612,10 +2612,7 @@ pub fn updateFile(
|
||||
var atomic_file = try dest_dir.atomicFile(dest_path, .{ .mode = actual_mode });
|
||||
defer atomic_file.deinit();
|
||||
|
||||
var src_reader: File.Reader = .{
|
||||
.file = src_file,
|
||||
.size = src_stat.size,
|
||||
};
|
||||
var src_reader: File.Reader = .initSize(src_file, &.{}, src_stat.size);
|
||||
var buffer: [2000]u8 = undefined;
|
||||
var dest_writer = atomic_file.file_writer.writer(&buffer);
|
||||
|
||||
@ -2658,7 +2655,7 @@ pub fn copyFile(
|
||||
var atomic_file = try dest_dir.atomicFile(dest_path, .{ .mode = mode });
|
||||
defer atomic_file.deinit();
|
||||
|
||||
try copy_file(in_file.handle, atomic_file.file.handle, size);
|
||||
try copy_file(in_file.handle, atomic_file.file_writer.file.handle, size);
|
||||
try atomic_file.finish();
|
||||
}
|
||||
|
||||
|
||||
@ -961,6 +961,14 @@ pub const Reader = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn initSize(file: File, buffer: []u8, size: u64) Reader {
|
||||
return .{
|
||||
.file = file,
|
||||
.interface = initInterface(buffer),
|
||||
.size = size,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getSize(r: *Reader) GetEndPosError!u64 {
|
||||
return r.size orelse {
|
||||
if (r.size_err) |err| return err;
|
||||
@ -1436,18 +1444,15 @@ pub fn readerStreaming(file: File) Reader {
|
||||
///
|
||||
/// Positional is more threadsafe, since the global seek position is not
|
||||
/// affected.
|
||||
pub fn writer(file: File) Writer {
|
||||
return .{ .file = file };
|
||||
pub fn writer(file: File, buffer: []u8) Writer {
|
||||
return .init(file, buffer);
|
||||
}
|
||||
|
||||
/// Positional is more threadsafe, since the global seek position is not
|
||||
/// affected, but when such syscalls are not available, preemptively choosing
|
||||
/// `Writer.Mode.streaming` will skip a failed syscall.
|
||||
pub fn writerStreaming(file: File) Writer {
|
||||
return .{
|
||||
.file = file,
|
||||
.mode = .streaming,
|
||||
};
|
||||
pub fn writerStreaming(file: File, buffer: []u8) Writer {
|
||||
return .initMode(file, buffer, .streaming);
|
||||
}
|
||||
|
||||
const range_off: windows.LARGE_INTEGER = 0;
|
||||
|
||||
@ -433,12 +433,18 @@ pub const Reader = struct {
|
||||
///
|
||||
/// See also:
|
||||
/// * `interfaceDecompressing`
|
||||
pub fn bodyReader(reader: *Reader, transfer_encoding: TransferEncoding, content_length: ?u64) std.io.Reader {
|
||||
pub fn bodyReader(
|
||||
reader: *Reader,
|
||||
buffer: []u8,
|
||||
transfer_encoding: TransferEncoding,
|
||||
content_length: ?u64,
|
||||
) std.io.Reader {
|
||||
assert(reader.state == .received_head);
|
||||
return switch (transfer_encoding) {
|
||||
.chunked => {
|
||||
reader.state = .{ .body_remaining_chunk_len = .head };
|
||||
return .{
|
||||
.buffer = buffer,
|
||||
.context = reader,
|
||||
.vtable = &.{
|
||||
.read = chunkedRead,
|
||||
@ -450,6 +456,7 @@ pub const Reader = struct {
|
||||
if (content_length) |len| {
|
||||
reader.state = .{ .body_remaining_content_length = len };
|
||||
return .{
|
||||
.buffer = buffer,
|
||||
.context = reader,
|
||||
.vtable = &.{
|
||||
.read = contentLengthRead,
|
||||
|
||||
@ -667,11 +667,11 @@ pub const Response = struct {
|
||||
///
|
||||
/// See also:
|
||||
/// * `readerDecompressing`
|
||||
pub fn reader(response: *Response) std.io.Reader {
|
||||
pub fn reader(response: *Response, buffer: []u8) std.io.Reader {
|
||||
const req = response.request;
|
||||
if (!req.method.responseHasBody()) return .ending;
|
||||
const head = &response.head;
|
||||
return req.reader.bodyReader(head.transfer_encoding, head.content_length);
|
||||
return req.reader.bodyReader(buffer, head.transfer_encoding, head.content_length);
|
||||
}
|
||||
|
||||
/// If compressed body has been negotiated this will return decompressed bytes.
|
||||
|
||||
@ -1198,8 +1198,9 @@ test "redirect to different connection" {
|
||||
|
||||
try req.sendBodiless();
|
||||
var response = try req.receiveHead(&redirect_buffer);
|
||||
var reader = response.reader(&.{});
|
||||
|
||||
const body = try response.reader().readRemainingAlloc(gpa, .limited(8192));
|
||||
const body = try reader.allocRemaining(gpa, .limited(8192));
|
||||
defer gpa.free(body);
|
||||
|
||||
try expectEqualStrings("good job, you pass", body);
|
||||
|
||||
@ -162,9 +162,9 @@ pub fn defaultDiscard(r: *Reader, limit: Limit) Error!usize {
|
||||
};
|
||||
if (n > @intFromEnum(limit)) {
|
||||
const over_amt = n - @intFromEnum(limit);
|
||||
assert(over_amt <= w.buffer.len); // limit may be exceeded only by an amount within buffer capacity.
|
||||
r.seek = w.end - over_amt;
|
||||
r.end = w.end;
|
||||
assert(r.end <= w.buffer.len); // limit may be exceeded only by an amount within buffer capacity.
|
||||
return @intFromEnum(limit);
|
||||
}
|
||||
return n;
|
||||
@ -740,12 +740,20 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 {
|
||||
}
|
||||
if (seek > 0) {
|
||||
const remainder = buffer[seek..];
|
||||
std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
|
||||
@memmove(buffer[0..remainder.len], remainder);
|
||||
r.end = remainder.len;
|
||||
r.seek = 0;
|
||||
}
|
||||
var writer: Writer = .{
|
||||
.buffer = r.buffer,
|
||||
.vtable = &.{ .drain = Writer.fixedDrain },
|
||||
};
|
||||
while (r.end < r.buffer.len) {
|
||||
const n = try r.unbuffered_reader.readVec(&.{r.buffer[r.end..]});
|
||||
writer.end = r.end;
|
||||
const n = r.vtable.stream(r, &writer, .limited(r.buffer.len - r.end)) catch |err| switch (err) {
|
||||
error.WriteFailed => unreachable,
|
||||
else => |e| return e,
|
||||
};
|
||||
const prev_end = r.end;
|
||||
r.end = prev_end + n;
|
||||
if (std.mem.indexOfScalarPos(u8, r.buffer[0..r.end], prev_end, delimiter)) |end| {
|
||||
@ -929,8 +937,16 @@ pub fn fill(r: *Reader, n: usize) Error!void {
|
||||
return;
|
||||
}
|
||||
rebaseCapacity(r, n);
|
||||
var writer: Writer = .{
|
||||
.buffer = r.buffer,
|
||||
.vtable = &.{ .drain = Writer.fixedDrain },
|
||||
};
|
||||
while (r.end < r.seek + n) {
|
||||
r.end += try r.unbuffered_reader.readVec(&.{r.buffer[r.end..]});
|
||||
writer.end = r.end;
|
||||
r.end += r.vtable.stream(r, &writer, .limited(r.buffer.len - r.end)) catch |err| switch (err) {
|
||||
error.WriteFailed => unreachable,
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -941,7 +957,15 @@ pub fn fill(r: *Reader, n: usize) Error!void {
|
||||
/// Asserts buffer capacity is at least 1.
|
||||
pub fn fillMore(r: *Reader) Error!void {
|
||||
rebaseCapacity(r, 1);
|
||||
r.end += try r.unbuffered_reader.readVec(&.{r.buffer[r.end..]});
|
||||
var writer: Writer = .{
|
||||
.buffer = r.buffer,
|
||||
.end = r.end,
|
||||
.vtable = &.{ .drain = Writer.fixedDrain },
|
||||
};
|
||||
r.end += r.vtable.stream(r, &writer, .limited(r.buffer.len - r.end)) catch |err| switch (err) {
|
||||
error.WriteFailed => unreachable,
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns the next byte from the stream or returns `error.EndOfStream`.
|
||||
|
||||
@ -1722,7 +1722,7 @@ pub fn unimplementedSendFile(w: *Writer, file_reader: *File.Reader, limit: Limit
|
||||
/// time to return an error. However, we still need to make sure all of the
|
||||
/// available buffer has been filled. Also, it may be called from `flush` in
|
||||
/// which case it should return successfully.
|
||||
fn fixedDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
|
||||
pub fn fixedDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
|
||||
if (data.len == 0) return 0;
|
||||
for (data[0 .. data.len - 1]) |bytes| {
|
||||
const dest = w.buffer[w.end..];
|
||||
@ -1860,24 +1860,30 @@ pub const Allocating = struct {
|
||||
pub fn init(allocator: Allocator) Allocating {
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.interface = init_interface,
|
||||
.buffer = &.{},
|
||||
.interface = .{
|
||||
.buffer = &.{},
|
||||
.vtable = &vtable,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn initCapacity(allocator: Allocator, capacity: usize) error{OutOfMemory}!Allocating {
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.interface = init_interface,
|
||||
.buffer = try allocator.alloc(u8, capacity),
|
||||
.interface = .{
|
||||
.buffer = try allocator.alloc(u8, capacity),
|
||||
.vtable = &vtable,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn initOwnedSlice(allocator: Allocator, slice: []u8) Allocating {
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.interface = init_interface,
|
||||
.buffer = slice,
|
||||
.interface = .{
|
||||
.buffer = slice,
|
||||
.vtable = &vtable,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -1886,23 +1892,21 @@ pub const Allocating = struct {
|
||||
defer array_list.* = .empty;
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.interface = init_interface,
|
||||
.buffer = array_list.allocatedSlice(),
|
||||
.end = array_list.items.len,
|
||||
.interface = .{
|
||||
.vtable = &vtable,
|
||||
.buffer = array_list.allocatedSlice(),
|
||||
.end = array_list.items.len,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const init_interface: Writer = .{
|
||||
.interface = .{
|
||||
.vtable = &.{
|
||||
.drain = Allocating.drain,
|
||||
.sendFile = Allocating.sendFile,
|
||||
},
|
||||
},
|
||||
const vtable: VTable = .{
|
||||
.drain = Allocating.drain,
|
||||
.sendFile = Allocating.sendFile,
|
||||
};
|
||||
|
||||
pub fn deinit(a: *Allocating) void {
|
||||
a.allocator.free(a.buffer);
|
||||
a.allocator.free(a.interface.buffer);
|
||||
a.* = undefined;
|
||||
}
|
||||
|
||||
@ -1983,8 +1987,8 @@ pub const Allocating = struct {
|
||||
}
|
||||
|
||||
fn setArrayList(a: *Allocating, list: std.ArrayListUnmanaged(u8)) void {
|
||||
a.buffer = list.allocatedSlice();
|
||||
a.end = list.items.len;
|
||||
a.interface.buffer = list.allocatedSlice();
|
||||
a.interface.end = list.items.len;
|
||||
}
|
||||
|
||||
test Allocating {
|
||||
|
||||
@ -970,7 +970,7 @@ pub fn getAddressList(gpa: Allocator, name: []const u8, port: u16) GetAddressLis
|
||||
const name_c = try gpa.dupeZ(u8, name);
|
||||
defer gpa.free(name_c);
|
||||
|
||||
const port_c = try std.fmt.allocPrintZ(gpa, "{}", .{port});
|
||||
const port_c = try std.fmt.allocPrintSentinel(gpa, "{d}", .{port}, 0);
|
||||
defer gpa.free(port_c);
|
||||
|
||||
const hints: posix.addrinfo = .{
|
||||
@ -1985,10 +1985,7 @@ pub const Stream = struct {
|
||||
return .{
|
||||
.stream = stream,
|
||||
.interface = .{
|
||||
.context = undefined,
|
||||
.vtable = &.{
|
||||
.drain = drain,
|
||||
},
|
||||
.vtable = &.{ .drain = drain },
|
||||
.buffer = buffer,
|
||||
},
|
||||
};
|
||||
@ -2090,7 +2087,6 @@ pub const Stream = struct {
|
||||
pub fn init(stream: Stream, buffer: []u8) Writer {
|
||||
return .{
|
||||
.interface = .{
|
||||
.context = undefined,
|
||||
.vtable = &.{
|
||||
.drain = drain,
|
||||
.sendFile = sendFile,
|
||||
|
||||
@ -347,7 +347,7 @@ test "run test cases" {
|
||||
|
||||
for (cases) |case| {
|
||||
var br: std.io.Reader = .fixed(case.data);
|
||||
var iter = tar.iterator(&br, .{
|
||||
var iter: tar.Iterator = .init(&br, .{
|
||||
.file_name_buffer = &file_name_buffer,
|
||||
.link_name_buffer = &link_name_buffer,
|
||||
});
|
||||
@ -391,7 +391,7 @@ test "pax/gnu long names with small buffer" {
|
||||
|
||||
for (long_name_cases) |case| {
|
||||
var br: std.io.Reader = .fixed(case.data);
|
||||
var iter = tar.iterator(&br, .{
|
||||
var iter: tar.Iterator = .init(&br, .{
|
||||
.file_name_buffer = &min_file_name_buffer,
|
||||
.link_name_buffer = &min_link_name_buffer,
|
||||
});
|
||||
@ -412,7 +412,7 @@ test "insufficient buffer in Header name filed" {
|
||||
var min_link_name_buffer: [100]u8 = undefined;
|
||||
|
||||
var br: std.io.Reader = .fixed(cases[0].data);
|
||||
var iter = tar.iterator(&br, .{
|
||||
var iter: tar.Iterator = .init(&br, .{
|
||||
.file_name_buffer = &min_file_name_buffer,
|
||||
.link_name_buffer = &min_link_name_buffer,
|
||||
});
|
||||
|
||||
@ -55,10 +55,12 @@ pub const Tz = struct {
|
||||
};
|
||||
|
||||
pub fn parse(allocator: std.mem.Allocator, reader: *std.io.Reader) !Tz {
|
||||
var legacy_header = try reader.takeStruct(Header);
|
||||
var legacy_header = (try reader.takeStruct(Header)).*;
|
||||
if (!std.mem.eql(u8, &legacy_header.magic, "TZif")) return error.BadHeader;
|
||||
if (legacy_header.version != 0 and legacy_header.version != '2' and legacy_header.version != '3') return error.BadVersion;
|
||||
|
||||
switch (legacy_header.version) {
|
||||
0, '2', '3' => {},
|
||||
else => return error.BadVersion,
|
||||
}
|
||||
if (builtin.target.cpu.arch.endian() != std.builtin.Endian.big) {
|
||||
std.mem.byteSwapAllFields(@TypeOf(legacy_header.counts), &legacy_header.counts);
|
||||
}
|
||||
|
||||
@ -355,20 +355,17 @@ fn testParser(
|
||||
// When all the lines have been analyzed the finalize method is called.
|
||||
fn CpuinfoParser(comptime impl: anytype) type {
|
||||
return struct {
|
||||
fn parse(arch: Target.Cpu.Arch, reader: anytype) anyerror!?Target.Cpu {
|
||||
var line_buf: [1024]u8 = undefined;
|
||||
fn parse(arch: Target.Cpu.Arch, reader: *std.io.Reader) !?Target.Cpu {
|
||||
var obj: impl = .{};
|
||||
|
||||
while (true) {
|
||||
const line = (try reader.readUntilDelimiterOrEof(&line_buf, '\n')) orelse break;
|
||||
while (reader.takeDelimiterExclusive('\n')) |line| {
|
||||
const colon_pos = mem.indexOfScalar(u8, line, ':') orelse continue;
|
||||
const key = mem.trimEnd(u8, line[0..colon_pos], " \t");
|
||||
const value = mem.trimStart(u8, line[colon_pos + 1 ..], " \t");
|
||||
|
||||
if (!try obj.line_hook(key, value))
|
||||
break;
|
||||
if (!try obj.line_hook(key, value)) break;
|
||||
} else |err| switch (err) {
|
||||
error.EndOfStream => {},
|
||||
else => |e| return e,
|
||||
}
|
||||
|
||||
return obj.finalize(arch);
|
||||
}
|
||||
};
|
||||
|
||||
@ -51,10 +51,10 @@ const FileStore = struct {
|
||||
uncompressed_size: usize,
|
||||
};
|
||||
|
||||
fn makeZip(file_writer: *std.fs.File.Writer, files: []const File, options: WriteZipOptions) !std.io.Reader {
|
||||
fn makeZip(file_writer: *std.fs.File.Writer, files: []const File, options: WriteZipOptions) !void {
|
||||
const store = try std.testing.allocator.alloc(FileStore, files.len);
|
||||
defer std.testing.allocator.free(store);
|
||||
return makeZipWithStore(file_writer, files, options, store);
|
||||
try makeZipWithStore(file_writer, files, options, store);
|
||||
}
|
||||
|
||||
fn makeZipWithStore(
|
||||
@ -312,7 +312,8 @@ fn testZipWithStore(
|
||||
|
||||
var file = tmp.createFile();
|
||||
defer file.close();
|
||||
var file_writer = file.writer();
|
||||
var buffer: [100]u8 = undefined;
|
||||
var file_writer = file.writer(&buffer);
|
||||
try makeZipWithStore(&file_writer, test_files, write_opt, store);
|
||||
var file_reader = file_writer.moveToReader();
|
||||
try zip.extract(tmp.dir, &file_reader, options);
|
||||
@ -323,7 +324,8 @@ fn testZipError(expected_error: anyerror, file: File, options: zip.ExtractOption
|
||||
defer tmp.cleanup();
|
||||
const tmp_file = tmp.createFile();
|
||||
defer tmp_file.close();
|
||||
var file_writer = tmp_file.writer();
|
||||
var buffer: [100]u8 = undefined;
|
||||
var file_writer = tmp_file.writer(&buffer);
|
||||
var store: [1]FileStore = undefined;
|
||||
try makeZipWithStore(&file_writer, &[_]File{file}, .{}, &store);
|
||||
var file_reader = file_writer.moveToReader();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user