| author | |
| committer | |
| log | 4ee25345668ff93f1a4a857436b14fc305f8cee7 |
| tree | 5764951bf7555cdf2d84f84eea10403c65f4e9bc |
| parent | 60854795b85d075ffc5418f9009c832f6a06a84c |
5 files changed, 112 insertions(+), 122 deletions(-)
lib/std/io.zig+3| ... | @@ -17,6 +17,8 @@ const Alignment = std.mem.Alignment; | ... | @@ -17,6 +17,8 @@ const Alignment = std.mem.Alignment; |
| 17 | pub const Reader = @import("io/Reader.zig"); | 17 | pub const Reader = @import("io/Reader.zig"); |
| 18 | pub const Writer = @import("io/Writer.zig"); | 18 | pub const Writer = @import("io/Writer.zig"); |
| 19 | 19 | ||
| 20 | pub const PositionalReader = @import("io/PositionalReader.zig"); | ||
| 21 | |||
| 20 | pub const BufferedReader = @import("io/BufferedReader.zig"); | 22 | pub const BufferedReader = @import("io/BufferedReader.zig"); |
| 21 | pub const BufferedWriter = @import("io/BufferedWriter.zig"); | 23 | pub const BufferedWriter = @import("io/BufferedWriter.zig"); |
| 22 | pub const AllocatingWriter = @import("io/AllocatingWriter.zig"); | 24 | pub const AllocatingWriter = @import("io/AllocatingWriter.zig"); |
| ... | @@ -451,6 +453,7 @@ test { | ... | @@ -451,6 +453,7 @@ test { |
| 451 | _ = BufferedReader; | 453 | _ = BufferedReader; |
| 452 | _ = Reader; | 454 | _ = Reader; |
| 453 | _ = Writer; | 455 | _ = Writer; |
| 456 | _ = PositionalReader; | ||
| 454 | _ = AllocatingWriter; | 457 | _ = AllocatingWriter; |
| 455 | _ = @import("io/bit_reader.zig"); | 458 | _ = @import("io/bit_reader.zig"); |
| 456 | _ = @import("io/bit_writer.zig"); | 459 | _ = @import("io/bit_writer.zig"); |
lib/std/io/BufferedReader.zig+14-51| ... | @@ -28,10 +28,8 @@ const eof_writer: std.io.Writer.VTable = .{ | ... | @@ -28,10 +28,8 @@ const eof_writer: std.io.Writer.VTable = .{ |
| 28 | .writeFile = eof_writeFile, | 28 | .writeFile = eof_writeFile, |
| 29 | }; | 29 | }; |
| 30 | const eof_reader: std.io.Reader.VTable = .{ | 30 | const eof_reader: std.io.Reader.VTable = .{ |
| 31 | .posRead = eof_posRead, | 31 | .read = eof_read, |
| 32 | .posReadVec = eof_posReadVec, | 32 | .readv = eof_readv, |
| 33 | .streamRead = eof_streamRead, | ||
| 34 | .streamReadVec = eof_streamReadVec, | ||
| 35 | }; | 33 | }; |
| 36 | 34 | ||
| 37 | fn eof_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) anyerror!usize { | 35 | fn eof_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) anyerror!usize { |
| ... | @@ -58,29 +56,14 @@ fn eof_writeFile( | ... | @@ -58,29 +56,14 @@ fn eof_writeFile( |
| 58 | return error.NoSpaceLeft; | 56 | return error.NoSpaceLeft; |
| 59 | } | 57 | } |
| 60 | 58 | ||
| 61 | fn eof_posRead(ctx: ?*anyopaque, bw: *std.io.BufferedWriter, limit: Reader.Limit, offset: u64) anyerror!Reader.Status { | 59 | fn eof_read(ctx: ?*anyopaque, bw: *std.io.BufferedWriter, limit: Reader.Limit) anyerror!Reader.Status { |
| 62 | _ = ctx; | ||
| 63 | _ = bw; | ||
| 64 | _ = limit; | ||
| 65 | _ = offset; | ||
| 66 | return error.EndOfStream; | ||
| 67 | } | ||
| 68 | |||
| 69 | fn eof_posReadVec(ctx: ?*anyopaque, data: []const []u8, offset: u64) anyerror!Reader.Status { | ||
| 70 | _ = ctx; | ||
| 71 | _ = data; | ||
| 72 | _ = offset; | ||
| 73 | return error.EndOfStream; | ||
| 74 | } | ||
| 75 | |||
| 76 | fn eof_streamRead(ctx: ?*anyopaque, bw: *std.io.BufferedWriter, limit: Reader.Limit) anyerror!Reader.Status { | ||
| 77 | _ = ctx; | 60 | _ = ctx; |
| 78 | _ = bw; | 61 | _ = bw; |
| 79 | _ = limit; | 62 | _ = limit; |
| 80 | return error.EndOfStream; | 63 | return error.EndOfStream; |
| 81 | } | 64 | } |
| 82 | 65 | ||
| 83 | fn eof_streamReadVec(ctx: ?*anyopaque, data: []const []u8) anyerror!Reader.Status { | 66 | fn eof_readv(ctx: ?*anyopaque, data: []const []u8) anyerror!Reader.Status { |
| 84 | _ = ctx; | 67 | _ = ctx; |
| 85 | _ = data; | 68 | _ = data; |
| 86 | return error.EndOfStream; | 69 | return error.EndOfStream; |
| ... | @@ -117,15 +100,13 @@ pub fn reader(br: *BufferedReader) Reader { | ... | @@ -117,15 +100,13 @@ pub fn reader(br: *BufferedReader) Reader { |
| 117 | return .{ | 100 | return .{ |
| 118 | .context = br, | 101 | .context = br, |
| 119 | .vtable = &.{ | 102 | .vtable = &.{ |
| 120 | .streamRead = passthru_streamRead, | 103 | .read = passthru_read, |
| 121 | .streamReadVec = passthru_streamReadVec, | 104 | .readv = passthru_readv, |
| 122 | .posRead = passthru_posRead, | ||
| 123 | .posReadVec = passthru_posReadVec, | ||
| 124 | }, | 105 | }, |
| 125 | }; | 106 | }; |
| 126 | } | 107 | } |
| 127 | 108 | ||
| 128 | fn passthru_streamRead(ctx: ?*anyopaque, bw: *BufferedWriter, limit: Reader.Limit) anyerror!Reader.RwResult { | 109 | fn passthru_read(ctx: ?*anyopaque, bw: *BufferedWriter, limit: Reader.Limit) anyerror!Reader.RwResult { |
| 129 | const br: *BufferedReader = @alignCast(@ptrCast(ctx)); | 110 | const br: *BufferedReader = @alignCast(@ptrCast(ctx)); |
| 130 | const buffer = br.storage.buffer.items; | 111 | const buffer = br.storage.buffer.items; |
| 131 | const buffered = buffer[br.seek..]; | 112 | const buffered = buffer[br.seek..]; |
| ... | @@ -139,31 +120,13 @@ fn passthru_streamRead(ctx: ?*anyopaque, bw: *BufferedWriter, limit: Reader.Limi | ... | @@ -139,31 +120,13 @@ fn passthru_streamRead(ctx: ?*anyopaque, bw: *BufferedWriter, limit: Reader.Limi |
| 139 | .write_end = result.end, | 120 | .write_end = result.end, |
| 140 | }; | 121 | }; |
| 141 | } | 122 | } |
| 142 | return br.unbuffered_reader.streamRead(bw, limit); | 123 | return br.unbuffered_reader.read(bw, limit); |
| 143 | } | ||
| 144 | |||
| 145 | fn passthru_streamReadVec(ctx: ?*anyopaque, data: []const []u8) anyerror!Reader.Status { | ||
| 146 | const br: *BufferedReader = @alignCast(@ptrCast(ctx)); | ||
| 147 | _ = br; | ||
| 148 | _ = data; | ||
| 149 | @panic("TODO"); | ||
| 150 | } | ||
| 151 | |||
| 152 | fn passthru_posRead(ctx: ?*anyopaque, bw: *BufferedWriter, limit: Reader.Limit, off: u64) anyerror!Reader.Status { | ||
| 153 | const br: *BufferedReader = @alignCast(@ptrCast(ctx)); | ||
| 154 | const buffer = br.storage.buffer.items; | ||
| 155 | if (off < buffer.len) { | ||
| 156 | const send = buffer[off..limit.min(buffer.len)]; | ||
| 157 | return bw.writeSplat(send, 1); | ||
| 158 | } | ||
| 159 | return br.unbuffered_reader.posRead(bw, limit, off - buffer.len); | ||
| 160 | } | 124 | } |
| 161 | 125 | ||
| 162 | fn passthru_posReadVec(ctx: ?*anyopaque, data: []const []u8, off: u64) anyerror!Reader.Status { | 126 | fn passthru_readv(ctx: ?*anyopaque, data: []const []u8) anyerror!Reader.Status { |
| 163 | const br: *BufferedReader = @alignCast(@ptrCast(ctx)); | 127 | const br: *BufferedReader = @alignCast(@ptrCast(ctx)); |
| 164 | _ = br; | 128 | _ = br; |
| 165 | _ = data; | 129 | _ = data; |
| 166 | _ = off; | ||
| 167 | @panic("TODO"); | 130 | @panic("TODO"); |
| 168 | } | 131 | } |
| 169 | 132 | ||
| ... | @@ -293,7 +256,7 @@ pub fn discardUpTo(br: *BufferedReader, n: usize) anyerror!usize { | ... | @@ -293,7 +256,7 @@ pub fn discardUpTo(br: *BufferedReader, n: usize) anyerror!usize { |
| 293 | remaining -= (list.items.len - br.seek); | 256 | remaining -= (list.items.len - br.seek); |
| 294 | list.items.len = 0; | 257 | list.items.len = 0; |
| 295 | br.seek = 0; | 258 | br.seek = 0; |
| 296 | const result = try br.unbuffered_reader.streamRead(&br.storage, .none); | 259 | const result = try br.unbuffered_reader.read(&br.storage, .none); |
| 297 | result.write_err catch unreachable; | 260 | result.write_err catch unreachable; |
| 298 | try result.read_err; | 261 | try result.read_err; |
| 299 | assert(result.len == list.items.len); | 262 | assert(result.len == list.items.len); |
| ... | @@ -337,7 +300,7 @@ pub fn read(br: *BufferedReader, buffer: []u8) anyerror!void { | ... | @@ -337,7 +300,7 @@ pub fn read(br: *BufferedReader, buffer: []u8) anyerror!void { |
| 337 | br.seek = 0; | 300 | br.seek = 0; |
| 338 | var i: usize = in_buffer.len; | 301 | var i: usize = in_buffer.len; |
| 339 | while (true) { | 302 | while (true) { |
| 340 | const status = try br.unbuffered_reader.streamRead(&br.storage, .none); | 303 | const status = try br.unbuffered_reader.read(&br.storage, .none); |
| 341 | const next_i = i + list.items.len; | 304 | const next_i = i + list.items.len; |
| 342 | if (next_i >= buffer.len) { | 305 | if (next_i >= buffer.len) { |
| 343 | const remaining = buffer[i..]; | 306 | const remaining = buffer[i..]; |
| ... | @@ -397,7 +360,7 @@ pub fn peekDelimiterInclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8 | ... | @@ -397,7 +360,7 @@ pub fn peekDelimiterInclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8 |
| 397 | list.items.len = i; | 360 | list.items.len = i; |
| 398 | br.seek = 0; | 361 | br.seek = 0; |
| 399 | while (i < list.capacity) { | 362 | while (i < list.capacity) { |
| 400 | const status = try br.unbuffered_reader.streamRead(&br.storage, .none); | 363 | const status = try br.unbuffered_reader.read(&br.storage, .none); |
| 401 | if (std.mem.indexOfScalarPos(u8, list.items, i, delimiter)) |end| { | 364 | if (std.mem.indexOfScalarPos(u8, list.items, i, delimiter)) |end| { |
| 402 | return list.items[0 .. end + 1]; | 365 | return list.items[0 .. end + 1]; |
| 403 | } | 366 | } |
| ... | @@ -442,7 +405,7 @@ pub fn peekDelimiterConclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8 | ... | @@ -442,7 +405,7 @@ pub fn peekDelimiterConclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8 |
| 442 | list.items.len = i; | 405 | list.items.len = i; |
| 443 | br.seek = 0; | 406 | br.seek = 0; |
| 444 | while (i < list.capacity) { | 407 | while (i < list.capacity) { |
| 445 | const status = try br.unbuffered_reader.streamRead(&br.storage, .none); | 408 | const status = try br.unbuffered_reader.read(&br.storage, .none); |
| 446 | if (std.mem.indexOfScalarPos(u8, list.items, i, delimiter)) |end| { | 409 | if (std.mem.indexOfScalarPos(u8, list.items, i, delimiter)) |end| { |
| 447 | return list.items[0 .. end + 1]; | 410 | return list.items[0 .. end + 1]; |
| 448 | } | 411 | } |
| ... | @@ -540,7 +503,7 @@ pub fn fill(br: *BufferedReader, n: usize) anyerror!void { | ... | @@ -540,7 +503,7 @@ pub fn fill(br: *BufferedReader, n: usize) anyerror!void { |
| 540 | list.items.len = remainder.len; | 503 | list.items.len = remainder.len; |
| 541 | br.seek = 0; | 504 | br.seek = 0; |
| 542 | while (true) { | 505 | while (true) { |
| 543 | const status = try br.unbuffered_reader.streamRead(&br.storage, .none); | 506 | const status = try br.unbuffered_reader.read(&br.storage, .none); |
| 544 | if (n <= list.items.len) return; | 507 | if (n <= list.items.len) return; |
| 545 | if (status.end) return error.EndOfStream; | 508 | if (status.end) return error.EndOfStream; |
| 546 | } | 509 | } |
lib/std/io/PositionalReader.zig created+64| ... | @@ -0,0 +1,64 @@ | ||
| 1 | const std = @import("../std.zig"); | ||
| 2 | const PositionalReader = @This(); | ||
| 3 | const assert = std.debug.assert; | ||
| 4 | |||
| 5 | context: ?*anyopaque, | ||
| 6 | vtable: *const VTable, | ||
| 7 | |||
| 8 | pub const VTable = struct { | ||
| 9 | /// Writes bytes starting from `offset` to `bw`. | ||
| 10 | /// | ||
| 11 | /// Returns the number of bytes written, which will be at minimum `0` and | ||
| 12 | /// at most `limit`. The number of bytes written, including zero, does not | ||
| 13 | /// indicate end of stream. | ||
| 14 | /// | ||
| 15 | /// If the resource represented by the reader has an internal seek | ||
| 16 | /// position, it is not mutated. | ||
| 17 | /// | ||
| 18 | /// The implementation should do a maximum of one underlying read call. | ||
| 19 | /// | ||
| 20 | /// If `error.Unseekable` is returned, the resource cannot be used via a | ||
| 21 | /// positional reading interface. | ||
| 22 | read: *const fn (ctx: ?*anyopaque, bw: *std.io.BufferedWriter, limit: Limit, offset: u64) anyerror!Status, | ||
| 23 | |||
| 24 | /// Writes bytes starting from `offset` to `data`. | ||
| 25 | /// | ||
| 26 | /// Returns the number of bytes written, which will be at minimum `0` and | ||
| 27 | /// at most `limit`. The number of bytes written, including zero, does not | ||
| 28 | /// indicate end of stream. | ||
| 29 | /// | ||
| 30 | /// If the resource represented by the reader has an internal seek | ||
| 31 | /// position, it is not mutated. | ||
| 32 | /// | ||
| 33 | /// The implementation should do a maximum of one underlying read call. | ||
| 34 | /// | ||
| 35 | /// If `error.Unseekable` is returned, the resource cannot be used via a | ||
| 36 | /// positional reading interface. | ||
| 37 | readv: *const fn (ctx: ?*anyopaque, data: []const []u8, offset: u64) anyerror!Status, | ||
| 38 | }; | ||
| 39 | |||
| 40 | pub const Len = std.io.Reader.Len; | ||
| 41 | pub const Status = std.io.Reader.Status; | ||
| 42 | pub const Limit = std.io.Reader.Limit; | ||
| 43 | |||
| 44 | pub fn read(pr: PositionalReader, bw: *std.io.BufferedWriter, limit: Limit, offset: u64) anyerror!Status { | ||
| 45 | return pr.vtable.read(pr.context, bw, limit, offset); | ||
| 46 | } | ||
| 47 | |||
| 48 | pub fn readv(pr: PositionalReader, data: []const []u8, offset: u64) anyerror!Status { | ||
| 49 | return pr.vtable.read(pr.context, data, offset); | ||
| 50 | } | ||
| 51 | |||
| 52 | /// Returns total number of bytes written to `w`. | ||
| 53 | /// | ||
| 54 | /// May return `error.Unseekable`, indicating this function cannot be used to | ||
| 55 | /// read from the reader. | ||
| 56 | pub fn readAll(pr: PositionalReader, w: *std.io.BufferedWriter, start_offset: u64) anyerror!usize { | ||
| 57 | const readFn = pr.vtable.read; | ||
| 58 | var offset: u64 = start_offset; | ||
| 59 | while (true) { | ||
| 60 | const status = try readFn(pr.context, w, .none, offset); | ||
| 61 | offset += status.len; | ||
| 62 | if (status.end) return @intCast(offset - start_offset); | ||
| 63 | } | ||
| 64 | } | ||
lib/std/io/Reader.zig+30-70| ... | @@ -6,39 +6,35 @@ context: ?*anyopaque, | ... | @@ -6,39 +6,35 @@ context: ?*anyopaque, |
| 6 | vtable: *const VTable, | 6 | vtable: *const VTable, |
| 7 | 7 | ||
| 8 | pub const VTable = struct { | 8 | pub const VTable = struct { |
| 9 | /// Writes bytes starting from `offset` to `bw`, or returns | 9 | /// Writes bytes from the internally tracked stream position to `bw`. |
| 10 | /// `error.Unseekable`, indicating `streamRead` should be used instead. | ||
| 11 | /// | 10 | /// |
| 12 | /// Returns the number of bytes written, which will be at minimum `0` and at | 11 | /// Returns the number of bytes written, which will be at minimum `0` and at |
| 13 | /// most `limit`. The number of bytes read, including zero, does not | 12 | /// most `limit`. The number of bytes read, including zero, does not |
| 14 | /// indicate end of stream. | 13 | /// indicate end of stream. |
| 15 | /// | 14 | /// |
| 16 | /// If the reader has an internal seek position, it is not mutated. | 15 | /// If the reader has an internal seek position, it moves forward in |
| 16 | /// accordance with the number of bytes return from this function. | ||
| 17 | /// | 17 | /// |
| 18 | /// The implementation should do a maximum of one underlying read call. | 18 | /// The implementation should do a maximum of one underlying read call. |
| 19 | /// | 19 | /// |
| 20 | /// If this is `null` it is equivalent to always returning | 20 | /// If `error.Unstreamable` is returned, the resource cannot be used via a |
| 21 | /// `error.Unseekable`. | 21 | /// streaming reading interface. |
| 22 | posRead: ?*const fn (ctx: ?*anyopaque, bw: *std.io.BufferedWriter, limit: Limit, offset: u64) anyerror!Status, | 22 | read: *const fn (ctx: ?*anyopaque, bw: *std.io.BufferedWriter, limit: Limit) anyerror!Status, |
| 23 | posReadVec: ?*const fn (ctx: ?*anyopaque, data: []const []u8, offset: u64) anyerror!Status, | 23 | |
| 24 | 24 | /// Writes bytes from the internally tracked stream position to `data`. | |
| 25 | /// Writes bytes from the internally tracked stream position to `bw`, or | ||
| 26 | /// returns `error.Unstreamable`, indicating `posRead` should be used | ||
| 27 | /// instead. | ||
| 28 | /// | 25 | /// |
| 29 | /// Returns the number of bytes written, which will be at minimum `0` and at | 26 | /// Returns the number of bytes written, which will be at minimum `0` and at |
| 30 | /// most `limit`. The number of bytes read, including zero, does not | 27 | /// most `limit`. The number of bytes read, including zero, does not |
| 31 | /// indicate end of stream. | 28 | /// indicate end of stream. |
| 32 | /// | 29 | /// |
| 33 | /// If the reader has an internal seek position, it moves forward in accordance | 30 | /// If the reader has an internal seek position, it moves forward in |
| 34 | /// with the number of bytes return from this function. | 31 | /// accordance with the number of bytes return from this function. |
| 35 | /// | 32 | /// |
| 36 | /// The implementation should do a maximum of one underlying read call. | 33 | /// The implementation should do a maximum of one underlying read call. |
| 37 | /// | 34 | /// |
| 38 | /// If this is `null` it is equivalent to always returning | 35 | /// If `error.Unstreamable` is returned, the resource cannot be used via a |
| 39 | /// `error.Unstreamable`. | 36 | /// streaming reading interface. |
| 40 | streamRead: ?*const fn (ctx: ?*anyopaque, bw: *std.io.BufferedWriter, limit: Limit) anyerror!Status, | 37 | readv: *const fn (ctx: ?*anyopaque, data: []const []u8) anyerror!Status, |
| 41 | streamReadVec: ?*const fn (ctx: ?*anyopaque, data: []const []u8) anyerror!Status, | ||
| 42 | }; | 38 | }; |
| 43 | 39 | ||
| 44 | pub const Len = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(usize) - 1 } }); | 40 | pub const Len = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(usize) - 1 } }); |
| ... | @@ -60,42 +56,20 @@ pub const Limit = enum(usize) { | ... | @@ -60,42 +56,20 @@ pub const Limit = enum(usize) { |
| 60 | } | 56 | } |
| 61 | }; | 57 | }; |
| 62 | 58 | ||
| 63 | /// Returns total number of bytes written to `w`. | 59 | pub fn read(r: Reader, w: *std.io.BufferedWriter, limit: Limit) anyerror!Status { |
| 64 | pub fn readAll(r: Reader, w: *std.io.BufferedWriter) anyerror!usize { | 60 | return r.vtable.read(r.context, w, limit); |
| 65 | if (r.vtable.pread != null) { | ||
| 66 | return posReadAll(r, w) catch |err| switch (err) { | ||
| 67 | error.Unseekable => {}, | ||
| 68 | else => return err, | ||
| 69 | }; | ||
| 70 | } | ||
| 71 | return streamReadAll(r, w); | ||
| 72 | } | 61 | } |
| 73 | 62 | ||
| 74 | /// Returns total number of bytes written to `w`. | 63 | pub fn readv(r: Reader, data: []const []u8) anyerror!Status { |
| 75 | /// | 64 | return r.vtable.readv(r.context, data); |
| 76 | /// May return `error.Unseekable`, indicating this function cannot be used to | ||
| 77 | /// read from the reader. | ||
| 78 | pub fn posReadAll(r: Reader, w: *std.io.BufferedWriter, start_offset: u64) anyerror!usize { | ||
| 79 | const vtable_posRead = r.vtable.posRead.?; | ||
| 80 | var offset: u64 = start_offset; | ||
| 81 | while (true) { | ||
| 82 | const status = try vtable_posRead(r.context, w, .none, offset); | ||
| 83 | offset += status.len; | ||
| 84 | if (status.end) return @intCast(offset - start_offset); | ||
| 85 | } | ||
| 86 | } | 65 | } |
| 87 | 66 | ||
| 88 | /// Returns total number of bytes written to `w`. | 67 | /// Returns total number of bytes written to `w`. |
| 89 | pub fn streamRead(r: Reader, w: *std.io.BufferedWriter, limit: Limit) anyerror!Status { | 68 | pub fn readAll(r: Reader, w: *std.io.BufferedWriter) anyerror!usize { |
| 90 | return r.vtable.streamRead.?(r.context, w, limit); | 69 | const readFn = r.vtable.read; |
| 91 | } | ||
| 92 | |||
| 93 | /// Returns total number of bytes written to `w`. | ||
| 94 | pub fn streamReadAll(r: Reader, w: *std.io.BufferedWriter) anyerror!usize { | ||
| 95 | const vtable_streamRead = r.vtable.streamRead.?; | ||
| 96 | var offset: usize = 0; | 70 | var offset: usize = 0; |
| 97 | while (true) { | 71 | while (true) { |
| 98 | const status = try vtable_streamRead(r.context, w, .none); | 72 | const status = try readFn(r.context, w, .none); |
| 99 | offset += status.len; | 73 | offset += status.len; |
| 100 | if (status.end) return offset; | 74 | if (status.end) return offset; |
| 101 | } | 75 | } |
| ... | @@ -107,42 +81,28 @@ pub fn streamReadAll(r: Reader, w: *std.io.BufferedWriter) anyerror!usize { | ... | @@ -107,42 +81,28 @@ pub fn streamReadAll(r: Reader, w: *std.io.BufferedWriter) anyerror!usize { |
| 107 | /// Caller owns returned memory. | 81 | /// Caller owns returned memory. |
| 108 | /// | 82 | /// |
| 109 | /// If this function returns an error, the contents from the stream read so far are lost. | 83 | /// If this function returns an error, the contents from the stream read so far are lost. |
| 110 | pub fn streamReadAlloc(r: Reader, gpa: std.mem.Allocator, max_size: usize) anyerror![]u8 { | 84 | pub fn readAlloc(r: Reader, gpa: std.mem.Allocator, max_size: usize) anyerror![]u8 { |
| 111 | const vtable_streamRead = r.vtable.streamRead.?; | 85 | const readFn = r.vtable.read; |
| 112 | 86 | var aw: std.io.AllocatingWriter = undefined; | |
| 113 | var bw: std.io.BufferedWriter = .{ | 87 | errdefer aw.deinit(); |
| 114 | .buffer = .empty, | 88 | const bw = aw.init(gpa); |
| 115 | .mode = .{ .allocator = gpa }, | ||
| 116 | }; | ||
| 117 | const list = &bw.buffer; | ||
| 118 | defer list.deinit(gpa); | ||
| 119 | |||
| 120 | var remaining = max_size; | 89 | var remaining = max_size; |
| 121 | while (remaining > 0) { | 90 | while (remaining > 0) { |
| 122 | const status = try vtable_streamRead(r.context, &bw, .init(remaining)); | 91 | const status = try readFn(r.context, bw, .init(remaining)); |
| 123 | if (status.end) return list.toOwnedSlice(gpa); | 92 | if (status.end) break; |
| 124 | remaining -= status.len; | 93 | remaining -= status.len; |
| 125 | } | 94 | } |
| 95 | return aw.toOwnedSlice(gpa); | ||
| 126 | } | 96 | } |
| 127 | 97 | ||
| 128 | /// Reads the stream until the end, ignoring all the data. | 98 | /// Reads the stream until the end, ignoring all the data. |
| 129 | /// Returns the number of bytes discarded. | 99 | /// Returns the number of bytes discarded. |
| 130 | pub fn discardUntilEnd(r: Reader) anyerror!usize { | 100 | pub fn discardUntilEnd(r: Reader) anyerror!usize { |
| 131 | var bw = std.io.null_writer.unbuffered(); | 101 | var bw = std.io.null_writer.unbuffered(); |
| 132 | return streamReadAll(r, &bw); | 102 | return readAll(r, &bw); |
| 133 | } | ||
| 134 | |||
| 135 | pub fn allocating(r: Reader, gpa: std.mem.Allocator) std.io.BufferedReader { | ||
| 136 | return .{ | ||
| 137 | .reader = r, | ||
| 138 | .buffered_writer = .{ | ||
| 139 | .buffer = .empty, | ||
| 140 | .mode = .{ .allocator = gpa }, | ||
| 141 | }, | ||
| 142 | }; | ||
| 143 | } | 103 | } |
| 144 | 104 | ||
| 145 | test "when the backing reader provides one byte at a time" { | 105 | test "readAlloc when the backing reader provides one byte at a time" { |
| 146 | const OneByteReader = struct { | 106 | const OneByteReader = struct { |
| 147 | str: []const u8, | 107 | str: []const u8, |
| 148 | curr: usize, | 108 | curr: usize, |
lib/std/zon/stringify.zig+1-1| ... | @@ -434,7 +434,7 @@ pub const SerializeContainerOptions = struct { | ... | @@ -434,7 +434,7 @@ pub const SerializeContainerOptions = struct { |
| 434 | /// * `beginStruct` | 434 | /// * `beginStruct` |
| 435 | /// * `beginTuple` | 435 | /// * `beginTuple` |
| 436 | pub const Serializer = struct { | 436 | pub const Serializer = struct { |
| 437 | options: Options, | 437 | options: Options = .{}, |
| 438 | indent_level: u8 = 0, | 438 | indent_level: u8 = 0, |
| 439 | writer: *std.io.BufferedWriter, | 439 | writer: *std.io.BufferedWriter, |
| 440 | 440 |