|
context: *const anyopaque, readFn: *const fn (context: *const anyopaque, buffer: []u8) anyerror!usize, |
Error |
pub const Error = anyerror; |
read()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) anyerror!usize { return self.readFn(self.context, buffer); } |
readAll() Returns the number of bytes read. If the number read is smaller than |
pub fn readAll(self: Self, buffer: []u8) anyerror!usize { return readAtLeast(self, buffer, buffer.len); } |
readAtLeast() Returns the number of bytes read, calling the underlying read function the minimal number of times until the buffer has at least |
pub fn readAtLeast(self: Self, buffer: []u8, len: usize) anyerror!usize { assert(len <= buffer.len); var index: usize = 0; while (index < len) { const amt = try self.read(buffer[index..]); if (amt == 0) break; index += amt; } return index; } |
readNoEof() If the number read would be smaller than |
pub fn readNoEof(self: Self, buf: []u8) anyerror!void { const amt_read = try self.readAll(buf); if (amt_read < buf.len) return error.EndOfStream; } |
readAllArrayList() Appends to the |
pub fn readAllArrayList( self: Self, array_list: *std.ArrayList(u8), max_append_size: usize, ) anyerror!void { return self.readAllArrayListAligned(null, array_list, max_append_size); } |
readAllArrayListAligned() |
pub fn readAllArrayListAligned( self: Self, comptime alignment: ?u29, array_list: *std.ArrayListAligned(u8, alignment), max_append_size: usize, ) anyerror!void { try array_list.ensureTotalCapacity(@min(max_append_size, 4096)); const original_len = array_list.items.len; var start_index: usize = original_len; while (true) { array_list.expandToCapacity(); const dest_slice = array_list.items[start_index..]; const bytes_read = try self.readAll(dest_slice); start_index += bytes_read; if (start_index - original_len > max_append_size) { array_list.shrinkAndFree(original_len + max_append_size); return error.StreamTooLong; } if (bytes_read != dest_slice.len) { array_list.shrinkAndFree(start_index); return; } // This will trigger ArrayList to expand superlinearly at whatever its growth rate is. try array_list.ensureTotalCapacity(start_index + 1); } } |
readAllAlloc() Allocates enough memory to hold all the contents of the stream. If the allocated memory would be greater than |
pub fn readAllAlloc(self: Self, allocator: mem.Allocator, max_size: usize) anyerror![]u8 { var array_list = std.ArrayList(u8).init(allocator); defer array_list.deinit(); try self.readAllArrayList(&array_list, max_size); return try array_list.toOwnedSlice(); } |
readUntilDelimiterArrayList() Deprecated: use |
pub fn readUntilDelimiterArrayList( self: Self, array_list: *std.ArrayList(u8), delimiter: u8, max_size: usize, ) anyerror!void { array_list.shrinkRetainingCapacity(0); try self.streamUntilDelimiter(array_list.writer(), delimiter, max_size); } |
readUntilDelimiterAlloc() Deprecated: use |
pub fn readUntilDelimiterAlloc( self: Self, allocator: mem.Allocator, delimiter: u8, max_size: usize, ) anyerror![]u8 { var array_list = std.ArrayList(u8).init(allocator); defer array_list.deinit(); try self.streamUntilDelimiter(array_list.writer(), delimiter, max_size); return try array_list.toOwnedSlice(); } |
readUntilDelimiter() Deprecated: use |
pub fn readUntilDelimiter(self: Self, buf: []u8, delimiter: u8) anyerror![]u8 { var fbs = std.io.fixedBufferStream(buf); try self.streamUntilDelimiter(fbs.writer(), delimiter, fbs.buffer.len); const output = fbs.getWritten(); buf[output.len] = delimiter; // emulating old behaviour return output; } |
readUntilDelimiterOrEofAlloc() Deprecated: use |
pub fn readUntilDelimiterOrEofAlloc( self: Self, allocator: mem.Allocator, delimiter: u8, max_size: usize, ) anyerror!?[]u8 { var array_list = std.ArrayList(u8).init(allocator); defer array_list.deinit(); self.streamUntilDelimiter(array_list.writer(), delimiter, max_size) catch |err| switch (err) { error.EndOfStream => if (array_list.items.len == 0) { return null; }, else => |e| return e, }; return try array_list.toOwnedSlice(); } |
readUntilDelimiterOrEof() Deprecated: use |
pub fn readUntilDelimiterOrEof(self: Self, buf: []u8, delimiter: u8) anyerror!?[]u8 { var fbs = std.io.fixedBufferStream(buf); self.streamUntilDelimiter(fbs.writer(), delimiter, fbs.buffer.len) catch |err| switch (err) { error.EndOfStream => if (fbs.getWritten().len == 0) { return null; }, else => |e| return e, }; const output = fbs.getWritten(); buf[output.len] = delimiter; // emulating old behaviour return output; } |
streamUntilDelimiter() Appends to the |
pub fn streamUntilDelimiter( self: Self, writer: anytype, delimiter: u8, optional_max_size: ?usize, ) anyerror!void { if (optional_max_size) |max_size| { for (0..max_size) |_| { const byte: u8 = try self.readByte(); if (byte == delimiter) return; try writer.writeByte(byte); } return error.StreamTooLong; } else { while (true) { const byte: u8 = try self.readByte(); if (byte == delimiter) return; try writer.writeByte(byte); } // Can not throw `error.StreamTooLong` since there are no boundary. } } |
skipUntilDelimiterOrEof()Reads from the stream until specified byte is found, discarding all data, including the delimiter. If end-of-stream is found, this function succeeds. |
pub fn skipUntilDelimiterOrEof(self: Self, delimiter: u8) anyerror!void { while (true) { const byte = self.readByte() catch |err| switch (err) { error.EndOfStream => return, else => |e| return e, }; if (byte == delimiter) return; } } |
readByte() Reads 1 byte from the stream or returns |
pub fn readByte(self: Self) anyerror!u8 { var result: [1]u8 = undefined; const amt_read = try self.read(result[0..]); if (amt_read < 1) return error.EndOfStream; return result[0]; } |
readByteSigned() Same as |
pub fn readByteSigned(self: Self) anyerror!i8 { return @as(i8, @bitCast(try self.readByte())); } |
readBytesNoEof() Reads exactly |
pub fn readBytesNoEof(self: Self, comptime num_bytes: usize) anyerror![num_bytes]u8 { var bytes: [num_bytes]u8 = undefined; try self.readNoEof(&bytes); return bytes; } |
readIntoBoundedBytes() Reads bytes until |
pub fn readIntoBoundedBytes( self: Self, comptime num_bytes: usize, bounded: *std.BoundedArray(u8, num_bytes), ) anyerror!void { while (bounded.len < num_bytes) { // get at most the number of bytes free in the bounded array const bytes_read = try self.read(bounded.unusedCapacitySlice()); if (bytes_read == 0) return; // bytes_read will never be larger than @TypeOf(bounded.len) // due to `self.read` being bounded by `bounded.unusedCapacitySlice()` bounded.len += @as(@TypeOf(bounded.len), @intCast(bytes_read)); } } |
readBoundedBytes() Reads at most |
pub fn readBoundedBytes(self: Self, comptime num_bytes: usize) anyerror!std.BoundedArray(u8, num_bytes) { var result = std.BoundedArray(u8, num_bytes){}; try self.readIntoBoundedBytes(num_bytes, &result); return result; } |
readInt() |
pub inline fn readInt(self: Self, comptime T: type, endian: std.builtin.Endian) anyerror!T { const bytes = try self.readBytesNoEof(@divExact(@typeInfo(T).Int.bits, 8)); return mem.readInt(T, &bytes, endian); } |
readVarInt() |
pub fn readVarInt( self: Self, comptime ReturnType: type, endian: std.builtin.Endian, size: usize, ) anyerror!ReturnType { assert(size <= @sizeOf(ReturnType)); var bytes_buf: [@sizeOf(ReturnType)]u8 = undefined; const bytes = bytes_buf[0..size]; try self.readNoEof(bytes); return mem.readVarInt(ReturnType, bytes, endian); } |
SkipBytesOptions Optional parameters for |
pub const SkipBytesOptions = struct { buf_size: usize = 512, }; // `num_bytes` is a `u64` to match `off_t` |
skipBytes() Reads |
pub fn skipBytes(self: Self, num_bytes: u64, comptime options: SkipBytesOptions) anyerror!void { var buf: [options.buf_size]u8 = undefined; var remaining = num_bytes; while (remaining > 0) { const amt = @min(remaining, options.buf_size); try self.readNoEof(buf[0..amt]); remaining -= amt; } } |
isBytes() Reads |
pub fn isBytes(self: Self, slice: []const u8) anyerror!bool { var i: usize = 0; var matches = true; while (i < slice.len) : (i += 1) { if (slice[i] != try self.readByte()) { matches = false; } } return matches; } |
readStruct() |
pub fn readStruct(self: Self, comptime T: type) anyerror!T { // Only extern and packed structs have defined in-memory layout. comptime assert(@typeInfo(T).Struct.layout != .Auto); var res: [1]T = undefined; try self.readNoEof(mem.sliceAsBytes(res[0..])); return res[0]; } |
readStructBig() |
pub fn readStructBig(self: Self, comptime T: type) anyerror!T { var res = try self.readStruct(T); if (native_endian != std.builtin.Endian.big) { mem.byteSwapAllFields(T, &res); } return res; } |
readEnum() Reads an integer with the same size as the given enum's tag type. If the integer matches an enum tag, casts the integer to the enum tag and returns it. Otherwise, returns an |
pub fn readEnum(self: Self, comptime Enum: type, endian: std.builtin.Endian) anyerror!Enum { const E = error{ InvalidValue, }; const type_info = @typeInfo(Enum).Enum; const tag = try self.readInt(type_info.tag_type, endian); inline for (std.meta.fields(Enum)) |field| { if (tag == field.value) { return @field(Enum, field.name); } } return E.InvalidValue; } const std = @import("../std.zig"); const Self = @This(); const math = std.math; const assert = std.debug.assert; const mem = std.mem; const testing = std.testing; const native_endian = @import("builtin").target.cpu.arch.endian(); test { _ = @import("Reader/test.zig"); } |
Generated by zstd-browse2 on 2023-11-04 14:12:29 -0400. |