mirror of
https://github.com/ziglang/zig.git
synced 2025-12-07 14:53:08 +00:00
This eliminates some simple usages of `usingnamespace` in the standard library. This construct may in future be removed from the language, and is generally an inappropriate way to formulate code. It is also problematic for incremental compilation, which may not initially support projects using it. I wasn't entirely sure what the appropriate namespacing for the types in `std.os.uefi.tables` would be, so I ofted to preserve the current namespacing, meaning this is not a breaking change. It's possible some of the moved types should instead be namespaced under `BootServices` etc, but this can be a future enhancement.
117 lines
3.5 KiB
Zig
117 lines
3.5 KiB
Zig
const std = @import("../std.zig");
|
|
const assert = std.debug.assert;
|
|
const io = std.io;
|
|
const mem = std.mem;
|
|
const testing = std.testing;
|
|
|
|
/// Creates a stream which supports 'un-reading' data, so that it can be read again.
|
|
/// This makes look-ahead style parsing much easier.
|
|
/// TODO merge this with `std.io.BufferedReader`: https://github.com/ziglang/zig/issues/4501
|
|
pub fn PeekStream(
|
|
comptime buffer_type: std.fifo.LinearFifoBufferType,
|
|
comptime ReaderType: type,
|
|
) type {
|
|
return struct {
|
|
unbuffered_reader: ReaderType,
|
|
fifo: FifoType,
|
|
|
|
pub const Error = ReaderType.Error;
|
|
pub const Reader = io.Reader(*Self, Error, read);
|
|
|
|
const Self = @This();
|
|
const FifoType = std.fifo.LinearFifo(u8, buffer_type);
|
|
|
|
pub const init = switch (buffer_type) {
|
|
.Static => initStatic,
|
|
.Slice => initSlice,
|
|
.Dynamic => initDynamic,
|
|
};
|
|
|
|
fn initStatic(base: ReaderType) Self {
|
|
comptime assert(buffer_type == .Static);
|
|
return .{
|
|
.unbuffered_reader = base,
|
|
.fifo = FifoType.init(),
|
|
};
|
|
}
|
|
|
|
fn initSlice(base: ReaderType, buf: []u8) Self {
|
|
comptime assert(buffer_type == .Slice);
|
|
return .{
|
|
.unbuffered_reader = base,
|
|
.fifo = FifoType.init(buf),
|
|
};
|
|
}
|
|
|
|
fn initDynamic(base: ReaderType, allocator: mem.Allocator) Self {
|
|
comptime assert(buffer_type == .Dynamic);
|
|
return .{
|
|
.unbuffered_reader = base,
|
|
.fifo = FifoType.init(allocator),
|
|
};
|
|
}
|
|
|
|
pub fn putBackByte(self: *Self, byte: u8) !void {
|
|
try self.putBack(&[_]u8{byte});
|
|
}
|
|
|
|
pub fn putBack(self: *Self, bytes: []const u8) !void {
|
|
try self.fifo.unget(bytes);
|
|
}
|
|
|
|
pub fn read(self: *Self, dest: []u8) Error!usize {
|
|
// copy over anything putBack()'d
|
|
var dest_index = self.fifo.read(dest);
|
|
if (dest_index == dest.len) return dest_index;
|
|
|
|
// ask the backing stream for more
|
|
dest_index += try self.unbuffered_reader.read(dest[dest_index..]);
|
|
return dest_index;
|
|
}
|
|
|
|
pub fn reader(self: *Self) Reader {
|
|
return .{ .context = self };
|
|
}
|
|
};
|
|
}
|
|
|
|
pub fn peekStream(
|
|
comptime lookahead: comptime_int,
|
|
underlying_stream: anytype,
|
|
) PeekStream(.{ .Static = lookahead }, @TypeOf(underlying_stream)) {
|
|
return PeekStream(.{ .Static = lookahead }, @TypeOf(underlying_stream)).init(underlying_stream);
|
|
}
|
|
|
|
test "PeekStream" {
|
|
const bytes = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
|
|
var fbs = io.fixedBufferStream(&bytes);
|
|
var ps = peekStream(2, fbs.reader());
|
|
|
|
var dest: [4]u8 = undefined;
|
|
|
|
try ps.putBackByte(9);
|
|
try ps.putBackByte(10);
|
|
|
|
var read = try ps.reader().read(dest[0..4]);
|
|
try testing.expect(read == 4);
|
|
try testing.expect(dest[0] == 10);
|
|
try testing.expect(dest[1] == 9);
|
|
try testing.expect(mem.eql(u8, dest[2..4], bytes[0..2]));
|
|
|
|
read = try ps.reader().read(dest[0..4]);
|
|
try testing.expect(read == 4);
|
|
try testing.expect(mem.eql(u8, dest[0..4], bytes[2..6]));
|
|
|
|
read = try ps.reader().read(dest[0..4]);
|
|
try testing.expect(read == 2);
|
|
try testing.expect(mem.eql(u8, dest[0..2], bytes[6..8]));
|
|
|
|
try ps.putBackByte(11);
|
|
try ps.putBackByte(12);
|
|
|
|
read = try ps.reader().read(dest[0..4]);
|
|
try testing.expect(read == 2);
|
|
try testing.expect(dest[0] == 12);
|
|
try testing.expect(dest[1] == 11);
|
|
}
|