Merge branch 'fengb-format-stream'

This commit is contained in:
Andrew Kelley 2020-03-13 12:07:06 -04:00
commit 3eff77bfb5
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
16 changed files with 356 additions and 436 deletions

View File

@ -65,13 +65,9 @@ pub const Buffer = struct {
} }
pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer { pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer {
const countSize = struct { const size = std.math.cast(usize, std.fmt.count(format, args)) catch |err| switch (err) {
fn countSize(size: *usize, bytes: []const u8) (error{}!void) { error.Overflow => return error.OutOfMemory,
size.* += bytes.len; };
}
}.countSize;
var size: usize = 0;
std.fmt.format(&size, error{}, countSize, format, args) catch |err| switch (err) {};
var self = try Buffer.initSize(allocator, size); var self = try Buffer.initSize(allocator, size);
assert((std.fmt.bufPrint(self.list.items, format, args) catch unreachable).len == size); assert((std.fmt.bufPrint(self.list.items, format, args) catch unreachable).len == size);
return self; return self;
@ -154,10 +150,6 @@ pub const Buffer = struct {
mem.copy(u8, self.list.toSlice(), m); mem.copy(u8, self.list.toSlice(), m);
} }
pub fn print(self: *Buffer, comptime fmt: []const u8, args: var) !void {
return std.fmt.format(self, error{OutOfMemory}, Buffer.append, fmt, args);
}
pub fn outStream(self: *Buffer) std.io.OutStream(*Buffer, error{OutOfMemory}, appendWrite) { pub fn outStream(self: *Buffer) std.io.OutStream(*Buffer, error{OutOfMemory}, appendWrite) {
return .{ .context = self }; return .{ .context = self };
} }
@ -216,7 +208,7 @@ test "Buffer.print" {
var buf = try Buffer.init(testing.allocator, ""); var buf = try Buffer.init(testing.allocator, "");
defer buf.deinit(); defer buf.deinit();
try buf.print("Hello {} the {}", .{ 2, "world" }); try buf.outStream().print("Hello {} the {}", .{ 2, "world" });
testing.expect(buf.eql("Hello 2 the world")); testing.expect(buf.eql("Hello 2 the world"));
} }

View File

