mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
std: delete most remaining uses of GenericWriter
This commit is contained in:
parent
8f4cb4614f
commit
9860dd475a
@ -144,48 +144,6 @@ pub fn GenericReader(
|
||||
return @errorCast(self.any().readAllAlloc(allocator, max_size));
|
||||
}
|
||||
|
||||
pub inline fn readUntilDelimiterAlloc(
|
||||
self: Self,
|
||||
allocator: Allocator,
|
||||
delimiter: u8,
|
||||
max_size: usize,
|
||||
) (NoEofError || Allocator.Error || error{StreamTooLong})![]u8 {
|
||||
return @errorCast(self.any().readUntilDelimiterAlloc(
|
||||
allocator,
|
||||
delimiter,
|
||||
max_size,
|
||||
));
|
||||
}
|
||||
|
||||
pub inline fn readUntilDelimiter(
|
||||
self: Self,
|
||||
buf: []u8,
|
||||
delimiter: u8,
|
||||
) (NoEofError || error{StreamTooLong})![]u8 {
|
||||
return @errorCast(self.any().readUntilDelimiter(buf, delimiter));
|
||||
}
|
||||
|
||||
pub inline fn readUntilDelimiterOrEofAlloc(
|
||||
self: Self,
|
||||
allocator: Allocator,
|
||||
delimiter: u8,
|
||||
max_size: usize,
|
||||
) (Error || Allocator.Error || error{StreamTooLong})!?[]u8 {
|
||||
return @errorCast(self.any().readUntilDelimiterOrEofAlloc(
|
||||
allocator,
|
||||
delimiter,
|
||||
max_size,
|
||||
));
|
||||
}
|
||||
|
||||
pub inline fn readUntilDelimiterOrEof(
|
||||
self: Self,
|
||||
buf: []u8,
|
||||
delimiter: u8,
|
||||
) (Error || error{StreamTooLong})!?[]u8 {
|
||||
return @errorCast(self.any().readUntilDelimiterOrEof(buf, delimiter));
|
||||
}
|
||||
|
||||
pub inline fn streamUntilDelimiter(
|
||||
self: Self,
|
||||
writer: anytype,
|
||||
|
||||
@ -290,7 +290,3 @@ const mem = std.mem;
|
||||
const testing = std.testing;
|
||||
const native_endian = @import("builtin").target.cpu.arch.endian();
|
||||
const Alignment = std.mem.Alignment;
|
||||
|
||||
test {
|
||||
_ = @import("Reader/test.zig");
|
||||
}
|
||||
|
||||
@ -1,351 +0,0 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("../../std.zig");
|
||||
const testing = std.testing;
|
||||
|
||||
test "Reader" {
|
||||
var buf = "a\x02".*;
|
||||
var fis = std.io.fixedBufferStream(&buf);
|
||||
const reader = fis.reader();
|
||||
try testing.expect((try reader.readByte()) == 'a');
|
||||
try testing.expect((try reader.readEnum(enum(u8) {
|
||||
a = 0,
|
||||
b = 99,
|
||||
c = 2,
|
||||
d = 3,
|
||||
}, builtin.cpu.arch.endian())) == .c);
|
||||
try testing.expectError(error.EndOfStream, reader.readByte());
|
||||
}
|
||||
|
||||
test "isBytes" {
|
||||
var fis = std.io.fixedBufferStream("foobar");
|
||||
const reader = fis.reader();
|
||||
try testing.expectEqual(true, try reader.isBytes("foo"));
|
||||
try testing.expectEqual(false, try reader.isBytes("qux"));
|
||||
}
|
||||
|
||||
test "skipBytes" {
|
||||
var fis = std.io.fixedBufferStream("foobar");
|
||||
const reader = fis.reader();
|
||||
try reader.skipBytes(3, .{});
|
||||
try testing.expect(try reader.isBytes("bar"));
|
||||
try reader.skipBytes(0, .{});
|
||||
try testing.expectError(error.EndOfStream, reader.skipBytes(1, .{}));
|
||||
}
|
||||
|
||||
test "readUntilDelimiterArrayList returns ArrayLists with bytes read until the delimiter, then EndOfStream" {
|
||||
const a = std.testing.allocator;
|
||||
var list = std.array_list.Managed(u8).init(a);
|
||||
defer list.deinit();
|
||||
|
||||
var fis = std.io.fixedBufferStream("0000\n1234\n");
|
||||
const reader = fis.reader();
|
||||
|
||||
try reader.readUntilDelimiterArrayList(&list, '\n', 5);
|
||||
try std.testing.expectEqualStrings("0000", list.items);
|
||||
try reader.readUntilDelimiterArrayList(&list, '\n', 5);
|
||||
try std.testing.expectEqualStrings("1234", list.items);
|
||||
try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterArrayList(&list, '\n', 5));
|
||||
}
|
||||
|
||||
test "readUntilDelimiterArrayList returns an empty ArrayList" {
|
||||
const a = std.testing.allocator;
|
||||
var list = std.array_list.Managed(u8).init(a);
|
||||
defer list.deinit();
|
||||
|
||||
var fis = std.io.fixedBufferStream("\n");
|
||||
const reader = fis.reader();
|
||||
|
||||
try reader.readUntilDelimiterArrayList(&list, '\n', 5);
|
||||
try std.testing.expectEqualStrings("", list.items);
|
||||
}
|
||||
|
||||
test "readUntilDelimiterArrayList returns StreamTooLong, then an ArrayList with bytes read until the delimiter" {
|
||||
const a = std.testing.allocator;
|
||||
var list = std.array_list.Managed(u8).init(a);
|
||||
defer list.deinit();
|
||||
|
||||
var fis = std.io.fixedBufferStream("1234567\n");
|
||||
const reader = fis.reader();
|
||||
|
||||
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterArrayList(&list, '\n', 5));
|
||||
try std.testing.expectEqualStrings("12345", list.items);
|
||||
try reader.readUntilDelimiterArrayList(&list, '\n', 5);
|
||||
try std.testing.expectEqualStrings("67", list.items);
|
||||
}
|
||||
|
||||
test "readUntilDelimiterArrayList returns EndOfStream" {
|
||||
const a = std.testing.allocator;
|
||||
var list = std.array_list.Managed(u8).init(a);
|
||||
defer list.deinit();
|
||||
|
||||
var fis = std.io.fixedBufferStream("1234");
|
||||
const reader = fis.reader();
|
||||
|
||||
try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterArrayList(&list, '\n', 5));
|
||||
try std.testing.expectEqualStrings("1234", list.items);
|
||||
}
|
||||
|
||||
test "readUntilDelimiterAlloc returns ArrayLists with bytes read until the delimiter, then EndOfStream" {
|
||||
const a = std.testing.allocator;
|
||||
|
||||
var fis = std.io.fixedBufferStream("0000\n1234\n");
|
||||
const reader = fis.reader();
|
||||
|
||||
{
|
||||
const result = try reader.readUntilDelimiterAlloc(a, '\n', 5);
|
||||
defer a.free(result);
|
||||
try std.testing.expectEqualStrings("0000", result);
|
||||
}
|
||||
|
||||
{
|
||||
const result = try reader.readUntilDelimiterAlloc(a, '\n', 5);
|
||||
defer a.free(result);
|
||||
try std.testing.expectEqualStrings("1234", result);
|
||||
}
|
||||
|
||||
try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterAlloc(a, '\n', 5));
|
||||
}
|
||||
|
||||
test "readUntilDelimiterAlloc returns an empty ArrayList" {
|
||||
const a = std.testing.allocator;
|
||||
|
||||
var fis = std.io.fixedBufferStream("\n");
|
||||
const reader = fis.reader();
|
||||
|
||||
{
|
||||
const result = try reader.readUntilDelimiterAlloc(a, '\n', 5);
|
||||
defer a.free(result);
|
||||
try std.testing.expectEqualStrings("", result);
|
||||
}
|
||||
}
|
||||
|
||||
test "readUntilDelimiterAlloc returns StreamTooLong, then an ArrayList with bytes read until the delimiter" {
|
||||
const a = std.testing.allocator;
|
||||
|
||||
var fis = std.io.fixedBufferStream("1234567\n");
|
||||
const reader = fis.reader();
|
||||
|
||||
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterAlloc(a, '\n', 5));
|
||||
|
||||
const result = try reader.readUntilDelimiterAlloc(a, '\n', 5);
|
||||
defer a.free(result);
|
||||
try std.testing.expectEqualStrings("67", result);
|
||||
}
|
||||
|
||||
test "readUntilDelimiterAlloc returns EndOfStream" {
|
||||
const a = std.testing.allocator;
|
||||
|
||||
var fis = std.io.fixedBufferStream("1234");
|
||||
const reader = fis.reader();
|
||||
|
||||
try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterAlloc(a, '\n', 5));
|
||||
}
|
||||
|
||||
test "readUntilDelimiter returns bytes read until the delimiter" {
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("0000\n1234\n");
|
||||
const reader = fis.reader();
|
||||
try std.testing.expectEqualStrings("0000", try reader.readUntilDelimiter(&buf, '\n'));
|
||||
try std.testing.expectEqualStrings("1234", try reader.readUntilDelimiter(&buf, '\n'));
|
||||
}
|
||||
|
||||
test "readUntilDelimiter returns an empty string" {
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("\n");
|
||||
const reader = fis.reader();
|
||||
try std.testing.expectEqualStrings("", try reader.readUntilDelimiter(&buf, '\n'));
|
||||
}
|
||||
|
||||
test "readUntilDelimiter returns StreamTooLong, then an empty string" {
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("12345\n");
|
||||
const reader = fis.reader();
|
||||
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n'));
|
||||
try std.testing.expectEqualStrings("", try reader.readUntilDelimiter(&buf, '\n'));
|
||||
}
|
||||
|
||||
test "readUntilDelimiter returns StreamTooLong, then bytes read until the delimiter" {
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("1234567\n");
|
||||
const reader = fis.reader();
|
||||
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n'));
|
||||
try std.testing.expectEqualStrings("67", try reader.readUntilDelimiter(&buf, '\n'));
|
||||
}
|
||||
|
||||
test "readUntilDelimiter returns EndOfStream" {
|
||||
{
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("");
|
||||
const reader = fis.reader();
|
||||
try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
|
||||
}
|
||||
{
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("1234");
|
||||
const reader = fis.reader();
|
||||
try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
|
||||
}
|
||||
}
|
||||
|
||||
test "readUntilDelimiter returns bytes read until delimiter, then EndOfStream" {
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("1234\n");
|
||||
const reader = fis.reader();
|
||||
try std.testing.expectEqualStrings("1234", try reader.readUntilDelimiter(&buf, '\n'));
|
||||
try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
|
||||
}
|
||||
|
||||
test "readUntilDelimiter returns StreamTooLong, then EndOfStream" {
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("12345");
|
||||
const reader = fis.reader();
|
||||
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n'));
|
||||
try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
|
||||
}
|
||||
|
||||
test "readUntilDelimiter writes all bytes read to the output buffer" {
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("0000\n12345");
|
||||
const reader = fis.reader();
|
||||
_ = try reader.readUntilDelimiter(&buf, '\n');
|
||||
try std.testing.expectEqualStrings("0000\n", &buf);
|
||||
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n'));
|
||||
try std.testing.expectEqualStrings("12345", &buf);
|
||||
}
|
||||
|
||||
test "readUntilDelimiterOrEofAlloc returns ArrayLists with bytes read until the delimiter, then EndOfStream" {
|
||||
const a = std.testing.allocator;
|
||||
|
||||
var fis = std.io.fixedBufferStream("0000\n1234\n");
|
||||
const reader = fis.reader();
|
||||
|
||||
{
|
||||
const result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?;
|
||||
defer a.free(result);
|
||||
try std.testing.expectEqualStrings("0000", result);
|
||||
}
|
||||
|
||||
{
|
||||
const result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?;
|
||||
defer a.free(result);
|
||||
try std.testing.expectEqualStrings("1234", result);
|
||||
}
|
||||
|
||||
try std.testing.expect((try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)) == null);
|
||||
}
|
||||
|
||||
test "readUntilDelimiterOrEofAlloc returns an empty ArrayList" {
|
||||
const a = std.testing.allocator;
|
||||
|
||||
var fis = std.io.fixedBufferStream("\n");
|
||||
const reader = fis.reader();
|
||||
|
||||
{
|
||||
const result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?;
|
||||
defer a.free(result);
|
||||
try std.testing.expectEqualStrings("", result);
|
||||
}
|
||||
}
|
||||
|
||||
test "readUntilDelimiterOrEofAlloc returns StreamTooLong, then an ArrayList with bytes read until the delimiter" {
|
||||
const a = std.testing.allocator;
|
||||
|
||||
var fis = std.io.fixedBufferStream("1234567\n");
|
||||
const reader = fis.reader();
|
||||
|
||||
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEofAlloc(a, '\n', 5));
|
||||
|
||||
const result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?;
|
||||
defer a.free(result);
|
||||
try std.testing.expectEqualStrings("67", result);
|
||||
}
|
||||
|
||||
test "readUntilDelimiterOrEof returns bytes read until the delimiter" {
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("0000\n1234\n");
|
||||
const reader = fis.reader();
|
||||
try std.testing.expectEqualStrings("0000", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
|
||||
try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
|
||||
}
|
||||
|
||||
test "readUntilDelimiterOrEof returns an empty string" {
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("\n");
|
||||
const reader = fis.reader();
|
||||
try std.testing.expectEqualStrings("", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
|
||||
}
|
||||
|
||||
test "readUntilDelimiterOrEof returns StreamTooLong, then an empty string" {
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("12345\n");
|
||||
const reader = fis.reader();
|
||||
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n'));
|
||||
try std.testing.expectEqualStrings("", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
|
||||
}
|
||||
|
||||
test "readUntilDelimiterOrEof returns StreamTooLong, then bytes read until the delimiter" {
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("1234567\n");
|
||||
const reader = fis.reader();
|
||||
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n'));
|
||||
try std.testing.expectEqualStrings("67", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
|
||||
}
|
||||
|
||||
test "readUntilDelimiterOrEof returns null" {
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("");
|
||||
const reader = fis.reader();
|
||||
try std.testing.expect((try reader.readUntilDelimiterOrEof(&buf, '\n')) == null);
|
||||
}
|
||||
|
||||
test "readUntilDelimiterOrEof returns bytes read until delimiter, then null" {
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("1234\n");
|
||||
const reader = fis.reader();
|
||||
try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
|
||||
try std.testing.expect((try reader.readUntilDelimiterOrEof(&buf, '\n')) == null);
|
||||
}
|
||||
|
||||
test "readUntilDelimiterOrEof returns bytes read until end-of-stream" {
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("1234");
|
||||
const reader = fis.reader();
|
||||
try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
|
||||
}
|
||||
|
||||
test "readUntilDelimiterOrEof returns StreamTooLong, then bytes read until end-of-stream" {
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("1234567");
|
||||
const reader = fis.reader();
|
||||
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n'));
|
||||
try std.testing.expectEqualStrings("67", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
|
||||
}
|
||||
|
||||
test "readUntilDelimiterOrEof writes all bytes read to the output buffer" {
|
||||
var buf: [5]u8 = undefined;
|
||||
var fis = std.io.fixedBufferStream("0000\n12345");
|
||||
const reader = fis.reader();
|
||||
_ = try reader.readUntilDelimiterOrEof(&buf, '\n');
|
||||
try std.testing.expectEqualStrings("0000\n", &buf);
|
||||
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n'));
|
||||
try std.testing.expectEqualStrings("12345", &buf);
|
||||
}
|
||||
|
||||
test "streamUntilDelimiter writes all bytes without delimiter to the output" {
|
||||
const input_string = "some_string_with_delimiter!";
|
||||
var input_fbs = std.io.fixedBufferStream(input_string);
|
||||
const reader = input_fbs.reader();
|
||||
|
||||
var output: [input_string.len]u8 = undefined;
|
||||
var output_fbs = std.io.fixedBufferStream(&output);
|
||||
const writer = output_fbs.writer();
|
||||
|
||||
try reader.streamUntilDelimiter(writer, '!', input_fbs.buffer.len);
|
||||
try std.testing.expectEqualStrings("some_string_with_delimiter", output_fbs.getWritten());
|
||||
try std.testing.expectError(error.EndOfStream, reader.streamUntilDelimiter(writer, '!', input_fbs.buffer.len));
|
||||
|
||||
input_fbs.reset();
|
||||
output_fbs.reset();
|
||||
|
||||
try std.testing.expectError(error.StreamTooLong, reader.streamUntilDelimiter(writer, '!', 5));
|
||||
}
|
||||
@ -167,7 +167,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void {
|
||||
const file = try std.fs.cwd().openFile(path, .{ .mode = .write_only });
|
||||
defer file.close();
|
||||
|
||||
try file.deprecatedWriter().writeAll(name);
|
||||
try file.writeAll(name);
|
||||
return;
|
||||
},
|
||||
.windows => {
|
||||
|
||||
@ -2041,60 +2041,6 @@ test "Managed(T) of struct T" {
|
||||
}
|
||||
}
|
||||
|
||||
test "Managed(u8) implements writer" {
|
||||
const a = testing.allocator;
|
||||
|
||||
{
|
||||
var buffer = Managed(u8).init(a);
|
||||
defer buffer.deinit();
|
||||
|
||||
const x: i32 = 42;
|
||||
const y: i32 = 1234;
|
||||
try buffer.writer().print("x: {}\ny: {}\n", .{ x, y });
|
||||
|
||||
try testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.items);
|
||||
}
|
||||
{
|
||||
var list = AlignedManaged(u8, .@"2").init(a);
|
||||
defer list.deinit();
|
||||
|
||||
const writer = list.writer();
|
||||
try writer.writeAll("a");
|
||||
try writer.writeAll("bc");
|
||||
try writer.writeAll("d");
|
||||
try writer.writeAll("efg");
|
||||
|
||||
try testing.expectEqualSlices(u8, list.items, "abcdefg");
|
||||
}
|
||||
}
|
||||
|
||||
test "ArrayList(u8) implements writer" {
|
||||
const a = testing.allocator;
|
||||
|
||||
{
|
||||
var buffer: ArrayList(u8) = .empty;
|
||||
defer buffer.deinit(a);
|
||||
|
||||
const x: i32 = 42;
|
||||
const y: i32 = 1234;
|
||||
try buffer.writer(a).print("x: {}\ny: {}\n", .{ x, y });
|
||||
|
||||
try testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.items);
|
||||
}
|
||||
{
|
||||
var list: Aligned(u8, .@"2") = .empty;
|
||||
defer list.deinit(a);
|
||||
|
||||
const writer = list.writer(a);
|
||||
try writer.writeAll("a");
|
||||
try writer.writeAll("bc");
|
||||
try writer.writeAll("d");
|
||||
try writer.writeAll("efg");
|
||||
|
||||
try testing.expectEqualSlices(u8, list.items, "abcdefg");
|
||||
}
|
||||
}
|
||||
|
||||
test "shrink still sets length when resizing is disabled" {
|
||||
var failing_allocator = testing.FailingAllocator.init(testing.allocator, .{ .resize_fail_index = 0 });
|
||||
const a = failing_allocator.allocator();
|
||||
|
||||
@ -304,31 +304,34 @@ const crypt_format = struct {
|
||||
|
||||
/// Serialize parameters into a string in modular crypt format.
|
||||
pub fn serialize(params: anytype, str: []u8) EncodingError![]const u8 {
|
||||
var buf = io.fixedBufferStream(str);
|
||||
try serializeTo(params, buf.writer());
|
||||
return buf.getWritten();
|
||||
var w: std.Io.Writer = .fixed(str);
|
||||
serializeTo(params, &w) catch |err| switch (err) {
|
||||
error.WriteFailed => return error.NoSpaceLeft,
|
||||
else => |e| return e,
|
||||
};
|
||||
return w.buffered();
|
||||
}
|
||||
|
||||
/// Compute the number of bytes required to serialize `params`
|
||||
pub fn calcSize(params: anytype) usize {
|
||||
var trash: [128]u8 = undefined;
|
||||
var d: std.Io.Writer.Discarding = .init(&trash);
|
||||
serializeTo(params, &d) catch unreachable;
|
||||
serializeTo(params, &d.writer) catch unreachable;
|
||||
return @intCast(d.fullCount());
|
||||
}
|
||||
|
||||
fn serializeTo(params: anytype, out: anytype) !void {
|
||||
fn serializeTo(params: anytype, w: *std.Io.Writer) !void {
|
||||
var header: [14]u8 = undefined;
|
||||
header[0..3].* = prefix.*;
|
||||
Codec.intEncode(header[3..4], params.ln);
|
||||
Codec.intEncode(header[4..9], params.r);
|
||||
Codec.intEncode(header[9..14], params.p);
|
||||
try out.writeAll(&header);
|
||||
try out.writeAll(params.salt);
|
||||
try out.writeAll("$");
|
||||
try w.writeAll(&header);
|
||||
try w.writeAll(params.salt);
|
||||
try w.writeAll("$");
|
||||
var buf: [@TypeOf(params.hash).max_encoded_length]u8 = undefined;
|
||||
const hash_str = try params.hash.toB64(&buf);
|
||||
try out.writeAll(hash_str);
|
||||
try w.writeAll(hash_str);
|
||||
}
|
||||
|
||||
/// Custom codec that maps 6 bits into 8 like regular Base64, but uses its own alphabet,
|
||||
|
||||
@ -8,6 +8,8 @@ const OP = std.dwarf.OP;
|
||||
const abi = std.debug.Dwarf.abi;
|
||||
const mem = std.mem;
|
||||
const assert = std.debug.assert;
|
||||
const testing = std.testing;
|
||||
const Writer = std.Io.Writer;
|
||||
|
||||
/// Expressions can be evaluated in different contexts, each requiring its own set of inputs.
|
||||
/// Callers should specify all the fields relevant to their context. If a field is required
|
||||
@ -782,7 +784,7 @@ pub fn Builder(comptime options: Options) type {
|
||||
|
||||
return struct {
|
||||
/// Zero-operand instructions
|
||||
pub fn writeOpcode(writer: anytype, comptime opcode: u8) !void {
|
||||
pub fn writeOpcode(writer: *Writer, comptime opcode: u8) !void {
|
||||
if (options.call_frame_context and !comptime isOpcodeValidInCFA(opcode)) return error.InvalidCFAOpcode;
|
||||
switch (opcode) {
|
||||
OP.dup,
|
||||
@ -823,14 +825,14 @@ pub fn Builder(comptime options: Options) type {
|
||||
}
|
||||
|
||||
// 2.5.1.1: Literal Encodings
|
||||
pub fn writeLiteral(writer: anytype, literal: u8) !void {
|
||||
pub fn writeLiteral(writer: *Writer, literal: u8) !void {
|
||||
switch (literal) {
|
||||
0...31 => |n| try writer.writeByte(n + OP.lit0),
|
||||
else => return error.InvalidLiteral,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn writeConst(writer: anytype, comptime T: type, value: T) !void {
|
||||
pub fn writeConst(writer: *Writer, comptime T: type, value: T) !void {
|
||||
if (@typeInfo(T) != .int) @compileError("Constants must be integers");
|
||||
|
||||
switch (T) {
|
||||
@ -852,7 +854,7 @@ pub fn Builder(comptime options: Options) type {
|
||||
else => switch (@typeInfo(T).int.signedness) {
|
||||
.unsigned => {
|
||||
try writer.writeByte(OP.constu);
|
||||
try leb.writeUleb128(writer, value);
|
||||
try writer.writeUleb128(value);
|
||||
},
|
||||
.signed => {
|
||||
try writer.writeByte(OP.consts);
|
||||
@ -862,105 +864,105 @@ pub fn Builder(comptime options: Options) type {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn writeConstx(writer: anytype, debug_addr_offset: anytype) !void {
|
||||
pub fn writeConstx(writer: *Writer, debug_addr_offset: anytype) !void {
|
||||
try writer.writeByte(OP.constx);
|
||||
try leb.writeUleb128(writer, debug_addr_offset);
|
||||
try writer.writeUleb128(debug_addr_offset);
|
||||
}
|
||||
|
||||
pub fn writeConstType(writer: anytype, die_offset: anytype, value_bytes: []const u8) !void {
|
||||
pub fn writeConstType(writer: *Writer, die_offset: anytype, value_bytes: []const u8) !void {
|
||||
if (options.call_frame_context) return error.InvalidCFAOpcode;
|
||||
if (value_bytes.len > 0xff) return error.InvalidTypeLength;
|
||||
try writer.writeByte(OP.const_type);
|
||||
try leb.writeUleb128(writer, die_offset);
|
||||
try writer.writeUleb128(die_offset);
|
||||
try writer.writeByte(@intCast(value_bytes.len));
|
||||
try writer.writeAll(value_bytes);
|
||||
}
|
||||
|
||||
pub fn writeAddr(writer: anytype, value: addr_type) !void {
|
||||
pub fn writeAddr(writer: *Writer, value: addr_type) !void {
|
||||
try writer.writeByte(OP.addr);
|
||||
try writer.writeInt(addr_type, value, options.endian);
|
||||
}
|
||||
|
||||
pub fn writeAddrx(writer: anytype, debug_addr_offset: anytype) !void {
|
||||
pub fn writeAddrx(writer: *Writer, debug_addr_offset: anytype) !void {
|
||||
if (options.call_frame_context) return error.InvalidCFAOpcode;
|
||||
try writer.writeByte(OP.addrx);
|
||||
try leb.writeUleb128(writer, debug_addr_offset);
|
||||
try writer.writeUleb128(debug_addr_offset);
|
||||
}
|
||||
|
||||
// 2.5.1.2: Register Values
|
||||
pub fn writeFbreg(writer: anytype, offset: anytype) !void {
|
||||
pub fn writeFbreg(writer: *Writer, offset: anytype) !void {
|
||||
try writer.writeByte(OP.fbreg);
|
||||
try leb.writeIleb128(writer, offset);
|
||||
}
|
||||
|
||||
pub fn writeBreg(writer: anytype, register: u8, offset: anytype) !void {
|
||||
pub fn writeBreg(writer: *Writer, register: u8, offset: anytype) !void {
|
||||
if (register > 31) return error.InvalidRegister;
|
||||
try writer.writeByte(OP.breg0 + register);
|
||||
try leb.writeIleb128(writer, offset);
|
||||
}
|
||||
|
||||
pub fn writeBregx(writer: anytype, register: anytype, offset: anytype) !void {
|
||||
pub fn writeBregx(writer: *Writer, register: anytype, offset: anytype) !void {
|
||||
try writer.writeByte(OP.bregx);
|
||||
try leb.writeUleb128(writer, register);
|
||||
try writer.writeUleb128(register);
|
||||
try leb.writeIleb128(writer, offset);
|
||||
}
|
||||
|
||||
pub fn writeRegvalType(writer: anytype, register: anytype, offset: anytype) !void {
|
||||
pub fn writeRegvalType(writer: *Writer, register: anytype, offset: anytype) !void {
|
||||
if (options.call_frame_context) return error.InvalidCFAOpcode;
|
||||
try writer.writeByte(OP.regval_type);
|
||||
try leb.writeUleb128(writer, register);
|
||||
try leb.writeUleb128(writer, offset);
|
||||
try writer.writeUleb128(register);
|
||||
try writer.writeUleb128(offset);
|
||||
}
|
||||
|
||||
// 2.5.1.3: Stack Operations
|
||||
pub fn writePick(writer: anytype, index: u8) !void {
|
||||
pub fn writePick(writer: *Writer, index: u8) !void {
|
||||
try writer.writeByte(OP.pick);
|
||||
try writer.writeByte(index);
|
||||
}
|
||||
|
||||
pub fn writeDerefSize(writer: anytype, size: u8) !void {
|
||||
pub fn writeDerefSize(writer: *Writer, size: u8) !void {
|
||||
try writer.writeByte(OP.deref_size);
|
||||
try writer.writeByte(size);
|
||||
}
|
||||
|
||||
pub fn writeXDerefSize(writer: anytype, size: u8) !void {
|
||||
pub fn writeXDerefSize(writer: *Writer, size: u8) !void {
|
||||
try writer.writeByte(OP.xderef_size);
|
||||
try writer.writeByte(size);
|
||||
}
|
||||
|
||||
pub fn writeDerefType(writer: anytype, size: u8, die_offset: anytype) !void {
|
||||
pub fn writeDerefType(writer: *Writer, size: u8, die_offset: anytype) !void {
|
||||
if (options.call_frame_context) return error.InvalidCFAOpcode;
|
||||
try writer.writeByte(OP.deref_type);
|
||||
try writer.writeByte(size);
|
||||
try leb.writeUleb128(writer, die_offset);
|
||||
try writer.writeUleb128(die_offset);
|
||||
}
|
||||
|
||||
pub fn writeXDerefType(writer: anytype, size: u8, die_offset: anytype) !void {
|
||||
pub fn writeXDerefType(writer: *Writer, size: u8, die_offset: anytype) !void {
|
||||
try writer.writeByte(OP.xderef_type);
|
||||
try writer.writeByte(size);
|
||||
try leb.writeUleb128(writer, die_offset);
|
||||
try writer.writeUleb128(die_offset);
|
||||
}
|
||||
|
||||
// 2.5.1.4: Arithmetic and Logical Operations
|
||||
|
||||
pub fn writePlusUconst(writer: anytype, uint_value: anytype) !void {
|
||||
pub fn writePlusUconst(writer: *Writer, uint_value: anytype) !void {
|
||||
try writer.writeByte(OP.plus_uconst);
|
||||
try leb.writeUleb128(writer, uint_value);
|
||||
try writer.writeUleb128(uint_value);
|
||||
}
|
||||
|
||||
// 2.5.1.5: Control Flow Operations
|
||||
|
||||
pub fn writeSkip(writer: anytype, offset: i16) !void {
|
||||
pub fn writeSkip(writer: *Writer, offset: i16) !void {
|
||||
try writer.writeByte(OP.skip);
|
||||
try writer.writeInt(i16, offset, options.endian);
|
||||
}
|
||||
|
||||
pub fn writeBra(writer: anytype, offset: i16) !void {
|
||||
pub fn writeBra(writer: *Writer, offset: i16) !void {
|
||||
try writer.writeByte(OP.bra);
|
||||
try writer.writeInt(i16, offset, options.endian);
|
||||
}
|
||||
|
||||
pub fn writeCall(writer: anytype, comptime T: type, offset: T) !void {
|
||||
pub fn writeCall(writer: *Writer, comptime T: type, offset: T) !void {
|
||||
if (options.call_frame_context) return error.InvalidCFAOpcode;
|
||||
switch (T) {
|
||||
u16 => try writer.writeByte(OP.call2),
|
||||
@ -971,45 +973,45 @@ pub fn Builder(comptime options: Options) type {
|
||||
try writer.writeInt(T, offset, options.endian);
|
||||
}
|
||||
|
||||
pub fn writeCallRef(writer: anytype, comptime is_64: bool, value: if (is_64) u64 else u32) !void {
|
||||
pub fn writeCallRef(writer: *Writer, comptime is_64: bool, value: if (is_64) u64 else u32) !void {
|
||||
if (options.call_frame_context) return error.InvalidCFAOpcode;
|
||||
try writer.writeByte(OP.call_ref);
|
||||
try writer.writeInt(if (is_64) u64 else u32, value, options.endian);
|
||||
}
|
||||
|
||||
pub fn writeConvert(writer: anytype, die_offset: anytype) !void {
|
||||
pub fn writeConvert(writer: *Writer, die_offset: anytype) !void {
|
||||
if (options.call_frame_context) return error.InvalidCFAOpcode;
|
||||
try writer.writeByte(OP.convert);
|
||||
try leb.writeUleb128(writer, die_offset);
|
||||
try writer.writeUleb128(die_offset);
|
||||
}
|
||||
|
||||
pub fn writeReinterpret(writer: anytype, die_offset: anytype) !void {
|
||||
pub fn writeReinterpret(writer: *Writer, die_offset: anytype) !void {
|
||||
if (options.call_frame_context) return error.InvalidCFAOpcode;
|
||||
try writer.writeByte(OP.reinterpret);
|
||||
try leb.writeUleb128(writer, die_offset);
|
||||
try writer.writeUleb128(die_offset);
|
||||
}
|
||||
|
||||
// 2.5.1.7: Special Operations
|
||||
|
||||
pub fn writeEntryValue(writer: anytype, expression: []const u8) !void {
|
||||
pub fn writeEntryValue(writer: *Writer, expression: []const u8) !void {
|
||||
try writer.writeByte(OP.entry_value);
|
||||
try leb.writeUleb128(writer, expression.len);
|
||||
try writer.writeUleb128(expression.len);
|
||||
try writer.writeAll(expression);
|
||||
}
|
||||
|
||||
// 2.6: Location Descriptions
|
||||
pub fn writeReg(writer: anytype, register: u8) !void {
|
||||
pub fn writeReg(writer: *Writer, register: u8) !void {
|
||||
try writer.writeByte(OP.reg0 + register);
|
||||
}
|
||||
|
||||
pub fn writeRegx(writer: anytype, register: anytype) !void {
|
||||
pub fn writeRegx(writer: *Writer, register: anytype) !void {
|
||||
try writer.writeByte(OP.regx);
|
||||
try leb.writeUleb128(writer, register);
|
||||
try writer.writeUleb128(register);
|
||||
}
|
||||
|
||||
pub fn writeImplicitValue(writer: anytype, value_bytes: []const u8) !void {
|
||||
pub fn writeImplicitValue(writer: *Writer, value_bytes: []const u8) !void {
|
||||
try writer.writeByte(OP.implicit_value);
|
||||
try leb.writeUleb128(writer, value_bytes.len);
|
||||
try writer.writeUleb128(value_bytes.len);
|
||||
try writer.writeAll(value_bytes);
|
||||
}
|
||||
};
|
||||
@ -1042,8 +1044,7 @@ fn isOpcodeRegisterLocation(opcode: u8) bool {
|
||||
};
|
||||
}
|
||||
|
||||
const testing = std.testing;
|
||||
test "DWARF expressions" {
|
||||
test "basics" {
|
||||
const allocator = std.testing.allocator;
|
||||
|
||||
const options = Options{};
|
||||
@ -1052,10 +1053,10 @@ test "DWARF expressions" {
|
||||
|
||||
const b = Builder(options);
|
||||
|
||||
var program = std.array_list.Managed(u8).init(allocator);
|
||||
var program: std.Io.Writer.Allocating = .init(allocator);
|
||||
defer program.deinit();
|
||||
|
||||
const writer = program.writer();
|
||||
const writer = &program.writer;
|
||||
|
||||
// Literals
|
||||
{
|
||||
@ -1064,7 +1065,7 @@ test "DWARF expressions" {
|
||||
try b.writeLiteral(writer, @intCast(i));
|
||||
}
|
||||
|
||||
_ = try stack_machine.run(program.items, allocator, context, 0);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, 0);
|
||||
|
||||
for (0..32) |i| {
|
||||
const expected = 31 - i;
|
||||
@ -1108,16 +1109,16 @@ test "DWARF expressions" {
|
||||
var mock_compile_unit: std.debug.Dwarf.CompileUnit = undefined;
|
||||
mock_compile_unit.addr_base = 1;
|
||||
|
||||
var mock_debug_addr = std.array_list.Managed(u8).init(allocator);
|
||||
var mock_debug_addr: std.Io.Writer.Allocating = .init(allocator);
|
||||
defer mock_debug_addr.deinit();
|
||||
|
||||
try mock_debug_addr.writer().writeInt(u16, 0, native_endian);
|
||||
try mock_debug_addr.writer().writeInt(usize, input[11], native_endian);
|
||||
try mock_debug_addr.writer().writeInt(usize, input[12], native_endian);
|
||||
try mock_debug_addr.writer.writeInt(u16, 0, native_endian);
|
||||
try mock_debug_addr.writer.writeInt(usize, input[11], native_endian);
|
||||
try mock_debug_addr.writer.writeInt(usize, input[12], native_endian);
|
||||
|
||||
const context = Context{
|
||||
const context: Context = .{
|
||||
.compile_unit = &mock_compile_unit,
|
||||
.debug_addr = mock_debug_addr.items,
|
||||
.debug_addr = mock_debug_addr.written(),
|
||||
};
|
||||
|
||||
try b.writeConstx(writer, @as(usize, 1));
|
||||
@ -1127,7 +1128,7 @@ test "DWARF expressions" {
|
||||
const type_bytes: []const u8 = &.{ 1, 2, 3, 4 };
|
||||
try b.writeConstType(writer, die_offset, type_bytes);
|
||||
|
||||
_ = try stack_machine.run(program.items, allocator, context, 0);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, 0);
|
||||
|
||||
const const_type = stack_machine.stack.pop().?.const_type;
|
||||
try testing.expectEqual(die_offset, const_type.type_offset);
|
||||
@ -1185,7 +1186,7 @@ test "DWARF expressions" {
|
||||
try b.writeBregx(writer, abi.ipRegNum(native_arch).?, @as(usize, 300));
|
||||
try b.writeRegvalType(writer, @as(u8, 0), @as(usize, 400));
|
||||
|
||||
_ = try stack_machine.run(program.items, allocator, context, 0);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, 0);
|
||||
|
||||
const regval_type = stack_machine.stack.pop().?.regval_type;
|
||||
try testing.expectEqual(@as(usize, 400), regval_type.type_offset);
|
||||
@ -1214,7 +1215,7 @@ test "DWARF expressions" {
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeConst(writer, u8, 1);
|
||||
try b.writeOpcode(writer, OP.dup);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 1), stack_machine.stack.pop().?.generic);
|
||||
try testing.expectEqual(@as(usize, 1), stack_machine.stack.pop().?.generic);
|
||||
|
||||
@ -1222,7 +1223,7 @@ test "DWARF expressions" {
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeConst(writer, u8, 1);
|
||||
try b.writeOpcode(writer, OP.drop);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expect(stack_machine.stack.pop() == null);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1231,7 +1232,7 @@ test "DWARF expressions" {
|
||||
try b.writeConst(writer, u8, 5);
|
||||
try b.writeConst(writer, u8, 6);
|
||||
try b.writePick(writer, 2);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 4), stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1240,7 +1241,7 @@ test "DWARF expressions" {
|
||||
try b.writeConst(writer, u8, 5);
|
||||
try b.writeConst(writer, u8, 6);
|
||||
try b.writeOpcode(writer, OP.over);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 5), stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1248,7 +1249,7 @@ test "DWARF expressions" {
|
||||
try b.writeConst(writer, u8, 5);
|
||||
try b.writeConst(writer, u8, 6);
|
||||
try b.writeOpcode(writer, OP.swap);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 5), stack_machine.stack.pop().?.generic);
|
||||
try testing.expectEqual(@as(usize, 6), stack_machine.stack.pop().?.generic);
|
||||
|
||||
@ -1258,7 +1259,7 @@ test "DWARF expressions" {
|
||||
try b.writeConst(writer, u8, 5);
|
||||
try b.writeConst(writer, u8, 6);
|
||||
try b.writeOpcode(writer, OP.rot);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 5), stack_machine.stack.pop().?.generic);
|
||||
try testing.expectEqual(@as(usize, 4), stack_machine.stack.pop().?.generic);
|
||||
try testing.expectEqual(@as(usize, 6), stack_machine.stack.pop().?.generic);
|
||||
@ -1269,7 +1270,7 @@ test "DWARF expressions" {
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeAddr(writer, @intFromPtr(&deref_target));
|
||||
try b.writeOpcode(writer, OP.deref);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(deref_target, stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1277,14 +1278,14 @@ test "DWARF expressions" {
|
||||
try b.writeLiteral(writer, 0);
|
||||
try b.writeAddr(writer, @intFromPtr(&deref_target));
|
||||
try b.writeOpcode(writer, OP.xderef);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(deref_target, stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeAddr(writer, @intFromPtr(&deref_target));
|
||||
try b.writeDerefSize(writer, 1);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, @as(*const u8, @ptrCast(&deref_target)).*), stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1292,7 +1293,7 @@ test "DWARF expressions" {
|
||||
try b.writeLiteral(writer, 0);
|
||||
try b.writeAddr(writer, @intFromPtr(&deref_target));
|
||||
try b.writeXDerefSize(writer, 1);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, @as(*const u8, @ptrCast(&deref_target)).*), stack_machine.stack.pop().?.generic);
|
||||
|
||||
const type_offset: usize = @truncate(0xaabbaabb_aabbaabb);
|
||||
@ -1301,7 +1302,7 @@ test "DWARF expressions" {
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeAddr(writer, @intFromPtr(&deref_target));
|
||||
try b.writeDerefType(writer, 1, type_offset);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
const deref_type = stack_machine.stack.pop().?.regval_type;
|
||||
try testing.expectEqual(type_offset, deref_type.type_offset);
|
||||
try testing.expectEqual(@as(u8, 1), deref_type.type_size);
|
||||
@ -1312,7 +1313,7 @@ test "DWARF expressions" {
|
||||
try b.writeLiteral(writer, 0);
|
||||
try b.writeAddr(writer, @intFromPtr(&deref_target));
|
||||
try b.writeXDerefType(writer, 1, type_offset);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
const xderef_type = stack_machine.stack.pop().?.regval_type;
|
||||
try testing.expectEqual(type_offset, xderef_type.type_offset);
|
||||
try testing.expectEqual(@as(u8, 1), xderef_type.type_size);
|
||||
@ -1323,7 +1324,7 @@ test "DWARF expressions" {
|
||||
stack_machine.reset();
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeOpcode(writer, OP.push_object_address);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, @intFromPtr(context.object_address.?)), stack_machine.stack.pop().?.generic);
|
||||
|
||||
// TODO: Test OP.form_tls_address
|
||||
@ -1333,7 +1334,7 @@ test "DWARF expressions" {
|
||||
stack_machine.reset();
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeOpcode(writer, OP.call_frame_cfa);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(context.cfa.?, stack_machine.stack.pop().?.generic);
|
||||
}
|
||||
|
||||
@ -1345,7 +1346,7 @@ test "DWARF expressions" {
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeConst(writer, i16, -4096);
|
||||
try b.writeOpcode(writer, OP.abs);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 4096), stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1353,7 +1354,7 @@ test "DWARF expressions" {
|
||||
try b.writeConst(writer, u16, 0xff0f);
|
||||
try b.writeConst(writer, u16, 0xf0ff);
|
||||
try b.writeOpcode(writer, OP.@"and");
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 0xf00f), stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1361,7 +1362,7 @@ test "DWARF expressions" {
|
||||
try b.writeConst(writer, i16, -404);
|
||||
try b.writeConst(writer, i16, 100);
|
||||
try b.writeOpcode(writer, OP.div);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(isize, -404 / 100), @as(isize, @bitCast(stack_machine.stack.pop().?.generic)));
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1369,7 +1370,7 @@ test "DWARF expressions" {
|
||||
try b.writeConst(writer, u16, 200);
|
||||
try b.writeConst(writer, u16, 50);
|
||||
try b.writeOpcode(writer, OP.minus);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 150), stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1377,7 +1378,7 @@ test "DWARF expressions" {
|
||||
try b.writeConst(writer, u16, 123);
|
||||
try b.writeConst(writer, u16, 100);
|
||||
try b.writeOpcode(writer, OP.mod);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 23), stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1385,7 +1386,7 @@ test "DWARF expressions" {
|
||||
try b.writeConst(writer, u16, 0xff);
|
||||
try b.writeConst(writer, u16, 0xee);
|
||||
try b.writeOpcode(writer, OP.mul);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 0xed12), stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1394,7 +1395,7 @@ test "DWARF expressions" {
|
||||
try b.writeOpcode(writer, OP.neg);
|
||||
try b.writeConst(writer, i16, -6);
|
||||
try b.writeOpcode(writer, OP.neg);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 6), stack_machine.stack.pop().?.generic);
|
||||
try testing.expectEqual(@as(isize, -5), @as(isize, @bitCast(stack_machine.stack.pop().?.generic)));
|
||||
|
||||
@ -1402,7 +1403,7 @@ test "DWARF expressions" {
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeConst(writer, u16, 0xff0f);
|
||||
try b.writeOpcode(writer, OP.not);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(~@as(usize, 0xff0f), stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1410,7 +1411,7 @@ test "DWARF expressions" {
|
||||
try b.writeConst(writer, u16, 0xff0f);
|
||||
try b.writeConst(writer, u16, 0xf0ff);
|
||||
try b.writeOpcode(writer, OP.@"or");
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 0xffff), stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1418,14 +1419,14 @@ test "DWARF expressions" {
|
||||
try b.writeConst(writer, i16, 402);
|
||||
try b.writeConst(writer, i16, 100);
|
||||
try b.writeOpcode(writer, OP.plus);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 502), stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeConst(writer, u16, 4096);
|
||||
try b.writePlusUconst(writer, @as(usize, 8192));
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 4096 + 8192), stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1433,7 +1434,7 @@ test "DWARF expressions" {
|
||||
try b.writeConst(writer, u16, 0xfff);
|
||||
try b.writeConst(writer, u16, 1);
|
||||
try b.writeOpcode(writer, OP.shl);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 0xfff << 1), stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1441,7 +1442,7 @@ test "DWARF expressions" {
|
||||
try b.writeConst(writer, u16, 0xfff);
|
||||
try b.writeConst(writer, u16, 1);
|
||||
try b.writeOpcode(writer, OP.shr);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 0xfff >> 1), stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1449,7 +1450,7 @@ test "DWARF expressions" {
|
||||
try b.writeConst(writer, u16, 0xfff);
|
||||
try b.writeConst(writer, u16, 1);
|
||||
try b.writeOpcode(writer, OP.shr);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, @bitCast(@as(isize, 0xfff) >> 1)), stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1457,7 +1458,7 @@ test "DWARF expressions" {
|
||||
try b.writeConst(writer, u16, 0xf0ff);
|
||||
try b.writeConst(writer, u16, 0xff0f);
|
||||
try b.writeOpcode(writer, OP.xor);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 0x0ff0), stack_machine.stack.pop().?.generic);
|
||||
}
|
||||
|
||||
@ -1486,7 +1487,7 @@ test "DWARF expressions" {
|
||||
try b.writeConst(writer, u16, 1);
|
||||
try b.writeConst(writer, u16, 0);
|
||||
try b.writeOpcode(writer, e[0]);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, e[3]), stack_machine.stack.pop().?.generic);
|
||||
try testing.expectEqual(@as(usize, e[2]), stack_machine.stack.pop().?.generic);
|
||||
try testing.expectEqual(@as(usize, e[1]), stack_machine.stack.pop().?.generic);
|
||||
@ -1497,7 +1498,7 @@ test "DWARF expressions" {
|
||||
try b.writeLiteral(writer, 2);
|
||||
try b.writeSkip(writer, 1);
|
||||
try b.writeLiteral(writer, 3);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 2), stack_machine.stack.pop().?.generic);
|
||||
|
||||
stack_machine.reset();
|
||||
@ -1509,7 +1510,7 @@ test "DWARF expressions" {
|
||||
try b.writeBra(writer, 1);
|
||||
try b.writeLiteral(writer, 4);
|
||||
try b.writeLiteral(writer, 5);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 5), stack_machine.stack.pop().?.generic);
|
||||
try testing.expectEqual(@as(usize, 4), stack_machine.stack.pop().?.generic);
|
||||
try testing.expect(stack_machine.stack.pop() == null);
|
||||
@ -1535,7 +1536,7 @@ test "DWARF expressions" {
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeConstType(writer, @as(usize, 0), &value_bytes);
|
||||
try b.writeConvert(writer, @as(usize, 0));
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(value, stack_machine.stack.pop().?.generic);
|
||||
|
||||
// Reinterpret to generic type
|
||||
@ -1543,7 +1544,7 @@ test "DWARF expressions" {
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeConstType(writer, @as(usize, 0), &value_bytes);
|
||||
try b.writeReinterpret(writer, @as(usize, 0));
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(value, stack_machine.stack.pop().?.generic);
|
||||
|
||||
// Reinterpret to new type
|
||||
@ -1553,7 +1554,7 @@ test "DWARF expressions" {
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeConstType(writer, @as(usize, 0), &value_bytes);
|
||||
try b.writeReinterpret(writer, die_offset);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
const const_type = stack_machine.stack.pop().?.const_type;
|
||||
try testing.expectEqual(die_offset, const_type.type_offset);
|
||||
|
||||
@ -1561,7 +1562,7 @@ test "DWARF expressions" {
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeLiteral(writer, 0);
|
||||
try b.writeReinterpret(writer, die_offset);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
const regval_type = stack_machine.stack.pop().?.regval_type;
|
||||
try testing.expectEqual(die_offset, regval_type.type_offset);
|
||||
}
|
||||
@ -1573,20 +1574,20 @@ test "DWARF expressions" {
|
||||
stack_machine.reset();
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeOpcode(writer, OP.nop);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expect(stack_machine.stack.pop() == null);
|
||||
|
||||
// Sub-expression
|
||||
{
|
||||
var sub_program = std.array_list.Managed(u8).init(allocator);
|
||||
var sub_program: std.Io.Writer.Allocating = .init(allocator);
|
||||
defer sub_program.deinit();
|
||||
const sub_writer = sub_program.writer();
|
||||
const sub_writer = &sub_program.writer;
|
||||
try b.writeLiteral(sub_writer, 3);
|
||||
|
||||
stack_machine.reset();
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeEntryValue(writer, sub_program.items);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
try b.writeEntryValue(writer, sub_program.written());
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 3), stack_machine.stack.pop().?.generic);
|
||||
}
|
||||
|
||||
@ -1605,15 +1606,15 @@ test "DWARF expressions" {
|
||||
if (abi.regBytes(&thread_context, 0, reg_context)) |reg_bytes| {
|
||||
mem.writeInt(usize, reg_bytes[0..@sizeOf(usize)], 0xee, native_endian);
|
||||
|
||||
var sub_program = std.array_list.Managed(u8).init(allocator);
|
||||
var sub_program: std.Io.Writer.Allocating = .init(allocator);
|
||||
defer sub_program.deinit();
|
||||
const sub_writer = sub_program.writer();
|
||||
const sub_writer = &sub_program.writer;
|
||||
try b.writeReg(sub_writer, 0);
|
||||
|
||||
stack_machine.reset();
|
||||
program.clearRetainingCapacity();
|
||||
try b.writeEntryValue(writer, sub_program.items);
|
||||
_ = try stack_machine.run(program.items, allocator, context, null);
|
||||
try b.writeEntryValue(writer, sub_program.written());
|
||||
_ = try stack_machine.run(program.written(), allocator, context, null);
|
||||
try testing.expectEqual(@as(usize, 0xee), stack_machine.stack.pop().?.generic);
|
||||
} else |err| {
|
||||
switch (err) {
|
||||
|
||||
@ -33,28 +33,6 @@ pub fn readUleb128(comptime T: type, reader: anytype) !T {
|
||||
return @as(T, @truncate(value));
|
||||
}
|
||||
|
||||
/// Write a single unsigned integer as unsigned LEB128 to the given writer.
|
||||
pub fn writeUleb128(writer: anytype, arg: anytype) !void {
|
||||
const Arg = @TypeOf(arg);
|
||||
const Int = switch (Arg) {
|
||||
comptime_int => std.math.IntFittingRange(arg, arg),
|
||||
else => Arg,
|
||||
};
|
||||
const Value = if (@typeInfo(Int).int.bits < 8) u8 else Int;
|
||||
var value: Value = arg;
|
||||
|
||||
while (true) {
|
||||
const byte: u8 = @truncate(value & 0x7f);
|
||||
value >>= 7;
|
||||
if (value == 0) {
|
||||
try writer.writeByte(byte);
|
||||
break;
|
||||
} else {
|
||||
try writer.writeByte(byte | 0x80);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read a single signed LEB128 value from the given reader as type T,
|
||||
/// or error.Overflow if the value cannot fit.
|
||||
pub fn readIleb128(comptime T: type, reader: anytype) !T {
|
||||
@ -374,84 +352,3 @@ test "deserialize unsigned LEB128" {
|
||||
// Decode sequence of ULEB128 values
|
||||
try test_read_uleb128_seq(u64, 4, "\x81\x01\x3f\x80\x7f\x80\x80\x80\x00");
|
||||
}
|
||||
|
||||
fn test_write_leb128(value: anytype) !void {
|
||||
const T = @TypeOf(value);
|
||||
const signedness = @typeInfo(T).int.signedness;
|
||||
const t_signed = signedness == .signed;
|
||||
|
||||
const writeStream = if (t_signed) writeIleb128 else writeUleb128;
|
||||
const readStream = if (t_signed) readIleb128 else readUleb128;
|
||||
|
||||
// decode to a larger bit size too, to ensure sign extension
|
||||
// is working as expected
|
||||
const larger_type_bits = ((@typeInfo(T).int.bits + 8) / 8) * 8;
|
||||
const B = std.meta.Int(signedness, larger_type_bits);
|
||||
|
||||
const bytes_needed = bn: {
|
||||
if (@typeInfo(T).int.bits <= 7) break :bn @as(u16, 1);
|
||||
|
||||
const unused_bits = if (value < 0) @clz(~value) else @clz(value);
|
||||
const used_bits: u16 = (@typeInfo(T).int.bits - unused_bits) + @intFromBool(t_signed);
|
||||
if (used_bits <= 7) break :bn @as(u16, 1);
|
||||
break :bn ((used_bits + 6) / 7);
|
||||
};
|
||||
|
||||
const max_groups = if (@typeInfo(T).int.bits == 0) 1 else (@typeInfo(T).int.bits + 6) / 7;
|
||||
|
||||
var buf: [max_groups]u8 = undefined;
|
||||
var fbs = std.io.fixedBufferStream(&buf);
|
||||
|
||||
// stream write
|
||||
try writeStream(fbs.writer(), value);
|
||||
const w1_pos = fbs.pos;
|
||||
try testing.expect(w1_pos == bytes_needed);
|
||||
|
||||
// stream read
|
||||
fbs.pos = 0;
|
||||
const sr = try readStream(T, fbs.reader());
|
||||
try testing.expect(fbs.pos == w1_pos);
|
||||
try testing.expect(sr == value);
|
||||
|
||||
// bigger type stream read
|
||||
fbs.pos = 0;
|
||||
const bsr = try readStream(B, fbs.reader());
|
||||
try testing.expect(fbs.pos == w1_pos);
|
||||
try testing.expect(bsr == value);
|
||||
}
|
||||
|
||||
test "serialize unsigned LEB128" {
|
||||
if (builtin.cpu.arch == .x86 and builtin.abi == .musl and builtin.link_mode == .dynamic) return error.SkipZigTest;
|
||||
|
||||
const max_bits = 18;
|
||||
|
||||
comptime var t = 0;
|
||||
inline while (t <= max_bits) : (t += 1) {
|
||||
const T = std.meta.Int(.unsigned, t);
|
||||
const min = std.math.minInt(T);
|
||||
const max = std.math.maxInt(T);
|
||||
var i = @as(std.meta.Int(.unsigned, @typeInfo(T).int.bits + 1), min);
|
||||
|
||||
while (i <= max) : (i += 1) try test_write_leb128(@as(T, @intCast(i)));
|
||||
}
|
||||
}
|
||||
|
||||
test "serialize signed LEB128" {
|
||||
if (builtin.cpu.arch == .x86 and builtin.abi == .musl and builtin.link_mode == .dynamic) return error.SkipZigTest;
|
||||
|
||||
// explicitly test i0 because starting `t` at 0
|
||||
// will break the while loop
|
||||
try test_write_leb128(@as(i0, 0));
|
||||
|
||||
const max_bits = 18;
|
||||
|
||||
comptime var t = 1;
|
||||
inline while (t <= max_bits) : (t += 1) {
|
||||
const T = std.meta.Int(.signed, t);
|
||||
const min = std.math.minInt(T);
|
||||
const max = std.math.maxInt(T);
|
||||
var i = @as(std.meta.Int(.signed, @typeInfo(T).int.bits + 1), min);
|
||||
|
||||
while (i <= max) : (i += 1) try test_write_leb128(@as(T, @intCast(i)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -683,11 +683,11 @@ test "mmap" {
|
||||
const file = try tmp.dir.createFile(test_out_file, .{});
|
||||
defer file.close();
|
||||
|
||||
const stream = file.deprecatedWriter();
|
||||
var stream = file.writer(&.{});
|
||||
|
||||
var i: u32 = 0;
|
||||
while (i < alloc_size / @sizeOf(u32)) : (i += 1) {
|
||||
try stream.writeInt(u32, i, .little);
|
||||
try stream.interface.writeInt(u32, i, .little);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user