@ -436,19 +436,17 @@ pub const Version = struct {
self: Version, self: Version,
comptime fmt: []const u8, comptime fmt: []const u8,
options: std.fmt.FormatOptions, options: std.fmt.FormatOptions,
context: var, out_stream: var,
comptime Error: type, ) !void {
comptime output: fn (@TypeOf(context), []const u8) Error!void,
) Error!void {
if (fmt.len == 0) { if (fmt.len == 0) {
if (self.patch == 0) { if (self.patch == 0) {
if (self.minor == 0) { if (self.minor == 0) {
return std.fmt.format(context, Error, output, "{}", .{self.major}); return std.fmt.format(out_stream, "{}", .{self.major});
} else { } else {
return std.fmt.format(context, Error, output, "{}.{}", .{ self.major, self.minor }); return std.fmt.format(out_stream, "{}.{}", .{ self.major, self.minor });
} }
} else { } else {
return std.fmt.format(context, Error, output, "{}.{}.{}", .{ self.major, self.minor, self.patch }); return std.fmt.format(out_stream, "{}.{}.{}", .{ self.major, self.minor, self.patch });
} }
} else { } else {
@compileError("Unknown format string: '" ++ fmt ++ "'"); @compileError("Unknown format string: '" ++ fmt ++ "'");

View File

@ -293,8 +293,18 @@ pub fn LinearFifo(
pub usingnamespace if (T == u8) pub usingnamespace if (T == u8)
struct { struct {
pub fn print(self: *Self, comptime format: []const u8, args: var) !void { const OutStream = std.io.OutStream(*Self, Error, appendWrite);
return std.fmt.format(self, error{OutOfMemory}, Self.write, format, args); const Error = error{OutOfMemory};
/// Same as `write` except it returns the number of bytes written, which is always the same
/// as `bytes.len`. The purpose of this function existing is to match `std.io.OutStream` API.
pub fn appendWrite(fifo: *Self, bytes: []const u8) Error!usize {
try fifo.write(bytes);
return bytes.len;
}
pub fn outStream(self: *Self) OutStream {
return .{ .context = self };
} }
} }
else else
@ -407,7 +417,7 @@ test "LinearFifo(u8, .Dynamic)" {
fifo.shrink(0); fifo.shrink(0);
{ {
try fifo.print("{}, {}!", .{ "Hello", "World" }); try fifo.outStream().print("{}, {}!", .{ "Hello", "World" });
var result: [30]u8 = undefined; var result: [30]u8 = undefined;
testing.expectEqualSlices(u8, "Hello, World!", result[0..fifo.read(&result)]); testing.expectEqualSlices(u8, "Hello, World!", result[0..fifo.read(&result)]);
testing.expectEqual(@as(usize, 0), fifo.readableLength()); testing.expectEqual(@as(usize, 0), fifo.readableLength());

File diff suppressed because it is too large Load Diff

View File

@ -350,15 +350,13 @@ pub const Headers = struct {
self: Self, self: Self,
comptime fmt: []const u8, comptime fmt: []const u8,
options: std.fmt.FormatOptions, options: std.fmt.FormatOptions,
context: var, out_stream: var,
comptime Errors: type, ) !void {
output: fn (@TypeOf(context), []const u8) Errors!void,
) Errors!void {
for (self.toSlice()) |entry| { for (self.toSlice()) |entry| {
try output(context, entry.name); try out_stream.writeAll(entry.name);
try output(context, ": "); try out_stream.writeAll(": ");
try output(context, entry.value); try out_stream.writeAll(entry.value);
try output(context, "\n"); try out_stream.writeAll("\n");
} }
} }
}; };

View File

@ -103,7 +103,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
return self.pos; return self.pos;
} }
pub fn getWritten(self: Self) []const u8 { pub fn getWritten(self: Self) Buffer {
return self.buffer[0..self.pos]; return self.buffer[0..self.pos];
} }

View File

@ -25,7 +25,7 @@ pub fn OutStream(
} }
pub fn print(self: Self, comptime format: []const u8, args: var) Error!void { pub fn print(self: Self, comptime format: []const u8, args: var) Error!void {
return std.fmt.format(self, Error, writeAll, format, args); return std.fmt.format(self, format, args);
} }
pub fn writeByte(self: Self, byte: u8) Error!void { pub fn writeByte(self: Self, byte: u8) Error!void {

View File

@ -2252,45 +2252,43 @@ pub const StringifyOptions = struct {
pub fn stringify( pub fn stringify(
value: var, value: var,
options: StringifyOptions, options: StringifyOptions,
context: var, out_stream: var,
comptime Errors: type, ) !void {
comptime output: fn (@TypeOf(context), []const u8) Errors!void,
) Errors!void {
const T = @TypeOf(value); const T = @TypeOf(value);
switch (@typeInfo(T)) { switch (@typeInfo(T)) {
.Float, .ComptimeFloat => { .Float, .ComptimeFloat => {
return std.fmt.formatFloatScientific(value, std.fmt.FormatOptions{}, context, Errors, output); return std.fmt.formatFloatScientific(value, std.fmt.FormatOptions{}, out_stream);
}, },
.Int, .ComptimeInt => { .Int, .ComptimeInt => {
return std.fmt.formatIntValue(value, "", std.fmt.FormatOptions{}, context, Errors, output); return std.fmt.formatIntValue(value, "", std.fmt.FormatOptions{}, out_stream);
}, },
.Bool => { .Bool => {
return output(context, if (value) "true" else "false"); return out_stream.writeAll(if (value) "true" else "false");
}, },
.Optional => { .Optional => {
if (value) |payload| { if (value) |payload| {
return try stringify(payload, options, context, Errors, output); return try stringify(payload, options, out_stream);
} else { } else {
return output(context, "null"); return out_stream.writeAll("null");
} }
}, },
.Enum => { .Enum => {
if (comptime std.meta.trait.hasFn("jsonStringify")(T)) { if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
return value.jsonStringify(options, context, Errors, output); return value.jsonStringify(options, out_stream);
} }
@compileError("Unable to stringify enum '" ++ @typeName(T) ++ "'"); @compileError("Unable to stringify enum '" ++ @typeName(T) ++ "'");
}, },
.Union => { .Union => {
if (comptime std.meta.trait.hasFn("jsonStringify")(T)) { if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
return value.jsonStringify(options, context, Errors, output); return value.jsonStringify(options, out_stream);
} }
const info = @typeInfo(T).Union; const info = @typeInfo(T).Union;
if (info.tag_type) |UnionTagType| { if (info.tag_type) |UnionTagType| {
inline for (info.fields) |u_field| { inline for (info.fields) |u_field| {
if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) { if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {
return try stringify(@field(value, u_field.name), options, context, Errors, output); return try stringify(@field(value, u_field.name), options, out_stream);
} }
} }
} else { } else {
@ -2299,10 +2297,10 @@ pub fn stringify(
}, },
.Struct => |S| { .Struct => |S| {
if (comptime std.meta.trait.hasFn("jsonStringify")(T)) { if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
return value.jsonStringify(options, context, Errors, output); return value.jsonStringify(options, out_stream);
} }
try output(context, "{"); try out_stream.writeAll("{");
comptime var field_output = false; comptime var field_output = false;
inline for (S.fields) |Field, field_i| { inline for (S.fields) |Field, field_i| {
// don't include void fields // don't include void fields
@ -2311,39 +2309,39 @@ pub fn stringify(
if (!field_output) { if (!field_output) {
field_output = true; field_output = true;
} else { } else {
try output(context, ","); try out_stream.writeAll(",");
} }
try stringify(Field.name, options, context, Errors, output); try stringify(Field.name, options, out_stream);
try output(context, ":"); try out_stream.writeAll(":");
try stringify(@field(value, Field.name), options, context, Errors, output); try stringify(@field(value, Field.name), options, out_stream);
} }
try output(context, "}"); try out_stream.writeAll("}");
return; return;
}, },
.Pointer => |ptr_info| switch (ptr_info.size) { .Pointer => |ptr_info| switch (ptr_info.size) {
.One => { .One => {
// TODO: avoid loops? // TODO: avoid loops?
return try stringify(value.*, options, context, Errors, output); return try stringify(value.*, options, out_stream);
}, },
// TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972) // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)
.Slice => { .Slice => {
if (ptr_info.child == u8 and std.unicode.utf8ValidateSlice(value)) { if (ptr_info.child == u8 and std.unicode.utf8ValidateSlice(value)) {
try output(context, "\""); try out_stream.writeAll("\"");
var i: usize = 0; var i: usize = 0;
while (i < value.len) : (i += 1) { while (i < value.len) : (i += 1) {
switch (value[i]) { switch (value[i]) {
// normal ascii characters // normal ascii characters
0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => try output(context, value[i .. i + 1]), 0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => try out_stream.writeAll(value[i .. i + 1]),
// control characters with short escapes // control characters with short escapes
'\\' => try output(context, "\\\\"), '\\' => try out_stream.writeAll("\\\\"),
'\"' => try output(context, "\\\""), '\"' => try out_stream.writeAll("\\\""),
'/' => try output(context, "\\/"), '/' => try out_stream.writeAll("\\/"),
0x8 => try output(context, "\\b"), 0x8 => try out_stream.writeAll("\\b"),
0xC => try output(context, "\\f"), 0xC => try out_stream.writeAll("\\f"),
'\n' => try output(context, "\\n"), '\n' => try out_stream.writeAll("\\n"),
'\r' => try output(context, "\\r"), '\r' => try out_stream.writeAll("\\r"),
'\t' => try output(context, "\\t"), '\t' => try out_stream.writeAll("\\t"),
else => { else => {
const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable; const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable;
const codepoint = std.unicode.utf8Decode(value[i .. i + ulen]) catch unreachable; const codepoint = std.unicode.utf8Decode(value[i .. i + ulen]) catch unreachable;
@ -2351,40 +2349,40 @@ pub fn stringify(
// If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF), // If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF),
// then it may be represented as a six-character sequence: a reverse solidus, followed // then it may be represented as a six-character sequence: a reverse solidus, followed
// by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point. // by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point.
try output(context, "\\u"); try out_stream.writeAll("\\u");
try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output); try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
} else { } else {
// To escape an extended character that is not in the Basic Multilingual Plane, // To escape an extended character that is not in the Basic Multilingual Plane,
// the character is represented as a 12-character sequence, encoding the UTF-16 surrogate pair. // the character is represented as a 12-character sequence, encoding the UTF-16 surrogate pair.
const high = @intCast(u16, (codepoint - 0x10000) >> 10) + 0xD800; const high = @intCast(u16, (codepoint - 0x10000) >> 10) + 0xD800;
const low = @intCast(u16, codepoint & 0x3FF) + 0xDC00; const low = @intCast(u16, codepoint & 0x3FF) + 0xDC00;
try output(context, "\\u"); try out_stream.writeAll("\\u");
try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output); try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
try output(context, "\\u"); try out_stream.writeAll("\\u");
try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output); try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
} }
i += ulen - 1; i += ulen - 1;
}, },
} }
} }
try output(context, "\""); try out_stream.writeAll("\"");
return; return;
} }
try output(context, "["); try out_stream.writeAll("[");
for (value) |x, i| { for (value) |x, i| {
if (i != 0) { if (i != 0) {
try output(context, ","); try out_stream.writeAll(",");
} }
try stringify(x, options, context, Errors, output); try stringify(x, options, out_stream);
} }
try output(context, "]"); try out_stream.writeAll("]");
return; return;
}, },
else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"), else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
}, },
.Array => |info| { .Array => |info| {
return try stringify(value[0..], options, context, Errors, output); return try stringify(value[0..], options, out_stream);
}, },
else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"), else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
} }
@ -2392,10 +2390,26 @@ pub fn stringify(
} }
fn teststringify(expected: []const u8, value: var) !void { fn teststringify(expected: []const u8, value: var) !void {
const TestStringifyContext = struct { const ValidationOutStream = struct {
const Self = @This();
pub const OutStream = std.io.OutStream(*Self, Error, write);
pub const Error = error{
TooMuchData,
DifferentData,
};
expected_remaining: []const u8, expected_remaining: []const u8,
fn testStringifyWrite(context: *@This(), bytes: []const u8) !void {
if (context.expected_remaining.len < bytes.len) { fn init(exp: []const u8) Self {
return .{ .expected_remaining = exp };
}
pub fn outStream(self: *Self) OutStream {
return .{ .context = self };
}
fn write(self: *Self, bytes: []const u8) Error!usize {
if (self.expected_remaining.len < bytes.len) {
std.debug.warn( std.debug.warn(
\\====== expected this output: ========= \\====== expected this output: =========
\\{} \\{}
@ -2403,12 +2417,12 @@ fn teststringify(expected: []const u8, value: var) !void {
\\{} \\{}
\\====================================== \\======================================
, .{ , .{
context.expected_remaining, self.expected_remaining,
bytes, bytes,
}); });
return error.TooMuchData; return error.TooMuchData;
} }
if (!mem.eql(u8, context.expected_remaining[0..bytes.len], bytes)) { if (!mem.eql(u8, self.expected_remaining[0..bytes.len], bytes)) {
std.debug.warn( std.debug.warn(
\\====== expected this output: ========= \\====== expected this output: =========
\\{} \\{}
@ -2416,21 +2430,19 @@ fn teststringify(expected: []const u8, value: var) !void {
\\{} \\{}
\\====================================== \\======================================
, .{ , .{
context.expected_remaining[0..bytes.len], self.expected_remaining[0..bytes.len],
bytes, bytes,
}); });
return error.DifferentData; return error.DifferentData;
} }
context.expected_remaining = context.expected_remaining[bytes.len..]; self.expected_remaining = self.expected_remaining[bytes.len..];
return bytes.len;
} }
}; };
var buf: [100]u8 = undefined;
var context = TestStringifyContext{ .expected_remaining = expected }; var vos = ValidationOutStream.init(expected);
try stringify(value, StringifyOptions{}, &context, error{ try stringify(value, StringifyOptions{}, vos.outStream());
TooMuchData, if (vos.expected_remaining.len > 0) return error.NotEnoughData;
DifferentData,
}, TestStringifyContext.testStringifyWrite);
if (context.expected_remaining.len > 0) return error.NotEnoughData;
} }
test "stringify basic types" { test "stringify basic types" {
@ -2498,13 +2510,11 @@ test "stringify struct with custom stringifier" {
pub fn jsonStringify( pub fn jsonStringify(
value: Self, value: Self,
options: StringifyOptions, options: StringifyOptions,
context: var, out_stream: var,
comptime Errors: type,
comptime output: fn (@TypeOf(context), []const u8) Errors!void,
) !void { ) !void {
try output(context, "[\"something special\","); try out_stream.writeAll("[\"something special\",");
try stringify(42, options, context, Errors, output); try stringify(42, options, out_stream);
try output(context, "]"); try out_stream.writeAll("]");
} }
}{ .foo = 42 }); }{ .foo = 42 });
} }

View File

@ -519,16 +519,14 @@ pub const Int = struct {
self: Int, self: Int,
comptime fmt: []const u8, comptime fmt: []const u8,
options: std.fmt.FormatOptions, options: std.fmt.FormatOptions,
context: var, out_stream: var,
comptime FmtError: type,
output: fn (@TypeOf(context), []const u8) FmtError!void,
) FmtError!void { ) FmtError!void {
self.assertWritable(); self.assertWritable();
// TODO look at fmt and support other bases // TODO look at fmt and support other bases
// TODO support read-only fixed integers // TODO support read-only fixed integers
const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating"); const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating");
defer self.allocator.?.free(str); defer self.allocator.?.free(str);
return output(context, str); return out_stream.print(str);
} }
/// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively. /// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.

View File

@ -269,15 +269,13 @@ pub const Address = extern union {
self: Address, self: Address,
comptime fmt: []const u8, comptime fmt: []const u8,
options: std.fmt.FormatOptions, options: std.fmt.FormatOptions,
context: var, out_stream: var,
comptime Errors: type,
comptime output: fn (@TypeOf(context), []const u8) Errors!void,
) !void { ) !void {
switch (self.any.family) { switch (self.any.family) {
os.AF_INET => { os.AF_INET => {
const port = mem.bigToNative(u16, self.in.port); const port = mem.bigToNative(u16, self.in.port);
const bytes = @ptrCast(*const [4]u8, &self.in.addr); const bytes = @ptrCast(*const [4]u8, &self.in.addr);
try std.fmt.format(context, Errors, output, "{}.{}.{}.{}:{}", .{ try std.fmt.format(out_stream, "{}.{}.{}.{}:{}", .{
bytes[0], bytes[0],
bytes[1], bytes[1],
bytes[2], bytes[2],
@ -288,7 +286,7 @@ pub const Address = extern union {
os.AF_INET6 => { os.AF_INET6 => {
const port = mem.bigToNative(u16, self.in6.port); const port = mem.bigToNative(u16, self.in6.port);
if (mem.eql(u8, self.in6.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) { if (mem.eql(u8, self.in6.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) {
try std.fmt.format(context, Errors, output, "[::ffff:{}.{}.{}.{}]:{}", .{ try std.fmt.format(out_stream, "[::ffff:{}.{}.{}.{}]:{}", .{
self.in6.addr[12], self.in6.addr[12],
self.in6.addr[13], self.in6.addr[13],
self.in6.addr[14], self.in6.addr[14],
@ -308,30 +306,30 @@ pub const Address = extern union {
break :blk buf; break :blk buf;
}, },
}; };
try output(context, "["); try out_stream.writeAll("[");
var i: usize = 0; var i: usize = 0;
var abbrv = false; var abbrv = false;
while (i < native_endian_parts.len) : (i += 1) { while (i < native_endian_parts.len) : (i += 1) {
if (native_endian_parts[i] == 0) { if (native_endian_parts[i] == 0) {
if (!abbrv) { if (!abbrv) {
try output(context, if (i == 0) "::" else ":"); try out_stream.writeAll(if (i == 0) "::" else ":");
abbrv = true; abbrv = true;
} }
continue; continue;
} }
try std.fmt.format(context, Errors, output, "{x}", .{native_endian_parts[i]}); try std.fmt.format(out_stream, "{x}", .{native_endian_parts[i]});
if (i != native_endian_parts.len - 1) { if (i != native_endian_parts.len - 1) {
try output(context, ":"); try out_stream.writeAll(":");
} }
} }
try std.fmt.format(context, Errors, output, "]:{}", .{port}); try std.fmt.format(out_stream, "]:{}", .{port});
}, },
os.AF_UNIX => { os.AF_UNIX => {
if (!has_unix_sockets) { if (!has_unix_sockets) {
unreachable; unreachable;
} }
try std.fmt.format(context, Errors, output, "{}", .{&self.un.path}); try std.fmt.format(out_stream, "{}", .{&self.un.path});
}, },
else => unreachable, else => unreachable,
} }

View File

@ -5,8 +5,6 @@ pub const protocols = @import("uefi/protocols.zig");
pub const Status = @import("uefi/status.zig").Status; pub const Status = @import("uefi/status.zig").Status;
pub const tables = @import("uefi/tables.zig"); pub const tables = @import("uefi/tables.zig");
const fmt = @import("std").fmt;
/// The EFI image's handle that is passed to its entry point. /// The EFI image's handle that is passed to its entry point.
pub var handle: Handle = undefined; pub var handle: Handle = undefined;
@ -29,13 +27,11 @@ pub const Guid = extern struct {
pub fn format( pub fn format(
self: @This(), self: @This(),
comptime f: []const u8, comptime f: []const u8,
options: fmt.FormatOptions, options: std.fmt.FormatOptions,
context: var, out_stream: var,
comptime Errors: type,
comptime output: fn (@TypeOf(context), []const u8) Errors!void,
) Errors!void { ) Errors!void {
if (f.len == 0) { if (f.len == 0) {
return fmt.format(context, Errors, output, "{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{ return std.fmt.format(out_stream, "{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{
self.time_low, self.time_low,
self.time_mid, self.time_mid,
self.time_high_and_version, self.time_high_and_version,

View File

@ -190,7 +190,7 @@ pub const Progress = struct {
end.* += amt; end.* += amt;
self.columns_written += amt; self.columns_written += amt;
} else |err| switch (err) { } else |err| switch (err) {
error.BufferTooSmall => { error.NoSpaceLeft => {
self.columns_written += self.output_buffer.len - end.*; self.columns_written += self.output_buffer.len - end.*;
end.* = self.output_buffer.len; end.* = self.output_buffer.len;
}, },

View File

@ -504,22 +504,22 @@ pub const CrossTarget = struct {
if (self.os_version_min != null or self.os_version_max != null) { if (self.os_version_min != null or self.os_version_max != null) {
switch (self.getOsVersionMin()) { switch (self.getOsVersionMin()) {
.none => {}, .none => {},
.semver => |v| try result.print(".{}", .{v}), .semver => |v| try result.outStream().print(".{}", .{v}),
.windows => |v| try result.print(".{}", .{@tagName(v)}), .windows => |v| try result.outStream().print(".{}", .{@tagName(v)}),
} }
} }
if (self.os_version_max) |max| { if (self.os_version_max) |max| {
switch (max) { switch (max) {
.none => {}, .none => {},
.semver => |v| try result.print("...{}", .{v}), .semver => |v| try result.outStream().print("...{}", .{v}),
.windows => |v| try result.print("...{}", .{@tagName(v)}), .windows => |v| try result.outStream().print("...{}", .{@tagName(v)}),
} }
} }
if (self.glibc_version) |v| { if (self.glibc_version) |v| {
try result.print("-{}.{}", .{ @tagName(self.getAbi()), v }); try result.outStream().print("-{}.{}", .{ @tagName(self.getAbi()), v });
} else if (self.abi) |abi| { } else if (self.abi) |abi| {
try result.print("-{}", .{@tagName(abi)}); try result.outStream().print("-{}", .{@tagName(abi)});
} }
return result.toOwnedSlice(); return result.toOwnedSlice();

View File

@ -306,12 +306,12 @@ pub const Tokenizer = struct {
fn errorPosition(self: *Tokenizer, position: usize, bytes: []const u8, comptime fmt: []const u8, args: var) Error { fn errorPosition(self: *Tokenizer, position: usize, bytes: []const u8, comptime fmt: []const u8, args: var) Error {
var buffer = try std.Buffer.initSize(&self.arena.allocator, 0); var buffer = try std.Buffer.initSize(&self.arena.allocator, 0);
std.fmt.format(&buffer, anyerror, std.Buffer.append, fmt, args) catch {}; try buffer.outStream().print(fmt, args);
try buffer.append(" '"); try buffer.append(" '");
var out = makeOutput(std.Buffer.append, &buffer); var out = makeOutput(std.Buffer.append, &buffer);
try printCharValues(&out, bytes); try printCharValues(&out, bytes);
try buffer.append("'"); try buffer.append("'");
std.fmt.format(&buffer, anyerror, std.Buffer.append, " at position {}", .{position - (bytes.len - 1)}) catch {}; try buffer.outStream().print(" at position {}", .{position - (bytes.len - 1)});
self.error_text = buffer.toSlice(); self.error_text = buffer.toSlice();
return Error.InvalidInput; return Error.InvalidInput;
} }
@ -319,10 +319,9 @@ pub const Tokenizer = struct {
fn errorIllegalChar(self: *Tokenizer, position: usize, char: u8, comptime fmt: []const u8, args: var) Error { fn errorIllegalChar(self: *Tokenizer, position: usize, char: u8, comptime fmt: []const u8, args: var) Error {
var buffer = try std.Buffer.initSize(&self.arena.allocator, 0); var buffer = try std.Buffer.initSize(&self.arena.allocator, 0);
try buffer.append("illegal char "); try buffer.append("illegal char ");
var out = makeOutput(std.Buffer.append, &buffer); try printUnderstandableChar(&buffer, char);
try printUnderstandableChar(&out, char); try buffer.outStream().print(" at position {}", .{position});
std.fmt.format(&buffer, anyerror, std.Buffer.append, " at position {}", .{position}) catch {}; if (fmt.len != 0) try buffer.outStream().print(": " ++ fmt, args);
if (fmt.len != 0) std.fmt.format(&buffer, anyerror, std.Buffer.append, ": " ++ fmt, args) catch {};
self.error_text = buffer.toSlice(); self.error_text = buffer.toSlice();
return Error.InvalidInput; return Error.InvalidInput;
} }
@ -996,14 +995,13 @@ fn printCharValues(out: var, bytes: []const u8) !void {
} }
} }
fn printUnderstandableChar(out: var, char: u8) !void { fn printUnderstandableChar(buffer: *std.Buffer, char: u8) !void {
if (!std.ascii.isPrint(char) or char == ' ') { if (!std.ascii.isPrint(char) or char == ' ') {
const output = @typeInfo(@TypeOf(out)).Pointer.child.output; try buffer.outStream().print("\\x{X:2}", .{char});
std.fmt.format(out.context, anyerror, output, "\\x{X:2}", .{char}) catch {};
} else { } else {
try out.write("'"); try buffer.append("'");
try out.write(&[_]u8{printable_char_tab[char]}); try buffer.appendByte(printable_char_tab[char]);
try out.write("'"); try buffer.append("'");
} }
} }

View File

@ -1019,7 +1019,7 @@ const Stage2Target = extern struct {
.macosx, .macosx,
.netbsd, .netbsd,
.openbsd, .openbsd,
=> try os_builtin_str_buffer.print( => try os_builtin_str_buffer.outStream().print(
\\ .semver = .{{ \\ .semver = .{{
\\ .min = .{{ \\ .min = .{{
\\ .major = {}, \\ .major = {},
@ -1043,7 +1043,7 @@ const Stage2Target = extern struct {
target.os.version_range.semver.max.patch, target.os.version_range.semver.max.patch,
}), }),
.linux => try os_builtin_str_buffer.print( .linux => try os_builtin_str_buffer.outStream().print(
\\ .linux = .{{ \\ .linux = .{{
\\ .range = .{{ \\ .range = .{{
\\ .min = .{{ \\ .min = .{{
@ -1078,7 +1078,7 @@ const Stage2Target = extern struct {
target.os.version_range.linux.glibc.patch, target.os.version_range.linux.glibc.patch,
}), }),
.windows => try os_builtin_str_buffer.print( .windows => try os_builtin_str_buffer.outStream().print(
\\ .windows = .{{ \\ .windows = .{{
\\ .min = .{}, \\ .min = .{},
\\ .max = .{}, \\ .max = .{},

View File

@ -4752,15 +4752,10 @@ fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenInd
} }
fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8, args: var) !ast.TokenIndex { fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8, args: var) !ast.TokenIndex {
const S = struct {
fn callback(context: *Context, bytes: []const u8) error{OutOfMemory}!void {
return context.source_buffer.append(bytes);
}
};
const start_index = c.source_buffer.len(); const start_index = c.source_buffer.len();
errdefer c.source_buffer.shrink(start_index); errdefer c.source_buffer.shrink(start_index);
try std.fmt.format(c, error{OutOfMemory}, S.callback, format, args); try c.source_buffer.outStream().print(format, args);
const end_index = c.source_buffer.len(); const end_index = c.source_buffer.len();
const token_index = c.tree.tokens.len; const token_index = c.tree.tokens.len;
const new_token = try c.tree.tokens.addOne(); const new_token = try c.tree.tokens.addOne();