mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
std.fmt: breaking API changes
added adapter to AnyWriter and GenericWriter to help bridge the gap
between old and new API
make std.testing.expectFmt work at compile-time
std.fmt no longer has a dependency on std.unicode. Formatted printing
was never properly unicode-aware. Now it no longer pretends to be.
Breakage/deprecations:
* std.fs.File.reader -> std.fs.File.deprecatedReader
* std.fs.File.writer -> std.fs.File.deprecatedWriter
* std.io.GenericReader -> std.io.Reader
* std.io.GenericWriter -> std.io.Writer
* std.io.AnyReader -> std.io.Reader
* std.io.AnyWriter -> std.io.Writer
* std.fmt.format -> std.fmt.deprecatedFormat
* std.fmt.fmtSliceEscapeLower -> std.ascii.hexEscape
* std.fmt.fmtSliceEscapeUpper -> std.ascii.hexEscape
* std.fmt.fmtSliceHexLower -> {x}
* std.fmt.fmtSliceHexUpper -> {X}
* std.fmt.fmtIntSizeDec -> {B}
* std.fmt.fmtIntSizeBin -> {Bi}
* std.fmt.fmtDuration -> {D}
* std.fmt.fmtDurationSigned -> {D}
* {} -> {f} when there is a format method
* format method signature
- anytype -> *std.io.Writer
- inferred error set -> error{WriteFailed}
- options -> (deleted)
* std.fmt.Formatted
- now takes context type explicitly
- no fmt string
This commit is contained in:
parent
0b3f0124dc
commit
0e37ff0d59
@ -436,7 +436,6 @@ set(ZIG_STAGE2_SOURCES
|
|||||||
lib/std/elf.zig
|
lib/std/elf.zig
|
||||||
lib/std/fifo.zig
|
lib/std/fifo.zig
|
||||||
lib/std/fmt.zig
|
lib/std/fmt.zig
|
||||||
lib/std/fmt/format_float.zig
|
|
||||||
lib/std/fmt/parse_float.zig
|
lib/std/fmt/parse_float.zig
|
||||||
lib/std/fs.zig
|
lib/std/fs.zig
|
||||||
lib/std/fs/AtomicFile.zig
|
lib/std/fs/AtomicFile.zig
|
||||||
|
|||||||
@ -279,7 +279,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
|
|
||||||
const ancestor_ver = try std.SemanticVersion.parse(tagged_ancestor);
|
const ancestor_ver = try std.SemanticVersion.parse(tagged_ancestor);
|
||||||
if (zig_version.order(ancestor_ver) != .gt) {
|
if (zig_version.order(ancestor_ver) != .gt) {
|
||||||
std.debug.print("Zig version '{}' must be greater than tagged ancestor '{}'\n", .{ zig_version, ancestor_ver });
|
std.debug.print("Zig version '{f}' must be greater than tagged ancestor '{f}'\n", .{ zig_version, ancestor_ver });
|
||||||
std.process.exit(1);
|
std.process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1449,7 +1449,7 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dir = b.build_root.handle.openDir("doc/langref", .{ .iterate = true }) catch |err| {
|
var dir = b.build_root.handle.openDir("doc/langref", .{ .iterate = true }) catch |err| {
|
||||||
std.debug.panic("unable to open '{}doc/langref' directory: {s}", .{
|
std.debug.panic("unable to open '{f}doc/langref' directory: {s}", .{
|
||||||
b.build_root, @errorName(err),
|
b.build_root, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -1470,7 +1470,7 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath {
|
|||||||
// in a temporary directory
|
// in a temporary directory
|
||||||
"--cache-root", b.cache_root.path orelse ".",
|
"--cache-root", b.cache_root.path orelse ".",
|
||||||
});
|
});
|
||||||
cmd.addArgs(&.{ "--zig-lib-dir", b.fmt("{}", .{b.graph.zig_lib_directory}) });
|
cmd.addArgs(&.{ "--zig-lib-dir", b.fmt("{f}", .{b.graph.zig_lib_directory}) });
|
||||||
cmd.addArgs(&.{"-i"});
|
cmd.addArgs(&.{"-i"});
|
||||||
cmd.addFileArg(b.path(b.fmt("doc/langref/{s}", .{entry.name})));
|
cmd.addFileArg(b.path(b.fmt("doc/langref/{s}", .{entry.name})));
|
||||||
|
|
||||||
|
|||||||
2
lib/compiler/aro/aro/Compilation.zig
vendored
2
lib/compiler/aro/aro/Compilation.zig
vendored
@ -1432,7 +1432,7 @@ fn getFileContents(comp: *Compilation, path: []const u8, limit: ?u32) ![]const u
|
|||||||
defer buf.deinit();
|
defer buf.deinit();
|
||||||
|
|
||||||
const max = limit orelse std.math.maxInt(u32);
|
const max = limit orelse std.math.maxInt(u32);
|
||||||
file.reader().readAllArrayList(&buf, max) catch |e| switch (e) {
|
file.deprecatedReader().readAllArrayList(&buf, max) catch |e| switch (e) {
|
||||||
error.StreamTooLong => if (limit == null) return e,
|
error.StreamTooLong => if (limit == null) return e,
|
||||||
else => return e,
|
else => return e,
|
||||||
};
|
};
|
||||||
|
|||||||
26
lib/compiler/aro/aro/Diagnostics.zig
vendored
26
lib/compiler/aro/aro/Diagnostics.zig
vendored
@ -1,4 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const assert = std.debug.assert;
|
||||||
const Allocator = mem.Allocator;
|
const Allocator = mem.Allocator;
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const Source = @import("Source.zig");
|
const Source = @import("Source.zig");
|
||||||
@ -443,18 +444,13 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void {
|
|||||||
printRt(m, prop.msg, .{"{s}"}, .{&str});
|
printRt(m, prop.msg, .{"{s}"}, .{&str});
|
||||||
} else {
|
} else {
|
||||||
var buf: [3]u8 = undefined;
|
var buf: [3]u8 = undefined;
|
||||||
const str = std.fmt.bufPrint(&buf, "x{x}", .{std.fmt.fmtSliceHexLower(&.{msg.extra.invalid_escape.char})}) catch unreachable;
|
const str = std.fmt.bufPrint(&buf, "x{x}", .{&.{msg.extra.invalid_escape.char}}) catch unreachable;
|
||||||
printRt(m, prop.msg, .{"{s}"}, .{str});
|
printRt(m, prop.msg, .{"{s}"}, .{str});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.normalized => {
|
.normalized => {
|
||||||
const f = struct {
|
const f = struct {
|
||||||
pub fn f(
|
pub fn f(bytes: []const u8, writer: *std.io.Writer) std.io.Writer.Error!void {
|
||||||
bytes: []const u8,
|
|
||||||
comptime _: []const u8,
|
|
||||||
_: std.fmt.FormatOptions,
|
|
||||||
writer: anytype,
|
|
||||||
) !void {
|
|
||||||
var it: std.unicode.Utf8Iterator = .{
|
var it: std.unicode.Utf8Iterator = .{
|
||||||
.bytes = bytes,
|
.bytes = bytes,
|
||||||
.i = 0,
|
.i = 0,
|
||||||
@ -464,22 +460,16 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void {
|
|||||||
try writer.writeByte(@intCast(codepoint));
|
try writer.writeByte(@intCast(codepoint));
|
||||||
} else if (codepoint < 0xFFFF) {
|
} else if (codepoint < 0xFFFF) {
|
||||||
try writer.writeAll("\\u");
|
try writer.writeAll("\\u");
|
||||||
try std.fmt.formatInt(codepoint, 16, .upper, .{
|
try writer.printIntOptions(codepoint, 16, .upper, .{ .fill = '0', .width = 4 });
|
||||||
.fill = '0',
|
|
||||||
.width = 4,
|
|
||||||
}, writer);
|
|
||||||
} else {
|
} else {
|
||||||
try writer.writeAll("\\U");
|
try writer.writeAll("\\U");
|
||||||
try std.fmt.formatInt(codepoint, 16, .upper, .{
|
try writer.printIntOptions(codepoint, 16, .upper, .{ .fill = '0', .width = 8 });
|
||||||
.fill = '0',
|
|
||||||
.width = 8,
|
|
||||||
}, writer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.f;
|
}.f;
|
||||||
printRt(m, prop.msg, .{"{s}"}, .{
|
printRt(m, prop.msg, .{"{f}"}, .{
|
||||||
std.fmt.Formatter(f){ .data = msg.extra.normalized },
|
std.fmt.Formatter([]const u8, f){ .data = msg.extra.normalized },
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.none, .offset => m.write(prop.msg),
|
.none, .offset => m.write(prop.msg),
|
||||||
@ -541,7 +531,7 @@ const MsgWriter = struct {
|
|||||||
fn init(config: std.io.tty.Config) MsgWriter {
|
fn init(config: std.io.tty.Config) MsgWriter {
|
||||||
std.debug.lockStdErr();
|
std.debug.lockStdErr();
|
||||||
return .{
|
return .{
|
||||||
.w = std.io.bufferedWriter(std.fs.File.stderr().writer()),
|
.w = std.io.bufferedWriter(std.fs.File.stderr().deprecatedWriter()),
|
||||||
.config = config,
|
.config = config,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
12
lib/compiler/aro/aro/Driver.zig
vendored
12
lib/compiler/aro/aro/Driver.zig
vendored
@ -591,7 +591,7 @@ pub fn main(d: *Driver, tc: *Toolchain, args: []const []const u8, comptime fast_
|
|||||||
var macro_buf = std.ArrayList(u8).init(d.comp.gpa);
|
var macro_buf = std.ArrayList(u8).init(d.comp.gpa);
|
||||||
defer macro_buf.deinit();
|
defer macro_buf.deinit();
|
||||||
|
|
||||||
const std_out = std.fs.File.stdout().writer();
|
const std_out = std.fs.File.stdout().deprecatedWriter();
|
||||||
if (try parseArgs(d, std_out, macro_buf.writer(), args)) return;
|
if (try parseArgs(d, std_out, macro_buf.writer(), args)) return;
|
||||||
|
|
||||||
const linking = !(d.only_preprocess or d.only_syntax or d.only_compile or d.only_preprocess_and_compile);
|
const linking = !(d.only_preprocess or d.only_syntax or d.only_compile or d.only_preprocess_and_compile);
|
||||||
@ -689,7 +689,7 @@ fn processSource(
|
|||||||
std.fs.File.stdout();
|
std.fs.File.stdout();
|
||||||
defer if (d.output_name != null) file.close();
|
defer if (d.output_name != null) file.close();
|
||||||
|
|
||||||
var buf_w = std.io.bufferedWriter(file.writer());
|
var buf_w = std.io.bufferedWriter(file.deprecatedWriter());
|
||||||
|
|
||||||
pp.prettyPrintTokens(buf_w.writer(), dump_mode) catch |er|
|
pp.prettyPrintTokens(buf_w.writer(), dump_mode) catch |er|
|
||||||
return d.fatal("unable to write result: {s}", .{errorDescription(er)});
|
return d.fatal("unable to write result: {s}", .{errorDescription(er)});
|
||||||
@ -705,7 +705,7 @@ fn processSource(
|
|||||||
|
|
||||||
if (d.verbose_ast) {
|
if (d.verbose_ast) {
|
||||||
const stdout = std.fs.File.stdout();
|
const stdout = std.fs.File.stdout();
|
||||||
var buf_writer = std.io.bufferedWriter(stdout.writer());
|
var buf_writer = std.io.bufferedWriter(stdout.deprecatedWriter());
|
||||||
tree.dump(d.detectConfig(stdout), buf_writer.writer()) catch {};
|
tree.dump(d.detectConfig(stdout), buf_writer.writer()) catch {};
|
||||||
buf_writer.flush() catch {};
|
buf_writer.flush() catch {};
|
||||||
}
|
}
|
||||||
@ -735,7 +735,7 @@ fn processSource(
|
|||||||
|
|
||||||
if (d.verbose_ir) {
|
if (d.verbose_ir) {
|
||||||
const stdout = std.fs.File.stdout();
|
const stdout = std.fs.File.stdout();
|
||||||
var buf_writer = std.io.bufferedWriter(stdout.writer());
|
var buf_writer = std.io.bufferedWriter(stdout.deprecatedWriter());
|
||||||
ir.dump(d.comp.gpa, d.detectConfig(stdout), buf_writer.writer()) catch {};
|
ir.dump(d.comp.gpa, d.detectConfig(stdout), buf_writer.writer()) catch {};
|
||||||
buf_writer.flush() catch {};
|
buf_writer.flush() catch {};
|
||||||
}
|
}
|
||||||
@ -806,10 +806,10 @@ fn processSource(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn dumpLinkerArgs(items: []const []const u8) !void {
|
fn dumpLinkerArgs(items: []const []const u8) !void {
|
||||||
const stdout = std.fs.File.stdout().writer();
|
const stdout = std.fs.File.stdout().deprecatedWriter();
|
||||||
for (items, 0..) |item, i| {
|
for (items, 0..) |item, i| {
|
||||||
if (i > 0) try stdout.writeByte(' ');
|
if (i > 0) try stdout.writeByte(' ');
|
||||||
try stdout.print("\"{}\"", .{std.zig.fmtEscapes(item)});
|
try stdout.print("\"{f}\"", .{std.zig.fmtString(item)});
|
||||||
}
|
}
|
||||||
try stdout.writeByte('\n');
|
try stdout.writeByte('\n');
|
||||||
}
|
}
|
||||||
|
|||||||
10
lib/compiler/aro/aro/Parser.zig
vendored
10
lib/compiler/aro/aro/Parser.zig
vendored
@ -500,8 +500,8 @@ fn checkDeprecatedUnavailable(p: *Parser, ty: Type, usage_tok: TokenIndex, decl_
|
|||||||
|
|
||||||
const w = p.strings.writer();
|
const w = p.strings.writer();
|
||||||
const msg_str = p.comp.interner.get(@"error".msg.ref()).bytes;
|
const msg_str = p.comp.interner.get(@"error".msg.ref()).bytes;
|
||||||
try w.print("call to '{s}' declared with attribute error: {}", .{
|
try w.print("call to '{s}' declared with attribute error: {f}", .{
|
||||||
p.tokSlice(@"error".__name_tok), std.zig.fmtEscapes(msg_str),
|
p.tokSlice(@"error".__name_tok), std.zig.fmtString(msg_str),
|
||||||
});
|
});
|
||||||
const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
|
const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
|
||||||
try p.errStr(.error_attribute, usage_tok, str);
|
try p.errStr(.error_attribute, usage_tok, str);
|
||||||
@ -512,8 +512,8 @@ fn checkDeprecatedUnavailable(p: *Parser, ty: Type, usage_tok: TokenIndex, decl_
|
|||||||
|
|
||||||
const w = p.strings.writer();
|
const w = p.strings.writer();
|
||||||
const msg_str = p.comp.interner.get(warning.msg.ref()).bytes;
|
const msg_str = p.comp.interner.get(warning.msg.ref()).bytes;
|
||||||
try w.print("call to '{s}' declared with attribute warning: {}", .{
|
try w.print("call to '{s}' declared with attribute warning: {f}", .{
|
||||||
p.tokSlice(warning.__name_tok), std.zig.fmtEscapes(msg_str),
|
p.tokSlice(warning.__name_tok), std.zig.fmtString(msg_str),
|
||||||
});
|
});
|
||||||
const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
|
const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
|
||||||
try p.errStr(.warning_attribute, usage_tok, str);
|
try p.errStr(.warning_attribute, usage_tok, str);
|
||||||
@ -542,7 +542,7 @@ fn errDeprecated(p: *Parser, tag: Diagnostics.Tag, tok_i: TokenIndex, msg: ?Valu
|
|||||||
try w.writeAll(reason);
|
try w.writeAll(reason);
|
||||||
if (msg) |m| {
|
if (msg) |m| {
|
||||||
const str = p.comp.interner.get(m.ref()).bytes;
|
const str = p.comp.interner.get(m.ref()).bytes;
|
||||||
try w.print(": {}", .{std.zig.fmtEscapes(str)});
|
try w.print(": {f}", .{std.zig.fmtString(str)});
|
||||||
}
|
}
|
||||||
const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
|
const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
|
||||||
return p.errStr(tag, tok_i, str);
|
return p.errStr(tag, tok_i, str);
|
||||||
|
|||||||
5
lib/compiler/aro/aro/Preprocessor.zig
vendored
5
lib/compiler/aro/aro/Preprocessor.zig
vendored
@ -811,7 +811,7 @@ fn verboseLog(pp: *Preprocessor, raw: RawToken, comptime fmt: []const u8, args:
|
|||||||
const source = pp.comp.getSource(raw.source);
|
const source = pp.comp.getSource(raw.source);
|
||||||
const line_col = source.lineCol(.{ .id = raw.source, .line = raw.line, .byte_offset = raw.start });
|
const line_col = source.lineCol(.{ .id = raw.source, .line = raw.line, .byte_offset = raw.start });
|
||||||
|
|
||||||
const stderr = std.fs.File.stderr().writer();
|
const stderr = std.fs.File.stderr().deprecatedWriter();
|
||||||
var buf_writer = std.io.bufferedWriter(stderr);
|
var buf_writer = std.io.bufferedWriter(stderr);
|
||||||
const writer = buf_writer.writer();
|
const writer = buf_writer.writer();
|
||||||
defer buf_writer.flush() catch {};
|
defer buf_writer.flush() catch {};
|
||||||
@ -3262,7 +3262,8 @@ fn printLinemarker(
|
|||||||
// containing the same bytes as the input regardless of encoding.
|
// containing the same bytes as the input regardless of encoding.
|
||||||
else => {
|
else => {
|
||||||
try w.writeAll("\\x");
|
try w.writeAll("\\x");
|
||||||
try std.fmt.formatInt(byte, 16, .lower, .{ .width = 2, .fill = '0' }, w);
|
// TODO try w.printIntOptions(byte, 16, .lower, .{ .width = 2, .fill = '0' });
|
||||||
|
try w.print("{x:0>2}", .{byte});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
try w.writeByte('"');
|
try w.writeByte('"');
|
||||||
|
|||||||
2
lib/compiler/aro/aro/Value.zig
vendored
2
lib/compiler/aro/aro/Value.zig
vendored
@ -982,7 +982,7 @@ pub fn printString(bytes: []const u8, ty: Type, comp: *const Compilation, w: any
|
|||||||
const without_null = bytes[0 .. bytes.len - @intFromEnum(size)];
|
const without_null = bytes[0 .. bytes.len - @intFromEnum(size)];
|
||||||
try w.writeByte('"');
|
try w.writeByte('"');
|
||||||
switch (size) {
|
switch (size) {
|
||||||
.@"1" => try w.print("{}", .{std.zig.fmtEscapes(without_null)}),
|
.@"1" => try w.print("{f}", .{std.zig.fmtString(without_null)}),
|
||||||
.@"2" => {
|
.@"2" => {
|
||||||
var items: [2]u16 = undefined;
|
var items: [2]u16 = undefined;
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
|
|||||||
2
lib/compiler/aro/backend/Object/Elf.zig
vendored
2
lib/compiler/aro/backend/Object/Elf.zig
vendored
@ -171,7 +171,7 @@ pub fn addRelocation(elf: *Elf, name: []const u8, section_kind: Object.Section,
|
|||||||
/// strtab
|
/// strtab
|
||||||
/// section headers
|
/// section headers
|
||||||
pub fn finish(elf: *Elf, file: std.fs.File) !void {
|
pub fn finish(elf: *Elf, file: std.fs.File) !void {
|
||||||
var buf_writer = std.io.bufferedWriter(file.writer());
|
var buf_writer = std.io.bufferedWriter(file.deprecatedWriter());
|
||||||
const w = buf_writer.writer();
|
const w = buf_writer.writer();
|
||||||
|
|
||||||
var num_sections: std.elf.Elf64_Half = additional_sections;
|
var num_sections: std.elf.Elf64_Half = additional_sections;
|
||||||
|
|||||||
@ -849,7 +849,7 @@ const Context = struct {
|
|||||||
fn addIdentifier(c: *Context, bytes: []const u8) Allocator.Error!TokenIndex {
|
fn addIdentifier(c: *Context, bytes: []const u8) Allocator.Error!TokenIndex {
|
||||||
if (std.zig.primitives.isPrimitive(bytes))
|
if (std.zig.primitives.isPrimitive(bytes))
|
||||||
return c.addTokenFmt(.identifier, "@\"{s}\"", .{bytes});
|
return c.addTokenFmt(.identifier, "@\"{s}\"", .{bytes});
|
||||||
return c.addTokenFmt(.identifier, "{p}", .{std.zig.fmtId(bytes)});
|
return c.addTokenFmt(.identifier, "{f}", .{std.zig.fmtIdFlags(bytes, .{ .allow_primitive = true })});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn listToSpan(c: *Context, list: []const NodeIndex) Allocator.Error!NodeSubRange {
|
fn listToSpan(c: *Context, list: []const NodeIndex) Allocator.Error!NodeSubRange {
|
||||||
@ -1201,7 +1201,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
|
|||||||
|
|
||||||
const compile_error_tok = try c.addToken(.builtin, "@compileError");
|
const compile_error_tok = try c.addToken(.builtin, "@compileError");
|
||||||
_ = try c.addToken(.l_paren, "(");
|
_ = try c.addToken(.l_paren, "(");
|
||||||
const err_msg_tok = try c.addTokenFmt(.string_literal, "\"{}\"", .{std.zig.fmtEscapes(payload.mangled)});
|
const err_msg_tok = try c.addTokenFmt(.string_literal, "\"{f}\"", .{std.zig.fmtString(payload.mangled)});
|
||||||
const err_msg = try c.addNode(.{
|
const err_msg = try c.addNode(.{
|
||||||
.tag = .string_literal,
|
.tag = .string_literal,
|
||||||
.main_token = err_msg_tok,
|
.main_token = err_msg_tok,
|
||||||
@ -2116,7 +2116,7 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {
|
|||||||
defer c.gpa.free(members);
|
defer c.gpa.free(members);
|
||||||
|
|
||||||
for (payload.fields, 0..) |field, i| {
|
for (payload.fields, 0..) |field, i| {
|
||||||
const name_tok = try c.addTokenFmt(.identifier, "{p}", .{std.zig.fmtId(field.name)});
|
const name_tok = try c.addTokenFmt(.identifier, "{f}", .{std.zig.fmtIdFlags(field.name, .{ .allow_primitive = true })});
|
||||||
_ = try c.addToken(.colon, ":");
|
_ = try c.addToken(.colon, ":");
|
||||||
const type_expr = try renderNode(c, field.type);
|
const type_expr = try renderNode(c, field.type);
|
||||||
|
|
||||||
@ -2205,7 +2205,7 @@ fn renderFieldAccess(c: *Context, lhs: NodeIndex, field_name: []const u8) !NodeI
|
|||||||
.main_token = try c.addToken(.period, "."),
|
.main_token = try c.addToken(.period, "."),
|
||||||
.data = .{ .node_and_token = .{
|
.data = .{ .node_and_token = .{
|
||||||
lhs,
|
lhs,
|
||||||
try c.addTokenFmt(.identifier, "{p}", .{std.zig.fmtId(field_name)}),
|
try c.addTokenFmt(.identifier, "{f}", .{std.zig.fmtIdFlags(field_name, .{ .allow_primitive = true })}),
|
||||||
} },
|
} },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -2681,7 +2681,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {
|
|||||||
_ = try c.addToken(.l_paren, "(");
|
_ = try c.addToken(.l_paren, "(");
|
||||||
const res = try c.addNode(.{
|
const res = try c.addNode(.{
|
||||||
.tag = .string_literal,
|
.tag = .string_literal,
|
||||||
.main_token = try c.addTokenFmt(.string_literal, "\"{}\"", .{std.zig.fmtEscapes(some)}),
|
.main_token = try c.addTokenFmt(.string_literal, "\"{f}\"", .{std.zig.fmtString(some)}),
|
||||||
.data = undefined,
|
.data = undefined,
|
||||||
});
|
});
|
||||||
_ = try c.addToken(.r_paren, ")");
|
_ = try c.addToken(.r_paren, ")");
|
||||||
@ -2765,7 +2765,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
|
|||||||
_ = try c.addToken(.l_paren, "(");
|
_ = try c.addToken(.l_paren, "(");
|
||||||
const res = try c.addNode(.{
|
const res = try c.addNode(.{
|
||||||
.tag = .string_literal,
|
.tag = .string_literal,
|
||||||
.main_token = try c.addTokenFmt(.string_literal, "\"{}\"", .{std.zig.fmtEscapes(some)}),
|
.main_token = try c.addTokenFmt(.string_literal, "\"{f}\"", .{std.zig.fmtString(some)}),
|
||||||
.data = undefined,
|
.data = undefined,
|
||||||
});
|
});
|
||||||
_ = try c.addToken(.r_paren, ")");
|
_ = try c.addToken(.r_paren, ")");
|
||||||
|
|||||||
@ -365,7 +365,7 @@ pub fn main() !void {
|
|||||||
.data = buffer.items,
|
.data = buffer.items,
|
||||||
.flags = .{ .exclusive = true },
|
.flags = .{ .exclusive = true },
|
||||||
}) catch |err| {
|
}) catch |err| {
|
||||||
fatal("unable to write configuration results to '{}{s}': {s}", .{
|
fatal("unable to write configuration results to '{f}{s}': {s}", .{
|
||||||
local_cache_directory, tmp_sub_path, @errorName(err),
|
local_cache_directory, tmp_sub_path, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -378,7 +378,7 @@ pub fn main() !void {
|
|||||||
|
|
||||||
validateSystemLibraryOptions(builder);
|
validateSystemLibraryOptions(builder);
|
||||||
|
|
||||||
const stdout_writer = std.fs.File.stdout().writer();
|
const stdout_writer = std.fs.File.stdout().deprecatedWriter();
|
||||||
|
|
||||||
if (help_menu)
|
if (help_menu)
|
||||||
return usage(builder, stdout_writer);
|
return usage(builder, stdout_writer);
|
||||||
@ -704,14 +704,14 @@ fn runStepNames(
|
|||||||
ttyconf.setColor(stderr, .cyan) catch {};
|
ttyconf.setColor(stderr, .cyan) catch {};
|
||||||
stderr.writeAll("Build Summary:") catch {};
|
stderr.writeAll("Build Summary:") catch {};
|
||||||
ttyconf.setColor(stderr, .reset) catch {};
|
ttyconf.setColor(stderr, .reset) catch {};
|
||||||
stderr.writer().print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {};
|
stderr.deprecatedWriter().print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {};
|
||||||
if (skipped_count > 0) stderr.writer().print("; {d} skipped", .{skipped_count}) catch {};
|
if (skipped_count > 0) stderr.deprecatedWriter().print("; {d} skipped", .{skipped_count}) catch {};
|
||||||
if (failure_count > 0) stderr.writer().print("; {d} failed", .{failure_count}) catch {};
|
if (failure_count > 0) stderr.deprecatedWriter().print("; {d} failed", .{failure_count}) catch {};
|
||||||
|
|
||||||
if (test_count > 0) stderr.writer().print("; {d}/{d} tests passed", .{ test_pass_count, test_count }) catch {};
|
if (test_count > 0) stderr.deprecatedWriter().print("; {d}/{d} tests passed", .{ test_pass_count, test_count }) catch {};
|
||||||
if (test_skip_count > 0) stderr.writer().print("; {d} skipped", .{test_skip_count}) catch {};
|
if (test_skip_count > 0) stderr.deprecatedWriter().print("; {d} skipped", .{test_skip_count}) catch {};
|
||||||
if (test_fail_count > 0) stderr.writer().print("; {d} failed", .{test_fail_count}) catch {};
|
if (test_fail_count > 0) stderr.deprecatedWriter().print("; {d} failed", .{test_fail_count}) catch {};
|
||||||
if (test_leak_count > 0) stderr.writer().print("; {d} leaked", .{test_leak_count}) catch {};
|
if (test_leak_count > 0) stderr.deprecatedWriter().print("; {d} leaked", .{test_leak_count}) catch {};
|
||||||
|
|
||||||
stderr.writeAll("\n") catch {};
|
stderr.writeAll("\n") catch {};
|
||||||
|
|
||||||
@ -820,10 +820,10 @@ fn printStepStatus(
|
|||||||
try stderr.writeAll(" cached");
|
try stderr.writeAll(" cached");
|
||||||
} else if (s.test_results.test_count > 0) {
|
} else if (s.test_results.test_count > 0) {
|
||||||
const pass_count = s.test_results.passCount();
|
const pass_count = s.test_results.passCount();
|
||||||
try stderr.writer().print(" {d} passed", .{pass_count});
|
try stderr.deprecatedWriter().print(" {d} passed", .{pass_count});
|
||||||
if (s.test_results.skip_count > 0) {
|
if (s.test_results.skip_count > 0) {
|
||||||
try ttyconf.setColor(stderr, .yellow);
|
try ttyconf.setColor(stderr, .yellow);
|
||||||
try stderr.writer().print(" {d} skipped", .{s.test_results.skip_count});
|
try stderr.deprecatedWriter().print(" {d} skipped", .{s.test_results.skip_count});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try stderr.writeAll(" success");
|
try stderr.writeAll(" success");
|
||||||
@ -832,15 +832,15 @@ fn printStepStatus(
|
|||||||
if (s.result_duration_ns) |ns| {
|
if (s.result_duration_ns) |ns| {
|
||||||
try ttyconf.setColor(stderr, .dim);
|
try ttyconf.setColor(stderr, .dim);
|
||||||
if (ns >= std.time.ns_per_min) {
|
if (ns >= std.time.ns_per_min) {
|
||||||
try stderr.writer().print(" {d}m", .{ns / std.time.ns_per_min});
|
try stderr.deprecatedWriter().print(" {d}m", .{ns / std.time.ns_per_min});
|
||||||
} else if (ns >= std.time.ns_per_s) {
|
} else if (ns >= std.time.ns_per_s) {
|
||||||
try stderr.writer().print(" {d}s", .{ns / std.time.ns_per_s});
|
try stderr.deprecatedWriter().print(" {d}s", .{ns / std.time.ns_per_s});
|
||||||
} else if (ns >= std.time.ns_per_ms) {
|
} else if (ns >= std.time.ns_per_ms) {
|
||||||
try stderr.writer().print(" {d}ms", .{ns / std.time.ns_per_ms});
|
try stderr.deprecatedWriter().print(" {d}ms", .{ns / std.time.ns_per_ms});
|
||||||
} else if (ns >= std.time.ns_per_us) {
|
} else if (ns >= std.time.ns_per_us) {
|
||||||
try stderr.writer().print(" {d}us", .{ns / std.time.ns_per_us});
|
try stderr.deprecatedWriter().print(" {d}us", .{ns / std.time.ns_per_us});
|
||||||
} else {
|
} else {
|
||||||
try stderr.writer().print(" {d}ns", .{ns});
|
try stderr.deprecatedWriter().print(" {d}ns", .{ns});
|
||||||
}
|
}
|
||||||
try ttyconf.setColor(stderr, .reset);
|
try ttyconf.setColor(stderr, .reset);
|
||||||
}
|
}
|
||||||
@ -848,13 +848,13 @@ fn printStepStatus(
|
|||||||
const rss = s.result_peak_rss;
|
const rss = s.result_peak_rss;
|
||||||
try ttyconf.setColor(stderr, .dim);
|
try ttyconf.setColor(stderr, .dim);
|
||||||
if (rss >= 1000_000_000) {
|
if (rss >= 1000_000_000) {
|
||||||
try stderr.writer().print(" MaxRSS:{d}G", .{rss / 1000_000_000});
|
try stderr.deprecatedWriter().print(" MaxRSS:{d}G", .{rss / 1000_000_000});
|
||||||
} else if (rss >= 1000_000) {
|
} else if (rss >= 1000_000) {
|
||||||
try stderr.writer().print(" MaxRSS:{d}M", .{rss / 1000_000});
|
try stderr.deprecatedWriter().print(" MaxRSS:{d}M", .{rss / 1000_000});
|
||||||
} else if (rss >= 1000) {
|
} else if (rss >= 1000) {
|
||||||
try stderr.writer().print(" MaxRSS:{d}K", .{rss / 1000});
|
try stderr.deprecatedWriter().print(" MaxRSS:{d}K", .{rss / 1000});
|
||||||
} else {
|
} else {
|
||||||
try stderr.writer().print(" MaxRSS:{d}B", .{rss});
|
try stderr.deprecatedWriter().print(" MaxRSS:{d}B", .{rss});
|
||||||
}
|
}
|
||||||
try ttyconf.setColor(stderr, .reset);
|
try ttyconf.setColor(stderr, .reset);
|
||||||
}
|
}
|
||||||
@ -866,7 +866,7 @@ fn printStepStatus(
|
|||||||
if (skip == .skipped_oom) {
|
if (skip == .skipped_oom) {
|
||||||
try stderr.writeAll(" (not enough memory)");
|
try stderr.writeAll(" (not enough memory)");
|
||||||
try ttyconf.setColor(stderr, .dim);
|
try ttyconf.setColor(stderr, .dim);
|
||||||
try stderr.writer().print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss });
|
try stderr.deprecatedWriter().print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss });
|
||||||
try ttyconf.setColor(stderr, .yellow);
|
try ttyconf.setColor(stderr, .yellow);
|
||||||
}
|
}
|
||||||
try stderr.writeAll("\n");
|
try stderr.writeAll("\n");
|
||||||
@ -883,18 +883,18 @@ fn printStepFailure(
|
|||||||
) !void {
|
) !void {
|
||||||
if (s.result_error_bundle.errorMessageCount() > 0) {
|
if (s.result_error_bundle.errorMessageCount() > 0) {
|
||||||
try ttyconf.setColor(stderr, .red);
|
try ttyconf.setColor(stderr, .red);
|
||||||
try stderr.writer().print(" {d} errors\n", .{
|
try stderr.deprecatedWriter().print(" {d} errors\n", .{
|
||||||
s.result_error_bundle.errorMessageCount(),
|
s.result_error_bundle.errorMessageCount(),
|
||||||
});
|
});
|
||||||
try ttyconf.setColor(stderr, .reset);
|
try ttyconf.setColor(stderr, .reset);
|
||||||
} else if (!s.test_results.isSuccess()) {
|
} else if (!s.test_results.isSuccess()) {
|
||||||
try stderr.writer().print(" {d}/{d} passed", .{
|
try stderr.deprecatedWriter().print(" {d}/{d} passed", .{
|
||||||
s.test_results.passCount(), s.test_results.test_count,
|
s.test_results.passCount(), s.test_results.test_count,
|
||||||
});
|
});
|
||||||
if (s.test_results.fail_count > 0) {
|
if (s.test_results.fail_count > 0) {
|
||||||
try stderr.writeAll(", ");
|
try stderr.writeAll(", ");
|
||||||
try ttyconf.setColor(stderr, .red);
|
try ttyconf.setColor(stderr, .red);
|
||||||
try stderr.writer().print("{d} failed", .{
|
try stderr.deprecatedWriter().print("{d} failed", .{
|
||||||
s.test_results.fail_count,
|
s.test_results.fail_count,
|
||||||
});
|
});
|
||||||
try ttyconf.setColor(stderr, .reset);
|
try ttyconf.setColor(stderr, .reset);
|
||||||
@ -902,7 +902,7 @@ fn printStepFailure(
|
|||||||
if (s.test_results.skip_count > 0) {
|
if (s.test_results.skip_count > 0) {
|
||||||
try stderr.writeAll(", ");
|
try stderr.writeAll(", ");
|
||||||
try ttyconf.setColor(stderr, .yellow);
|
try ttyconf.setColor(stderr, .yellow);
|
||||||
try stderr.writer().print("{d} skipped", .{
|
try stderr.deprecatedWriter().print("{d} skipped", .{
|
||||||
s.test_results.skip_count,
|
s.test_results.skip_count,
|
||||||
});
|
});
|
||||||
try ttyconf.setColor(stderr, .reset);
|
try ttyconf.setColor(stderr, .reset);
|
||||||
@ -910,7 +910,7 @@ fn printStepFailure(
|
|||||||
if (s.test_results.leak_count > 0) {
|
if (s.test_results.leak_count > 0) {
|
||||||
try stderr.writeAll(", ");
|
try stderr.writeAll(", ");
|
||||||
try ttyconf.setColor(stderr, .red);
|
try ttyconf.setColor(stderr, .red);
|
||||||
try stderr.writer().print("{d} leaked", .{
|
try stderr.deprecatedWriter().print("{d} leaked", .{
|
||||||
s.test_results.leak_count,
|
s.test_results.leak_count,
|
||||||
});
|
});
|
||||||
try ttyconf.setColor(stderr, .reset);
|
try ttyconf.setColor(stderr, .reset);
|
||||||
@ -992,7 +992,7 @@ fn printTreeStep(
|
|||||||
if (s.dependencies.items.len == 0) {
|
if (s.dependencies.items.len == 0) {
|
||||||
try stderr.writeAll(" (reused)\n");
|
try stderr.writeAll(" (reused)\n");
|
||||||
} else {
|
} else {
|
||||||
try stderr.writer().print(" (+{d} more reused dependencies)\n", .{
|
try stderr.deprecatedWriter().print(" (+{d} more reused dependencies)\n", .{
|
||||||
s.dependencies.items.len,
|
s.dependencies.items.len,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1209,7 +1209,7 @@ pub fn printErrorMessages(
|
|||||||
var indent: usize = 0;
|
var indent: usize = 0;
|
||||||
while (step_stack.pop()) |s| : (indent += 1) {
|
while (step_stack.pop()) |s| : (indent += 1) {
|
||||||
if (indent > 0) {
|
if (indent > 0) {
|
||||||
try stderr.writer().writeByteNTimes(' ', (indent - 1) * 3);
|
try stderr.deprecatedWriter().writeByteNTimes(' ', (indent - 1) * 3);
|
||||||
try printChildNodePrefix(stderr, ttyconf);
|
try printChildNodePrefix(stderr, ttyconf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1231,7 +1231,7 @@ pub fn printErrorMessages(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!prominent_compile_errors and failing_step.result_error_bundle.errorMessageCount() > 0) {
|
if (!prominent_compile_errors and failing_step.result_error_bundle.errorMessageCount() > 0) {
|
||||||
try failing_step.result_error_bundle.renderToWriter(options, stderr.writer());
|
try failing_step.result_error_bundle.renderToWriter(options, stderr.deprecatedWriter());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (failing_step.result_error_msgs.items) |msg| {
|
for (failing_step.result_error_msgs.items) |msg| {
|
||||||
|
|||||||
@ -40,7 +40,7 @@ pub fn main() !void {
|
|||||||
const arg = args[i];
|
const arg = args[i];
|
||||||
if (mem.startsWith(u8, arg, "-")) {
|
if (mem.startsWith(u8, arg, "-")) {
|
||||||
if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
|
if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
|
||||||
const stdout = std.fs.File.stdout().writer();
|
const stdout = std.fs.File.stdout().deprecatedWriter();
|
||||||
try stdout.writeAll(usage_libc);
|
try stdout.writeAll(usage_libc);
|
||||||
return std.process.cleanExit();
|
return std.process.cleanExit();
|
||||||
} else if (mem.eql(u8, arg, "-target")) {
|
} else if (mem.eql(u8, arg, "-target")) {
|
||||||
@ -97,7 +97,7 @@ pub fn main() !void {
|
|||||||
fatal("no include dirs detected for target {s}", .{zig_target});
|
fatal("no include dirs detected for target {s}", .{zig_target});
|
||||||
}
|
}
|
||||||
|
|
||||||
var bw = std.io.bufferedWriter(std.fs.File.stdout().writer());
|
var bw = std.io.bufferedWriter(std.fs.File.stdout().deprecatedWriter());
|
||||||
var writer = bw.writer();
|
var writer = bw.writer();
|
||||||
for (libc_dirs.libc_include_dir_list) |include_dir| {
|
for (libc_dirs.libc_include_dir_list) |include_dir| {
|
||||||
try writer.writeAll(include_dir);
|
try writer.writeAll(include_dir);
|
||||||
@ -125,7 +125,7 @@ pub fn main() !void {
|
|||||||
};
|
};
|
||||||
defer libc.deinit(gpa);
|
defer libc.deinit(gpa);
|
||||||
|
|
||||||
var bw = std.io.bufferedWriter(std.fs.File.stdout().writer());
|
var bw = std.io.bufferedWriter(std.fs.File.stdout().deprecatedWriter());
|
||||||
try libc.render(bw.writer());
|
try libc.render(bw.writer());
|
||||||
try bw.flush();
|
try bw.flush();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -635,11 +635,11 @@ const HexWriter = struct {
|
|||||||
const payload_bytes = self.getPayloadBytes();
|
const payload_bytes = self.getPayloadBytes();
|
||||||
assert(payload_bytes.len <= MAX_PAYLOAD_LEN);
|
assert(payload_bytes.len <= MAX_PAYLOAD_LEN);
|
||||||
|
|
||||||
const line = try std.fmt.bufPrint(&outbuf, ":{0X:0>2}{1X:0>4}{2X:0>2}{3s}{4X:0>2}" ++ linesep, .{
|
const line = try std.fmt.bufPrint(&outbuf, ":{0X:0>2}{1X:0>4}{2X:0>2}{3X}{4X:0>2}" ++ linesep, .{
|
||||||
@as(u8, @intCast(payload_bytes.len)),
|
@as(u8, @intCast(payload_bytes.len)),
|
||||||
self.address,
|
self.address,
|
||||||
@intFromEnum(self.payload),
|
@intFromEnum(self.payload),
|
||||||
std.fmt.fmtSliceHexUpper(payload_bytes),
|
payload_bytes,
|
||||||
self.checksum(),
|
self.checksum(),
|
||||||
});
|
});
|
||||||
try file.writeAll(line);
|
try file.writeAll(line);
|
||||||
@ -1495,7 +1495,7 @@ const ElfFileHelper = struct {
|
|||||||
if (size < prefix.len) return null;
|
if (size < prefix.len) return null;
|
||||||
|
|
||||||
try in_file.seekTo(offset);
|
try in_file.seekTo(offset);
|
||||||
var section_reader = std.io.limitedReader(in_file.reader(), size);
|
var section_reader = std.io.limitedReader(in_file.deprecatedReader(), size);
|
||||||
|
|
||||||
// allocate as large as decompressed data. if the compression doesn't fit, keep the data uncompressed.
|
// allocate as large as decompressed data. if the compression doesn't fit, keep the data uncompressed.
|
||||||
const compressed_data = try allocator.alignedAlloc(u8, .@"8", @intCast(size));
|
const compressed_data = try allocator.alignedAlloc(u8, .@"8", @intCast(size));
|
||||||
|
|||||||
@ -68,7 +68,7 @@ pub fn main() !void {
|
|||||||
const arg = args[i];
|
const arg = args[i];
|
||||||
if (mem.startsWith(u8, arg, "-")) {
|
if (mem.startsWith(u8, arg, "-")) {
|
||||||
if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
|
if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
|
||||||
const stdout = std.fs.File.stdout().writer();
|
const stdout = std.fs.File.stdout().deprecatedWriter();
|
||||||
try stdout.writeAll(usage);
|
try stdout.writeAll(usage);
|
||||||
return std.process.cleanExit();
|
return std.process.cleanExit();
|
||||||
} else if (mem.eql(u8, arg, "--")) {
|
} else if (mem.eql(u8, arg, "--")) {
|
||||||
|
|||||||
@ -127,7 +127,7 @@ pub const Diagnostics = struct {
|
|||||||
pub fn renderToStdErr(self: *Diagnostics, args: []const []const u8, config: std.io.tty.Config) void {
|
pub fn renderToStdErr(self: *Diagnostics, args: []const []const u8, config: std.io.tty.Config) void {
|
||||||
std.debug.lockStdErr();
|
std.debug.lockStdErr();
|
||||||
defer std.debug.unlockStdErr();
|
defer std.debug.unlockStdErr();
|
||||||
const stderr = std.fs.File.stderr().writer();
|
const stderr = std.fs.File.stderr().deprecatedWriter();
|
||||||
self.renderToWriter(args, stderr, config) catch return;
|
self.renderToWriter(args, stderr, config) catch return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -570,7 +570,7 @@ pub const Compiler = struct {
|
|||||||
switch (predefined_type) {
|
switch (predefined_type) {
|
||||||
.GROUP_ICON, .GROUP_CURSOR => {
|
.GROUP_ICON, .GROUP_CURSOR => {
|
||||||
// Check for animated icon first
|
// Check for animated icon first
|
||||||
if (ani.isAnimatedIcon(file.reader())) {
|
if (ani.isAnimatedIcon(file.deprecatedReader())) {
|
||||||
// Animated icons are just put into the resource unmodified,
|
// Animated icons are just put into the resource unmodified,
|
||||||
// and the resource type changes to ANIICON/ANICURSOR
|
// and the resource type changes to ANIICON/ANICURSOR
|
||||||
|
|
||||||
@ -586,14 +586,14 @@ pub const Compiler = struct {
|
|||||||
|
|
||||||
try header.write(writer, self.errContext(node.id));
|
try header.write(writer, self.errContext(node.id));
|
||||||
try file.seekTo(0);
|
try file.seekTo(0);
|
||||||
try writeResourceData(writer, file.reader(), header.data_size);
|
try writeResourceData(writer, file.deprecatedReader(), header.data_size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// isAnimatedIcon moved the file cursor so reset to the start
|
// isAnimatedIcon moved the file cursor so reset to the start
|
||||||
try file.seekTo(0);
|
try file.seekTo(0);
|
||||||
|
|
||||||
const icon_dir = ico.read(self.allocator, file.reader(), try file.getEndPos()) catch |err| switch (err) {
|
const icon_dir = ico.read(self.allocator, file.deprecatedReader(), try file.getEndPos()) catch |err| switch (err) {
|
||||||
error.OutOfMemory => |e| return e,
|
error.OutOfMemory => |e| return e,
|
||||||
else => |e| {
|
else => |e| {
|
||||||
return self.iconReadError(
|
return self.iconReadError(
|
||||||
@ -672,7 +672,7 @@ pub const Compiler = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try file.seekTo(entry.data_offset_from_start_of_file);
|
try file.seekTo(entry.data_offset_from_start_of_file);
|
||||||
var header_bytes = file.reader().readBytesNoEof(16) catch {
|
var header_bytes = file.deprecatedReader().readBytesNoEof(16) catch {
|
||||||
return self.iconReadError(
|
return self.iconReadError(
|
||||||
error.UnexpectedEOF,
|
error.UnexpectedEOF,
|
||||||
filename_utf8,
|
filename_utf8,
|
||||||
@ -803,7 +803,7 @@ pub const Compiler = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try file.seekTo(entry.data_offset_from_start_of_file);
|
try file.seekTo(entry.data_offset_from_start_of_file);
|
||||||
try writeResourceDataNoPadding(writer, file.reader(), entry.data_size_in_bytes);
|
try writeResourceDataNoPadding(writer, file.deprecatedReader(), entry.data_size_in_bytes);
|
||||||
try writeDataPadding(writer, full_data_size);
|
try writeDataPadding(writer, full_data_size);
|
||||||
|
|
||||||
if (self.state.icon_id == std.math.maxInt(u16)) {
|
if (self.state.icon_id == std.math.maxInt(u16)) {
|
||||||
@ -859,7 +859,7 @@ pub const Compiler = struct {
|
|||||||
header.applyMemoryFlags(node.common_resource_attributes, self.source);
|
header.applyMemoryFlags(node.common_resource_attributes, self.source);
|
||||||
const file_size = try file.getEndPos();
|
const file_size = try file.getEndPos();
|
||||||
|
|
||||||
const bitmap_info = bmp.read(file.reader(), file_size) catch |err| {
|
const bitmap_info = bmp.read(file.deprecatedReader(), file_size) catch |err| {
|
||||||
const filename_string_index = try self.diagnostics.putString(filename_utf8);
|
const filename_string_index = try self.diagnostics.putString(filename_utf8);
|
||||||
return self.addErrorDetailsAndFail(.{
|
return self.addErrorDetailsAndFail(.{
|
||||||
.err = .bmp_read_error,
|
.err = .bmp_read_error,
|
||||||
@ -922,7 +922,7 @@ pub const Compiler = struct {
|
|||||||
header.data_size = bmp_bytes_to_write;
|
header.data_size = bmp_bytes_to_write;
|
||||||
try header.write(writer, self.errContext(node.id));
|
try header.write(writer, self.errContext(node.id));
|
||||||
try file.seekTo(bmp.file_header_len);
|
try file.seekTo(bmp.file_header_len);
|
||||||
const file_reader = file.reader();
|
const file_reader = file.deprecatedReader();
|
||||||
try writeResourceDataNoPadding(writer, file_reader, bitmap_info.dib_header_size);
|
try writeResourceDataNoPadding(writer, file_reader, bitmap_info.dib_header_size);
|
||||||
if (bitmap_info.getBitmasksByteLen() > 0) {
|
if (bitmap_info.getBitmasksByteLen() > 0) {
|
||||||
try writeResourceDataNoPadding(writer, file_reader, bitmap_info.getBitmasksByteLen());
|
try writeResourceDataNoPadding(writer, file_reader, bitmap_info.getBitmasksByteLen());
|
||||||
@ -968,7 +968,7 @@ pub const Compiler = struct {
|
|||||||
header.data_size = @intCast(file_size);
|
header.data_size = @intCast(file_size);
|
||||||
try header.write(writer, self.errContext(node.id));
|
try header.write(writer, self.errContext(node.id));
|
||||||
|
|
||||||
var header_slurping_reader = headerSlurpingReader(148, file.reader());
|
var header_slurping_reader = headerSlurpingReader(148, file.deprecatedReader());
|
||||||
try writeResourceData(writer, header_slurping_reader.reader(), header.data_size);
|
try writeResourceData(writer, header_slurping_reader.reader(), header.data_size);
|
||||||
|
|
||||||
try self.state.font_dir.add(self.arena, FontDir.Font{
|
try self.state.font_dir.add(self.arena, FontDir.Font{
|
||||||
@ -1002,7 +1002,7 @@ pub const Compiler = struct {
|
|||||||
// We now know that the data size will fit in a u32
|
// We now know that the data size will fit in a u32
|
||||||
header.data_size = @intCast(data_size);
|
header.data_size = @intCast(data_size);
|
||||||
try header.write(writer, self.errContext(node.id));
|
try header.write(writer, self.errContext(node.id));
|
||||||
try writeResourceData(writer, file.reader(), header.data_size);
|
try writeResourceData(writer, file.deprecatedReader(), header.data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iconReadError(
|
fn iconReadError(
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const assert = std.debug.assert;
|
||||||
const Token = @import("lex.zig").Token;
|
const Token = @import("lex.zig").Token;
|
||||||
const SourceMappings = @import("source_mapping.zig").SourceMappings;
|
const SourceMappings = @import("source_mapping.zig").SourceMappings;
|
||||||
const utils = @import("utils.zig");
|
const utils = @import("utils.zig");
|
||||||
@ -63,7 +64,7 @@ pub const Diagnostics = struct {
|
|||||||
pub fn renderToStdErr(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, tty_config: std.io.tty.Config, source_mappings: ?SourceMappings) void {
|
pub fn renderToStdErr(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, tty_config: std.io.tty.Config, source_mappings: ?SourceMappings) void {
|
||||||
std.debug.lockStdErr();
|
std.debug.lockStdErr();
|
||||||
defer std.debug.unlockStdErr();
|
defer std.debug.unlockStdErr();
|
||||||
const stderr = std.fs.File.stderr().writer();
|
const stderr = std.fs.File.stderr().deprecatedWriter();
|
||||||
for (self.errors.items) |err_details| {
|
for (self.errors.items) |err_details| {
|
||||||
renderErrorMessage(stderr, tty_config, cwd, err_details, source, self.strings.items, source_mappings) catch return;
|
renderErrorMessage(stderr, tty_config, cwd, err_details, source, self.strings.items, source_mappings) catch return;
|
||||||
}
|
}
|
||||||
@ -409,15 +410,7 @@ pub const ErrorDetails = struct {
|
|||||||
failed_to_open_cwd,
|
failed_to_open_cwd,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn formatToken(
|
fn formatToken(ctx: TokenFormatContext, writer: *std.io.Writer) std.io.Writer.Error!void {
|
||||||
ctx: TokenFormatContext,
|
|
||||||
comptime fmt: []const u8,
|
|
||||||
options: std.fmt.FormatOptions,
|
|
||||||
writer: anytype,
|
|
||||||
) !void {
|
|
||||||
_ = fmt;
|
|
||||||
_ = options;
|
|
||||||
|
|
||||||
switch (ctx.token.id) {
|
switch (ctx.token.id) {
|
||||||
.eof => return writer.writeAll(ctx.token.id.nameForErrorDisplay()),
|
.eof => return writer.writeAll(ctx.token.id.nameForErrorDisplay()),
|
||||||
else => {},
|
else => {},
|
||||||
@ -441,7 +434,7 @@ pub const ErrorDetails = struct {
|
|||||||
code_page: SupportedCodePage,
|
code_page: SupportedCodePage,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn fmtToken(self: ErrorDetails, source: []const u8) std.fmt.Formatter(formatToken) {
|
fn fmtToken(self: ErrorDetails, source: []const u8) std.fmt.Formatter(TokenFormatContext, formatToken) {
|
||||||
return .{ .data = .{
|
return .{ .data = .{
|
||||||
.token = self.token,
|
.token = self.token,
|
||||||
.code_page = self.code_page,
|
.code_page = self.code_page,
|
||||||
@ -466,10 +459,14 @@ pub const ErrorDetails = struct {
|
|||||||
.hint => return,
|
.hint => return,
|
||||||
},
|
},
|
||||||
.illegal_byte => {
|
.illegal_byte => {
|
||||||
return writer.print("character '{s}' is not allowed", .{std.fmt.fmtSliceEscapeUpper(self.token.slice(source))});
|
return writer.print("character '{f}' is not allowed", .{
|
||||||
|
std.ascii.hexEscape(self.token.slice(source), .upper),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
.illegal_byte_outside_string_literals => {
|
.illegal_byte_outside_string_literals => {
|
||||||
return writer.print("character '{s}' is not allowed outside of string literals", .{std.fmt.fmtSliceEscapeUpper(self.token.slice(source))});
|
return writer.print("character '{f}' is not allowed outside of string literals", .{
|
||||||
|
std.ascii.hexEscape(self.token.slice(source), .upper),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
.illegal_codepoint_outside_string_literals => {
|
.illegal_codepoint_outside_string_literals => {
|
||||||
// This is somewhat hacky, but we know that:
|
// This is somewhat hacky, but we know that:
|
||||||
@ -1106,7 +1103,7 @@ const CorrespondingLines = struct {
|
|||||||
.code_page = err_details.code_page,
|
.code_page = err_details.code_page,
|
||||||
};
|
};
|
||||||
corresponding_lines.buffered_reader = BufferedReaderType{
|
corresponding_lines.buffered_reader = BufferedReaderType{
|
||||||
.unbuffered_reader = corresponding_lines.file.reader(),
|
.unbuffered_reader = corresponding_lines.file.deprecatedReader(),
|
||||||
};
|
};
|
||||||
errdefer corresponding_lines.deinit();
|
errdefer corresponding_lines.deinit();
|
||||||
|
|
||||||
|
|||||||
@ -237,7 +237,9 @@ pub const Lexer = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump(self: *Self, token: *const Token) void {
|
pub fn dump(self: *Self, token: *const Token) void {
|
||||||
std.debug.print("{s}:{d}: {s}\n", .{ @tagName(token.id), token.line_number, std.fmt.fmtSliceEscapeLower(token.slice(self.buffer)) });
|
std.debug.print("{s}:{d}: {f}\n", .{
|
||||||
|
@tagName(token.id), token.line_number, std.ascii.hexEscape(token.slice(self.buffer), .lower),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const LexMethod = enum {
|
pub const LexMethod = enum {
|
||||||
|
|||||||
@ -29,7 +29,7 @@ pub fn main() !void {
|
|||||||
defer std.process.argsFree(allocator, args);
|
defer std.process.argsFree(allocator, args);
|
||||||
|
|
||||||
if (args.len < 2) {
|
if (args.len < 2) {
|
||||||
try renderErrorMessage(stderr.writer(), stderr_config, .err, "expected zig lib dir as first argument", .{});
|
try renderErrorMessage(stderr.deprecatedWriter(), stderr_config, .err, "expected zig lib dir as first argument", .{});
|
||||||
std.process.exit(1);
|
std.process.exit(1);
|
||||||
}
|
}
|
||||||
const zig_lib_dir = args[1];
|
const zig_lib_dir = args[1];
|
||||||
@ -82,14 +82,14 @@ pub fn main() !void {
|
|||||||
|
|
||||||
if (options.print_help_and_exit) {
|
if (options.print_help_and_exit) {
|
||||||
const stdout = std.fs.File.stdout();
|
const stdout = std.fs.File.stdout();
|
||||||
try cli.writeUsage(stdout.writer(), "zig rc");
|
try cli.writeUsage(stdout.deprecatedWriter(), "zig rc");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow verbose when integrating with Zig via stdout
|
// Don't allow verbose when integrating with Zig via stdout
|
||||||
options.verbose = false;
|
options.verbose = false;
|
||||||
|
|
||||||
const stdout_writer = std.fs.File.stdout().writer();
|
const stdout_writer = std.fs.File.stdout().deprecatedWriter();
|
||||||
if (options.verbose) {
|
if (options.verbose) {
|
||||||
try options.dumpVerbose(stdout_writer);
|
try options.dumpVerbose(stdout_writer);
|
||||||
try stdout_writer.writeByte('\n');
|
try stdout_writer.writeByte('\n');
|
||||||
@ -290,7 +290,7 @@ pub fn main() !void {
|
|||||||
};
|
};
|
||||||
defer depfile.close();
|
defer depfile.close();
|
||||||
|
|
||||||
const depfile_writer = depfile.writer();
|
const depfile_writer = depfile.deprecatedWriter();
|
||||||
var depfile_buffered_writer = std.io.bufferedWriter(depfile_writer);
|
var depfile_buffered_writer = std.io.bufferedWriter(depfile_writer);
|
||||||
switch (options.depfile_fmt) {
|
switch (options.depfile_fmt) {
|
||||||
.json => {
|
.json => {
|
||||||
@ -645,7 +645,7 @@ const ErrorHandler = union(enum) {
|
|||||||
},
|
},
|
||||||
.tty => {
|
.tty => {
|
||||||
// extra newline to separate this line from the aro errors
|
// extra newline to separate this line from the aro errors
|
||||||
try renderErrorMessage(std.fs.File.stderr().writer(), self.tty, .err, "{s}\n", .{fail_msg});
|
try renderErrorMessage(std.fs.File.stderr().deprecatedWriter(), self.tty, .err, "{s}\n", .{fail_msg});
|
||||||
aro.Diagnostics.render(comp, self.tty);
|
aro.Diagnostics.render(comp, self.tty);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -690,7 +690,7 @@ const ErrorHandler = union(enum) {
|
|||||||
try server.serveErrorBundle(error_bundle);
|
try server.serveErrorBundle(error_bundle);
|
||||||
},
|
},
|
||||||
.tty => {
|
.tty => {
|
||||||
try renderErrorMessage(std.fs.File.stderr().writer(), self.tty, msg_type, format, args);
|
try renderErrorMessage(std.fs.File.stderr().deprecatedWriter(), self.tty, msg_type, format, args);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const assert = std.debug.assert;
|
||||||
const rc = @import("rc.zig");
|
const rc = @import("rc.zig");
|
||||||
const ResourceType = rc.ResourceType;
|
const ResourceType = rc.ResourceType;
|
||||||
const CommonResourceAttributes = rc.CommonResourceAttributes;
|
const CommonResourceAttributes = rc.CommonResourceAttributes;
|
||||||
@ -163,14 +164,8 @@ pub const Language = packed struct(u16) {
|
|||||||
return @bitCast(self);
|
return @bitCast(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(
|
pub fn format(language: Language, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
|
||||||
language: Language,
|
comptime assert(fmt.len == 0);
|
||||||
comptime fmt: []const u8,
|
|
||||||
options: std.fmt.FormatOptions,
|
|
||||||
out_stream: anytype,
|
|
||||||
) !void {
|
|
||||||
_ = fmt;
|
|
||||||
_ = options;
|
|
||||||
const language_id = language.asInt();
|
const language_id = language.asInt();
|
||||||
const language_name = language_name: {
|
const language_name = language_name: {
|
||||||
if (std.enums.fromInt(lang.LanguageId, language_id)) |lang_enum_val| {
|
if (std.enums.fromInt(lang.LanguageId, language_id)) |lang_enum_val| {
|
||||||
@ -181,7 +176,7 @@ pub const Language = packed struct(u16) {
|
|||||||
}
|
}
|
||||||
break :language_name "<UNKNOWN>";
|
break :language_name "<UNKNOWN>";
|
||||||
};
|
};
|
||||||
try out_stream.print("{s} (0x{X})", .{ language_name, language_id });
|
try w.print("{s} (0x{X})", .{ language_name, language_id });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -445,47 +440,34 @@ pub const NameOrOrdinal = union(enum) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(
|
pub fn format(self: NameOrOrdinal, w: *std.io.Writer, comptime fmt: []const u8) !void {
|
||||||
self: NameOrOrdinal,
|
comptime assert(fmt.len == 0);
|
||||||
comptime fmt: []const u8,
|
|
||||||
options: std.fmt.FormatOptions,
|
|
||||||
out_stream: anytype,
|
|
||||||
) !void {
|
|
||||||
_ = fmt;
|
|
||||||
_ = options;
|
|
||||||
switch (self) {
|
switch (self) {
|
||||||
.name => |name| {
|
.name => |name| {
|
||||||
try out_stream.print("{s}", .{std.unicode.fmtUtf16Le(name)});
|
try w.print("{s}", .{std.unicode.fmtUtf16Le(name)});
|
||||||
},
|
},
|
||||||
.ordinal => |ordinal| {
|
.ordinal => |ordinal| {
|
||||||
try out_stream.print("{d}", .{ordinal});
|
try w.print("{d}", .{ordinal});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn formatResourceType(
|
fn formatResourceType(self: NameOrOrdinal, w: *std.io.Writer) std.io.Writer.Error!void {
|
||||||
self: NameOrOrdinal,
|
|
||||||
comptime fmt: []const u8,
|
|
||||||
options: std.fmt.FormatOptions,
|
|
||||||
out_stream: anytype,
|
|
||||||
) !void {
|
|
||||||
_ = fmt;
|
|
||||||
_ = options;
|
|
||||||
switch (self) {
|
switch (self) {
|
||||||
.name => |name| {
|
.name => |name| {
|
||||||
try out_stream.print("{s}", .{std.unicode.fmtUtf16Le(name)});
|
try w.print("{s}", .{std.unicode.fmtUtf16Le(name)});
|
||||||
},
|
},
|
||||||
.ordinal => |ordinal| {
|
.ordinal => |ordinal| {
|
||||||
if (std.enums.tagName(RT, @enumFromInt(ordinal))) |predefined_type_name| {
|
if (std.enums.tagName(RT, @enumFromInt(ordinal))) |predefined_type_name| {
|
||||||
try out_stream.print("{s}", .{predefined_type_name});
|
try w.print("{s}", .{predefined_type_name});
|
||||||
} else {
|
} else {
|
||||||
try out_stream.print("{d}", .{ordinal});
|
try w.print("{d}", .{ordinal});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmtResourceType(type_value: NameOrOrdinal) std.fmt.Formatter(formatResourceType) {
|
pub fn fmtResourceType(type_value: NameOrOrdinal) std.fmt.Formatter(NameOrOrdinal, formatResourceType) {
|
||||||
return .{ .data = type_value };
|
return .{ .data = type_value };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -328,7 +328,7 @@ pub fn mainSimple() anyerror!void {
|
|||||||
passed += 1;
|
passed += 1;
|
||||||
}
|
}
|
||||||
if (enable_print and print_summary) {
|
if (enable_print and print_summary) {
|
||||||
stderr.writer().print("{} passed, {} skipped, {} failed\n", .{ passed, skipped, failed }) catch {};
|
stderr.deprecatedWriter().print("{} passed, {} skipped, {} failed\n", .{ passed, skipped, failed }) catch {};
|
||||||
}
|
}
|
||||||
if (failed != 0) std.process.exit(1);
|
if (failed != 0) std.process.exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -160,7 +160,7 @@ fn mainImpl() !void {
|
|||||||
var doc = try parser.endInput();
|
var doc = try parser.endInput();
|
||||||
defer doc.deinit(gpa);
|
defer doc.deinit(gpa);
|
||||||
|
|
||||||
var stdout_buf = std.io.bufferedWriter(std.fs.File.stdout().writer());
|
var stdout_buf = std.io.bufferedWriter(std.fs.File.stdout().deprecatedWriter());
|
||||||
try doc.render(stdout_buf.writer());
|
try doc.render(stdout_buf.writer());
|
||||||
try stdout_buf.flush();
|
try stdout_buf.flush();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Document = @import("Document.zig");
|
const Document = @import("Document.zig");
|
||||||
const Node = Document.Node;
|
const Node = Document.Node;
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
/// A Markdown document renderer.
|
/// A Markdown document renderer.
|
||||||
///
|
///
|
||||||
@ -229,18 +230,11 @@ pub fn renderInlineNodeText(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmtHtml(bytes: []const u8) std.fmt.Formatter(formatHtml) {
|
pub fn fmtHtml(bytes: []const u8) std.fmt.Formatter([]const u8, formatHtml) {
|
||||||
return .{ .data = bytes };
|
return .{ .data = bytes };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn formatHtml(
|
fn formatHtml(bytes: []const u8, writer: *std.io.Writer) std.io.Writer.Error!void {
|
||||||
bytes: []const u8,
|
|
||||||
comptime fmt: []const u8,
|
|
||||||
options: std.fmt.FormatOptions,
|
|
||||||
writer: anytype,
|
|
||||||
) !void {
|
|
||||||
_ = fmt;
|
|
||||||
_ = options;
|
|
||||||
for (bytes) |b| {
|
for (bytes) |b| {
|
||||||
switch (b) {
|
switch (b) {
|
||||||
'<' => try writer.writeAll("<"),
|
'<' => try writer.writeAll("<"),
|
||||||
|
|||||||
@ -5,7 +5,7 @@ pub fn bufferedPrint() !void {
|
|||||||
// Stdout is for the actual output of your application, for example if you
|
// Stdout is for the actual output of your application, for example if you
|
||||||
// are implementing gzip, then only the compressed bytes should be sent to
|
// are implementing gzip, then only the compressed bytes should be sent to
|
||||||
// stdout, not any debugging messages.
|
// stdout, not any debugging messages.
|
||||||
const stdout_file = std.fs.File.stdout().writer();
|
const stdout_file = std.fs.File.stdout().deprecatedWriter();
|
||||||
// Buffering can improve performance significantly in print-heavy programs.
|
// Buffering can improve performance significantly in print-heavy programs.
|
||||||
var bw = std.io.bufferedWriter(stdout_file);
|
var bw = std.io.bufferedWriter(stdout_file);
|
||||||
const stdout = bw.writer();
|
const stdout = bw.writer();
|
||||||
|
|||||||
@ -1745,7 +1745,7 @@ pub fn addUserInputOption(b: *Build, name_raw: []const u8, value_raw: []const u8
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
.lazy_path, .lazy_path_list => {
|
.lazy_path, .lazy_path_list => {
|
||||||
log.warn("the lazy path value type isn't added from the CLI, but somehow '{s}' is a .{}", .{ name, std.zig.fmtId(@tagName(gop.value_ptr.value)) });
|
log.warn("the lazy path value type isn't added from the CLI, but somehow '{s}' is a .{f}", .{ name, std.zig.fmtId(@tagName(gop.value_ptr.value)) });
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -2059,7 +2059,7 @@ pub fn runAllowFail(
|
|||||||
try Step.handleVerbose2(b, null, child.env_map, argv);
|
try Step.handleVerbose2(b, null, child.env_map, argv);
|
||||||
try child.spawn();
|
try child.spawn();
|
||||||
|
|
||||||
const stdout = child.stdout.?.reader().readAllAlloc(b.allocator, max_output_size) catch {
|
const stdout = child.stdout.?.deprecatedReader().readAllAlloc(b.allocator, max_output_size) catch {
|
||||||
return error.ReadFailure;
|
return error.ReadFailure;
|
||||||
};
|
};
|
||||||
errdefer b.allocator.free(stdout);
|
errdefer b.allocator.free(stdout);
|
||||||
@ -2770,7 +2770,7 @@ fn dumpBadDirnameHelp(
|
|||||||
defer debug.unlockStdErr();
|
defer debug.unlockStdErr();
|
||||||
|
|
||||||
const stderr: fs.File = .stderr();
|
const stderr: fs.File = .stderr();
|
||||||
const w = stderr.writer();
|
const w = stderr.deprecatedWriter();
|
||||||
try w.print(msg, args);
|
try w.print(msg, args);
|
||||||
|
|
||||||
const tty_config = std.io.tty.detectConfig(stderr);
|
const tty_config = std.io.tty.detectConfig(stderr);
|
||||||
@ -2785,7 +2785,7 @@ fn dumpBadDirnameHelp(
|
|||||||
|
|
||||||
if (asking_step) |as| {
|
if (asking_step) |as| {
|
||||||
tty_config.setColor(w, .red) catch {};
|
tty_config.setColor(w, .red) catch {};
|
||||||
try stderr.writer().print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name});
|
try stderr.deprecatedWriter().print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name});
|
||||||
tty_config.setColor(w, .reset) catch {};
|
tty_config.setColor(w, .reset) catch {};
|
||||||
|
|
||||||
as.dump(stderr);
|
as.dump(stderr);
|
||||||
@ -2803,7 +2803,7 @@ pub fn dumpBadGetPathHelp(
|
|||||||
src_builder: *Build,
|
src_builder: *Build,
|
||||||
asking_step: ?*Step,
|
asking_step: ?*Step,
|
||||||
) anyerror!void {
|
) anyerror!void {
|
||||||
const w = stderr.writer();
|
const w = stderr.deprecatedWriter();
|
||||||
try w.print(
|
try w.print(
|
||||||
\\getPath() was called on a GeneratedFile that wasn't built yet.
|
\\getPath() was called on a GeneratedFile that wasn't built yet.
|
||||||
\\ source package path: {s}
|
\\ source package path: {s}
|
||||||
@ -2822,7 +2822,7 @@ pub fn dumpBadGetPathHelp(
|
|||||||
s.dump(stderr);
|
s.dump(stderr);
|
||||||
if (asking_step) |as| {
|
if (asking_step) |as| {
|
||||||
tty_config.setColor(w, .red) catch {};
|
tty_config.setColor(w, .red) catch {};
|
||||||
try stderr.writer().print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name});
|
try stderr.deprecatedWriter().print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name});
|
||||||
tty_config.setColor(w, .reset) catch {};
|
tty_config.setColor(w, .reset) catch {};
|
||||||
|
|
||||||
as.dump(stderr);
|
as.dump(stderr);
|
||||||
|
|||||||
@ -68,7 +68,7 @@ const PrefixedPath = struct {
|
|||||||
|
|
||||||
fn findPrefix(cache: *const Cache, file_path: []const u8) !PrefixedPath {
|
fn findPrefix(cache: *const Cache, file_path: []const u8) !PrefixedPath {
|
||||||
const gpa = cache.gpa;
|
const gpa = cache.gpa;
|
||||||
const resolved_path = try fs.path.resolve(gpa, &[_][]const u8{file_path});
|
const resolved_path = try fs.path.resolve(gpa, &.{file_path});
|
||||||
errdefer gpa.free(resolved_path);
|
errdefer gpa.free(resolved_path);
|
||||||
return findPrefixResolved(cache, resolved_path);
|
return findPrefixResolved(cache, resolved_path);
|
||||||
}
|
}
|
||||||
@ -132,7 +132,7 @@ pub const Hasher = crypto.auth.siphash.SipHash128(1, 3);
|
|||||||
/// Initial state with random bytes, that can be copied.
|
/// Initial state with random bytes, that can be copied.
|
||||||
/// Refresh this with new random bytes when the manifest
|
/// Refresh this with new random bytes when the manifest
|
||||||
/// format is modified in a non-backwards-compatible way.
|
/// format is modified in a non-backwards-compatible way.
|
||||||
pub const hasher_init: Hasher = Hasher.init(&[_]u8{
|
pub const hasher_init: Hasher = Hasher.init(&.{
|
||||||
0x33, 0x52, 0xa2, 0x84,
|
0x33, 0x52, 0xa2, 0x84,
|
||||||
0xcf, 0x17, 0x56, 0x57,
|
0xcf, 0x17, 0x56, 0x57,
|
||||||
0x01, 0xbb, 0xcd, 0xe4,
|
0x01, 0xbb, 0xcd, 0xe4,
|
||||||
@ -286,11 +286,8 @@ pub const HashHelper = struct {
|
|||||||
|
|
||||||
pub fn binToHex(bin_digest: BinDigest) HexDigest {
|
pub fn binToHex(bin_digest: BinDigest) HexDigest {
|
||||||
var out_digest: HexDigest = undefined;
|
var out_digest: HexDigest = undefined;
|
||||||
_ = fmt.bufPrint(
|
var w: std.io.Writer = .fixed(&out_digest);
|
||||||
&out_digest,
|
w.printHex(&bin_digest, .lower) catch unreachable;
|
||||||
"{s}",
|
|
||||||
.{fmt.fmtSliceHexLower(&bin_digest)},
|
|
||||||
) catch unreachable;
|
|
||||||
return out_digest;
|
return out_digest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,7 +334,6 @@ pub const Manifest = struct {
|
|||||||
manifest_create: fs.File.OpenError,
|
manifest_create: fs.File.OpenError,
|
||||||
manifest_read: fs.File.ReadError,
|
manifest_read: fs.File.ReadError,
|
||||||
manifest_lock: fs.File.LockError,
|
manifest_lock: fs.File.LockError,
|
||||||
manifest_seek: fs.File.SeekError,
|
|
||||||
file_open: FileOp,
|
file_open: FileOp,
|
||||||
file_stat: FileOp,
|
file_stat: FileOp,
|
||||||
file_read: FileOp,
|
file_read: FileOp,
|
||||||
@ -611,12 +607,6 @@ pub const Manifest = struct {
|
|||||||
var file = self.files.pop().?;
|
var file = self.files.pop().?;
|
||||||
file.key.deinit(self.cache.gpa);
|
file.key.deinit(self.cache.gpa);
|
||||||
}
|
}
|
||||||
// Also, seek the file back to the start.
|
|
||||||
self.manifest_file.?.seekTo(0) catch |err| {
|
|
||||||
self.diagnostic = .{ .manifest_seek = err };
|
|
||||||
return error.CacheCheckFailed;
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (try self.hitWithCurrentLock()) {
|
switch (try self.hitWithCurrentLock()) {
|
||||||
.hit => break :hit,
|
.hit => break :hit,
|
||||||
.miss => |m| break :digests m.file_digests_populated,
|
.miss => |m| break :digests m.file_digests_populated,
|
||||||
@ -661,9 +651,8 @@ pub const Manifest = struct {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assumes that `self.hash.hasher` has been updated only with the original digest, that
|
/// Assumes that `self.hash.hasher` has been updated only with the original digest and that
|
||||||
/// `self.files` contains only the original input files, and that `self.manifest_file.?` is
|
/// `self.files` contains only the original input files.
|
||||||
/// seeked to the start of the file.
|
|
||||||
fn hitWithCurrentLock(self: *Manifest) HitError!union(enum) {
|
fn hitWithCurrentLock(self: *Manifest) HitError!union(enum) {
|
||||||
hit,
|
hit,
|
||||||
miss: struct {
|
miss: struct {
|
||||||
@ -672,12 +661,13 @@ pub const Manifest = struct {
|
|||||||
} {
|
} {
|
||||||
const gpa = self.cache.gpa;
|
const gpa = self.cache.gpa;
|
||||||
const input_file_count = self.files.entries.len;
|
const input_file_count = self.files.entries.len;
|
||||||
|
var manifest_reader = self.manifest_file.?.reader(&.{}); // Reads positionally from zero.
|
||||||
const file_contents = self.manifest_file.?.reader().readAllAlloc(gpa, manifest_file_size_max) catch |err| switch (err) {
|
const limit: std.io.Limit = .limited(manifest_file_size_max);
|
||||||
|
const file_contents = manifest_reader.interface.allocRemaining(gpa, limit) catch |err| switch (err) {
|
||||||
error.OutOfMemory => return error.OutOfMemory,
|
error.OutOfMemory => return error.OutOfMemory,
|
||||||
error.StreamTooLong => return error.OutOfMemory,
|
error.StreamTooLong => return error.OutOfMemory,
|
||||||
else => |e| {
|
error.ReadFailed => {
|
||||||
self.diagnostic = .{ .manifest_read = e };
|
self.diagnostic = .{ .manifest_read = manifest_reader.err.? };
|
||||||
return error.CacheCheckFailed;
|
return error.CacheCheckFailed;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -1063,14 +1053,17 @@ pub const Manifest = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn addDepFileMaybePost(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void {
|
fn addDepFileMaybePost(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void {
|
||||||
const dep_file_contents = try dir.readFileAlloc(self.cache.gpa, dep_file_basename, manifest_file_size_max);
|
const gpa = self.cache.gpa;
|
||||||
defer self.cache.gpa.free(dep_file_contents);
|
const dep_file_contents = try dir.readFileAlloc(gpa, dep_file_basename, manifest_file_size_max);
|
||||||
|
defer gpa.free(dep_file_contents);
|
||||||
|
|
||||||
var error_buf = std.ArrayList(u8).init(self.cache.gpa);
|
var error_buf: std.ArrayListUnmanaged(u8) = .empty;
|
||||||
defer error_buf.deinit();
|
defer error_buf.deinit(gpa);
|
||||||
|
|
||||||
|
var resolve_buf: std.ArrayListUnmanaged(u8) = .empty;
|
||||||
|
defer resolve_buf.deinit(gpa);
|
||||||
|
|
||||||
var it: DepTokenizer = .{ .bytes = dep_file_contents };
|
var it: DepTokenizer = .{ .bytes = dep_file_contents };
|
||||||
|
|
||||||
while (it.next()) |token| {
|
while (it.next()) |token| {
|
||||||
switch (token) {
|
switch (token) {
|
||||||
// We don't care about targets, we only want the prereqs
|
// We don't care about targets, we only want the prereqs
|
||||||
@ -1080,16 +1073,14 @@ pub const Manifest = struct {
|
|||||||
_ = try self.addFile(file_path, null);
|
_ = try self.addFile(file_path, null);
|
||||||
} else try self.addFilePost(file_path),
|
} else try self.addFilePost(file_path),
|
||||||
.prereq_must_resolve => {
|
.prereq_must_resolve => {
|
||||||
var resolve_buf = std.ArrayList(u8).init(self.cache.gpa);
|
resolve_buf.clearRetainingCapacity();
|
||||||
defer resolve_buf.deinit();
|
try token.resolve(gpa, &resolve_buf);
|
||||||
|
|
||||||
try token.resolve(resolve_buf.writer());
|
|
||||||
if (self.manifest_file == null) {
|
if (self.manifest_file == null) {
|
||||||
_ = try self.addFile(resolve_buf.items, null);
|
_ = try self.addFile(resolve_buf.items, null);
|
||||||
} else try self.addFilePost(resolve_buf.items);
|
} else try self.addFilePost(resolve_buf.items);
|
||||||
},
|
},
|
||||||
else => |err| {
|
else => |err| {
|
||||||
try err.printError(error_buf.writer());
|
try err.printError(gpa, &error_buf);
|
||||||
log.err("failed parsing {s}: {s}", .{ dep_file_basename, error_buf.items });
|
log.err("failed parsing {s}: {s}", .{ dep_file_basename, error_buf.items });
|
||||||
return error.InvalidDepFile;
|
return error.InvalidDepFile;
|
||||||
},
|
},
|
||||||
@ -1127,24 +1118,25 @@ pub const Manifest = struct {
|
|||||||
if (self.manifest_dirty) {
|
if (self.manifest_dirty) {
|
||||||
self.manifest_dirty = false;
|
self.manifest_dirty = false;
|
||||||
|
|
||||||
var contents = std.ArrayList(u8).init(self.cache.gpa);
|
const gpa = self.cache.gpa;
|
||||||
defer contents.deinit();
|
var contents: std.ArrayListUnmanaged(u8) = .empty;
|
||||||
|
defer contents.deinit(gpa);
|
||||||
|
|
||||||
const writer = contents.writer();
|
try contents.appendSlice(gpa, manifest_header ++ "\n");
|
||||||
try writer.writeAll(manifest_header ++ "\n");
|
|
||||||
for (self.files.keys()) |file| {
|
for (self.files.keys()) |file| {
|
||||||
try writer.print("{d} {d} {d} {} {d} {s}\n", .{
|
try contents.print(gpa, "{d} {d} {d} {x} {d} {s}\n", .{
|
||||||
file.stat.size,
|
file.stat.size,
|
||||||
file.stat.inode,
|
file.stat.inode,
|
||||||
file.stat.mtime,
|
file.stat.mtime,
|
||||||
fmt.fmtSliceHexLower(&file.bin_digest),
|
&file.bin_digest,
|
||||||
file.prefixed_path.prefix,
|
file.prefixed_path.prefix,
|
||||||
file.prefixed_path.sub_path,
|
file.prefixed_path.sub_path,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try manifest_file.setEndPos(contents.items.len);
|
try manifest_file.setEndPos(contents.items.len);
|
||||||
try manifest_file.pwriteAll(contents.items, 0);
|
var pos: usize = 0;
|
||||||
|
while (pos < contents.items.len) pos += try manifest_file.pwrite(contents.items[pos..], pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.want_shared_lock) {
|
if (self.want_shared_lock) {
|
||||||
|
|||||||
@ -7,6 +7,7 @@ state: State = .lhs,
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
pub fn next(self: *Tokenizer) ?Token {
|
pub fn next(self: *Tokenizer) ?Token {
|
||||||
var start = self.index;
|
var start = self.index;
|
||||||
@ -362,7 +363,7 @@ pub const Token = union(enum) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Resolve escapes in target or prereq. Only valid with .target_must_resolve or .prereq_must_resolve.
|
/// Resolve escapes in target or prereq. Only valid with .target_must_resolve or .prereq_must_resolve.
|
||||||
pub fn resolve(self: Token, writer: anytype) @TypeOf(writer).Error!void {
|
pub fn resolve(self: Token, gpa: Allocator, list: *std.ArrayListUnmanaged(u8)) error{OutOfMemory}!void {
|
||||||
switch (self) {
|
switch (self) {
|
||||||
.target_must_resolve => |bytes| {
|
.target_must_resolve => |bytes| {
|
||||||
var state: enum { start, escape, dollar } = .start;
|
var state: enum { start, escape, dollar } = .start;
|
||||||
@ -372,27 +373,27 @@ pub const Token = union(enum) {
|
|||||||
switch (c) {
|
switch (c) {
|
||||||
'\\' => state = .escape,
|
'\\' => state = .escape,
|
||||||
'$' => state = .dollar,
|
'$' => state = .dollar,
|
||||||
else => try writer.writeByte(c),
|
else => try list.append(gpa, c),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.escape => {
|
.escape => {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
' ', '#', '\\' => {},
|
' ', '#', '\\' => {},
|
||||||
'$' => {
|
'$' => {
|
||||||
try writer.writeByte('\\');
|
try list.append(gpa, '\\');
|
||||||
state = .dollar;
|
state = .dollar;
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
else => try writer.writeByte('\\'),
|
else => try list.append(gpa, '\\'),
|
||||||
}
|
}
|
||||||
try writer.writeByte(c);
|
try list.append(gpa, c);
|
||||||
state = .start;
|
state = .start;
|
||||||
},
|
},
|
||||||
.dollar => {
|
.dollar => {
|
||||||
try writer.writeByte('$');
|
try list.append(gpa, '$');
|
||||||
switch (c) {
|
switch (c) {
|
||||||
'$' => {},
|
'$' => {},
|
||||||
else => try writer.writeByte(c),
|
else => try list.append(gpa, c),
|
||||||
}
|
}
|
||||||
state = .start;
|
state = .start;
|
||||||
},
|
},
|
||||||
@ -406,19 +407,19 @@ pub const Token = union(enum) {
|
|||||||
.start => {
|
.start => {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
'\\' => state = .escape,
|
'\\' => state = .escape,
|
||||||
else => try writer.writeByte(c),
|
else => try list.append(gpa, c),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.escape => {
|
.escape => {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
' ' => {},
|
' ' => {},
|
||||||
'\\' => {
|
'\\' => {
|
||||||
try writer.writeByte(c);
|
try list.append(gpa, c);
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
else => try writer.writeByte('\\'),
|
else => try list.append(gpa, '\\'),
|
||||||
}
|
}
|
||||||
try writer.writeByte(c);
|
try list.append(gpa, c);
|
||||||
state = .start;
|
state = .start;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -428,20 +429,20 @@ pub const Token = union(enum) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn printError(self: Token, writer: anytype) @TypeOf(writer).Error!void {
|
pub fn printError(self: Token, gpa: Allocator, list: *std.ArrayListUnmanaged(u8)) error{OutOfMemory}!void {
|
||||||
switch (self) {
|
switch (self) {
|
||||||
.target, .target_must_resolve, .prereq, .prereq_must_resolve => unreachable, // not an error
|
.target, .target_must_resolve, .prereq, .prereq_must_resolve => unreachable, // not an error
|
||||||
.incomplete_quoted_prerequisite,
|
.incomplete_quoted_prerequisite,
|
||||||
.incomplete_target,
|
.incomplete_target,
|
||||||
=> |index_and_bytes| {
|
=> |index_and_bytes| {
|
||||||
try writer.print("{s} '", .{self.errStr()});
|
try list.print(gpa, "{s} '", .{self.errStr()});
|
||||||
if (self == .incomplete_target) {
|
if (self == .incomplete_target) {
|
||||||
const tmp = Token{ .target_must_resolve = index_and_bytes.bytes };
|
const tmp = Token{ .target_must_resolve = index_and_bytes.bytes };
|
||||||
try tmp.resolve(writer);
|
try tmp.resolve(gpa, list);
|
||||||
} else {
|
} else {
|
||||||
try printCharValues(writer, index_and_bytes.bytes);
|
try printCharValues(gpa, list, index_and_bytes.bytes);
|
||||||
}
|
}
|
||||||
try writer.print("' at position {d}", .{index_and_bytes.index});
|
try list.print(gpa, "' at position {d}", .{index_and_bytes.index});
|
||||||
},
|
},
|
||||||
.invalid_target,
|
.invalid_target,
|
||||||
.bad_target_escape,
|
.bad_target_escape,
|
||||||
@ -450,9 +451,9 @@ pub const Token = union(enum) {
|
|||||||
.incomplete_escape,
|
.incomplete_escape,
|
||||||
.expected_colon,
|
.expected_colon,
|
||||||
=> |index_and_char| {
|
=> |index_and_char| {
|
||||||
try writer.writeAll("illegal char ");
|
try list.appendSlice(gpa, "illegal char ");
|
||||||
try printUnderstandableChar(writer, index_and_char.char);
|
try printUnderstandableChar(gpa, list, index_and_char.char);
|
||||||
try writer.print(" at position {d}: {s}", .{ index_and_char.index, self.errStr() });
|
try list.print(gpa, " at position {d}: {s}", .{ index_and_char.index, self.errStr() });
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1026,41 +1027,41 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {
|
|||||||
defer arena_allocator.deinit();
|
defer arena_allocator.deinit();
|
||||||
|
|
||||||
var it: Tokenizer = .{ .bytes = input };
|
var it: Tokenizer = .{ .bytes = input };
|
||||||
var buffer = std.ArrayList(u8).init(arena);
|
var buffer: std.ArrayListUnmanaged(u8) = .empty;
|
||||||
var resolve_buf = std.ArrayList(u8).init(arena);
|
var resolve_buf: std.ArrayListUnmanaged(u8) = .empty;
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (it.next()) |token| {
|
while (it.next()) |token| {
|
||||||
if (i != 0) try buffer.appendSlice("\n");
|
if (i != 0) try buffer.appendSlice(arena, "\n");
|
||||||
switch (token) {
|
switch (token) {
|
||||||
.target, .prereq => |bytes| {
|
.target, .prereq => |bytes| {
|
||||||
try buffer.appendSlice(@tagName(token));
|
try buffer.appendSlice(arena, @tagName(token));
|
||||||
try buffer.appendSlice(" = {");
|
try buffer.appendSlice(arena, " = {");
|
||||||
for (bytes) |b| {
|
for (bytes) |b| {
|
||||||
try buffer.append(printable_char_tab[b]);
|
try buffer.append(arena, printable_char_tab[b]);
|
||||||
}
|
}
|
||||||
try buffer.appendSlice("}");
|
try buffer.appendSlice(arena, "}");
|
||||||
},
|
},
|
||||||
.target_must_resolve => {
|
.target_must_resolve => {
|
||||||
try buffer.appendSlice("target = {");
|
try buffer.appendSlice(arena, "target = {");
|
||||||
try token.resolve(resolve_buf.writer());
|
try token.resolve(arena, &resolve_buf);
|
||||||
for (resolve_buf.items) |b| {
|
for (resolve_buf.items) |b| {
|
||||||
try buffer.append(printable_char_tab[b]);
|
try buffer.append(arena, printable_char_tab[b]);
|
||||||
}
|
}
|
||||||
resolve_buf.items.len = 0;
|
resolve_buf.items.len = 0;
|
||||||
try buffer.appendSlice("}");
|
try buffer.appendSlice(arena, "}");
|
||||||
},
|
},
|
||||||
.prereq_must_resolve => {
|
.prereq_must_resolve => {
|
||||||
try buffer.appendSlice("prereq = {");
|
try buffer.appendSlice(arena, "prereq = {");
|
||||||
try token.resolve(resolve_buf.writer());
|
try token.resolve(arena, &resolve_buf);
|
||||||
for (resolve_buf.items) |b| {
|
for (resolve_buf.items) |b| {
|
||||||
try buffer.append(printable_char_tab[b]);
|
try buffer.append(arena, printable_char_tab[b]);
|
||||||
}
|
}
|
||||||
resolve_buf.items.len = 0;
|
resolve_buf.items.len = 0;
|
||||||
try buffer.appendSlice("}");
|
try buffer.appendSlice(arena, "}");
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
try buffer.appendSlice("ERROR: ");
|
try buffer.appendSlice(arena, "ERROR: ");
|
||||||
try token.printError(buffer.writer());
|
try token.printError(arena, &buffer);
|
||||||
break;
|
break;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -1072,134 +1073,18 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const out = std.fs.File.stderr().writer();
|
try testing.expectEqualStrings(expect, buffer.items);
|
||||||
|
|
||||||
try out.writeAll("\n");
|
|
||||||
try printSection(out, "<<<< input", input);
|
|
||||||
try printSection(out, "==== expect", expect);
|
|
||||||
try printSection(out, ">>>> got", buffer.items);
|
|
||||||
try printRuler(out);
|
|
||||||
|
|
||||||
try testing.expect(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printSection(out: anytype, label: []const u8, bytes: []const u8) !void {
|
fn printCharValues(gpa: Allocator, list: *std.ArrayListUnmanaged(u8), bytes: []const u8) !void {
|
||||||
try printLabel(out, label, bytes);
|
for (bytes) |b| try list.append(gpa, printable_char_tab[b]);
|
||||||
try hexDump(out, bytes);
|
|
||||||
try printRuler(out);
|
|
||||||
try out.writeAll(bytes);
|
|
||||||
try out.writeAll("\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printLabel(out: anytype, label: []const u8, bytes: []const u8) !void {
|
fn printUnderstandableChar(gpa: Allocator, list: *std.ArrayListUnmanaged(u8), char: u8) !void {
|
||||||
var buf: [80]u8 = undefined;
|
|
||||||
const text = try std.fmt.bufPrint(buf[0..], "{s} {d} bytes ", .{ label, bytes.len });
|
|
||||||
try out.writeAll(text);
|
|
||||||
var i: usize = text.len;
|
|
||||||
const end = 79;
|
|
||||||
while (i < end) : (i += 1) {
|
|
||||||
try out.writeAll(&[_]u8{label[0]});
|
|
||||||
}
|
|
||||||
try out.writeAll("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn printRuler(out: anytype) !void {
|
|
||||||
var i: usize = 0;
|
|
||||||
const end = 79;
|
|
||||||
while (i < end) : (i += 1) {
|
|
||||||
try out.writeAll("-");
|
|
||||||
}
|
|
||||||
try out.writeAll("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hexDump(out: anytype, bytes: []const u8) !void {
|
|
||||||
const n16 = bytes.len >> 4;
|
|
||||||
var line: usize = 0;
|
|
||||||
var offset: usize = 0;
|
|
||||||
while (line < n16) : (line += 1) {
|
|
||||||
try hexDump16(out, offset, bytes[offset..][0..16]);
|
|
||||||
offset += 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
const n = bytes.len & 0x0f;
|
|
||||||
if (n > 0) {
|
|
||||||
try printDecValue(out, offset, 8);
|
|
||||||
try out.writeAll(":");
|
|
||||||
try out.writeAll(" ");
|
|
||||||
const end1 = @min(offset + n, offset + 8);
|
|
||||||
for (bytes[offset..end1]) |b| {
|
|
||||||
try out.writeAll(" ");
|
|
||||||
try printHexValue(out, b, 2);
|
|
||||||
}
|
|
||||||
const end2 = offset + n;
|
|
||||||
if (end2 > end1) {
|
|
||||||
try out.writeAll(" ");
|
|
||||||
for (bytes[end1..end2]) |b| {
|
|
||||||
try out.writeAll(" ");
|
|
||||||
try printHexValue(out, b, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const short = 16 - n;
|
|
||||||
var i: usize = 0;
|
|
||||||
while (i < short) : (i += 1) {
|
|
||||||
try out.writeAll(" ");
|
|
||||||
}
|
|
||||||
if (end2 > end1) {
|
|
||||||
try out.writeAll(" |");
|
|
||||||
} else {
|
|
||||||
try out.writeAll(" |");
|
|
||||||
}
|
|
||||||
try printCharValues(out, bytes[offset..end2]);
|
|
||||||
try out.writeAll("|\n");
|
|
||||||
offset += n;
|
|
||||||
}
|
|
||||||
|
|
||||||
try printDecValue(out, offset, 8);
|
|
||||||
try out.writeAll(":");
|
|
||||||
try out.writeAll("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hexDump16(out: anytype, offset: usize, bytes: []const u8) !void {
|
|
||||||
try printDecValue(out, offset, 8);
|
|
||||||
try out.writeAll(":");
|
|
||||||
try out.writeAll(" ");
|
|
||||||
for (bytes[0..8]) |b| {
|
|
||||||
try out.writeAll(" ");
|
|
||||||
try printHexValue(out, b, 2);
|
|
||||||
}
|
|
||||||
try out.writeAll(" ");
|
|
||||||
for (bytes[8..16]) |b| {
|
|
||||||
try out.writeAll(" ");
|
|
||||||
try printHexValue(out, b, 2);
|
|
||||||
}
|
|
||||||
try out.writeAll(" |");
|
|
||||||
try printCharValues(out, bytes);
|
|
||||||
try out.writeAll("|\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn printDecValue(out: anytype, value: u64, width: u8) !void {
|
|
||||||
var buffer: [20]u8 = undefined;
|
|
||||||
const len = std.fmt.formatIntBuf(buffer[0..], value, 10, .lower, .{ .width = width, .fill = '0' });
|
|
||||||
try out.writeAll(buffer[0..len]);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn printHexValue(out: anytype, value: u64, width: u8) !void {
|
|
||||||
var buffer: [16]u8 = undefined;
|
|
||||||
const len = std.fmt.formatIntBuf(buffer[0..], value, 16, .lower, .{ .width = width, .fill = '0' });
|
|
||||||
try out.writeAll(buffer[0..len]);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn printCharValues(out: anytype, bytes: []const u8) !void {
|
|
||||||
for (bytes) |b| {
|
|
||||||
try out.writeAll(&[_]u8{printable_char_tab[b]});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn printUnderstandableChar(out: anytype, char: u8) !void {
|
|
||||||
if (std.ascii.isPrint(char)) {
|
if (std.ascii.isPrint(char)) {
|
||||||
try out.print("'{c}'", .{char});
|
try list.print(gpa, "'{c}'", .{char});
|
||||||
} else {
|
} else {
|
||||||
try out.print("\\x{X:0>2}", .{char});
|
try list.print(gpa, "\\x{X:0>2}", .{char});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
const Directory = @This();
|
const Directory = @This();
|
||||||
const std = @import("../../std.zig");
|
const std = @import("../../std.zig");
|
||||||
|
const assert = std.debug.assert;
|
||||||
const fs = std.fs;
|
const fs = std.fs;
|
||||||
const fmt = std.fmt;
|
const fmt = std.fmt;
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
@ -55,14 +56,8 @@ pub fn closeAndFree(self: *Directory, gpa: Allocator) void {
|
|||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(
|
pub fn format(self: Directory, writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
|
||||||
self: Directory,
|
comptime assert(f.len == 0);
|
||||||
comptime fmt_string: []const u8,
|
|
||||||
options: fmt.FormatOptions,
|
|
||||||
writer: anytype,
|
|
||||||
) !void {
|
|
||||||
_ = options;
|
|
||||||
if (fmt_string.len != 0) fmt.invalidFmtError(fmt_string, self);
|
|
||||||
if (self.path) |p| {
|
if (self.path) |p| {
|
||||||
try writer.writeAll(p);
|
try writer.writeAll(p);
|
||||||
try writer.writeAll(fs.path.sep_str);
|
try writer.writeAll(fs.path.sep_str);
|
||||||
|
|||||||
@ -1,3 +1,10 @@
|
|||||||
|
const Path = @This();
|
||||||
|
const std = @import("../../std.zig");
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
const fs = std.fs;
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
const Cache = std.Build.Cache;
|
||||||
|
|
||||||
root_dir: Cache.Directory,
|
root_dir: Cache.Directory,
|
||||||
/// The path, relative to the root dir, that this `Path` represents.
|
/// The path, relative to the root dir, that this `Path` represents.
|
||||||
/// Empty string means the root_dir is the path.
|
/// Empty string means the root_dir is the path.
|
||||||
@ -133,38 +140,32 @@ pub fn makePath(p: Path, sub_path: []const u8) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn toString(p: Path, allocator: Allocator) Allocator.Error![]u8 {
|
pub fn toString(p: Path, allocator: Allocator) Allocator.Error![]u8 {
|
||||||
return std.fmt.allocPrint(allocator, "{}", .{p});
|
return std.fmt.allocPrint(allocator, "{f}", .{p});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toStringZ(p: Path, allocator: Allocator) Allocator.Error![:0]u8 {
|
pub fn toStringZ(p: Path, allocator: Allocator) Allocator.Error![:0]u8 {
|
||||||
return std.fmt.allocPrintZ(allocator, "{}", .{p});
|
return std.fmt.allocPrintSentinel(allocator, "{f}", .{p}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(
|
pub fn format(self: Path, writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
|
||||||
self: Path,
|
if (f.len == 1) {
|
||||||
comptime fmt_string: []const u8,
|
|
||||||
options: std.fmt.FormatOptions,
|
|
||||||
writer: anytype,
|
|
||||||
) !void {
|
|
||||||
if (fmt_string.len == 1) {
|
|
||||||
// Quote-escape the string.
|
// Quote-escape the string.
|
||||||
const stringEscape = std.zig.stringEscape;
|
const zigEscape = switch (f[0]) {
|
||||||
const f = switch (fmt_string[0]) {
|
'q' => std.zig.stringEscape,
|
||||||
'q' => "",
|
'\'' => std.zig.charEscape,
|
||||||
'\'' => "\'",
|
else => @compileError("unsupported format string: " ++ f),
|
||||||
else => @compileError("unsupported format string: " ++ fmt_string),
|
|
||||||
};
|
};
|
||||||
if (self.root_dir.path) |p| {
|
if (self.root_dir.path) |p| {
|
||||||
try stringEscape(p, f, options, writer);
|
try zigEscape(p, writer);
|
||||||
if (self.sub_path.len > 0) try stringEscape(fs.path.sep_str, f, options, writer);
|
if (self.sub_path.len > 0) try zigEscape(fs.path.sep_str, writer);
|
||||||
}
|
}
|
||||||
if (self.sub_path.len > 0) {
|
if (self.sub_path.len > 0) {
|
||||||
try stringEscape(self.sub_path, f, options, writer);
|
try zigEscape(self.sub_path, writer);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (fmt_string.len > 0)
|
if (f.len > 0)
|
||||||
std.fmt.invalidFmtError(fmt_string, self);
|
std.fmt.invalidFmtError(f, self);
|
||||||
if (std.fs.path.isAbsolute(self.sub_path)) {
|
if (std.fs.path.isAbsolute(self.sub_path)) {
|
||||||
try writer.writeAll(self.sub_path);
|
try writer.writeAll(self.sub_path);
|
||||||
return;
|
return;
|
||||||
@ -223,9 +224,3 @@ pub const TableAdapter = struct {
|
|||||||
return a.eql(b);
|
return a.eql(b);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const Path = @This();
|
|
||||||
const std = @import("../../std.zig");
|
|
||||||
const fs = std.fs;
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
const Cache = std.Build.Cache;
|
|
||||||
|
|||||||
@ -170,7 +170,7 @@ fn serveFile(
|
|||||||
// We load the file with every request so that the user can make changes to the file
|
// We load the file with every request so that the user can make changes to the file
|
||||||
// and refresh the HTML page without restarting this server.
|
// and refresh the HTML page without restarting this server.
|
||||||
const file_contents = ws.zig_lib_directory.handle.readFileAlloc(gpa, name, 10 * 1024 * 1024) catch |err| {
|
const file_contents = ws.zig_lib_directory.handle.readFileAlloc(gpa, name, 10 * 1024 * 1024) catch |err| {
|
||||||
log.err("failed to read '{}{s}': {s}", .{ ws.zig_lib_directory, name, @errorName(err) });
|
log.err("failed to read '{f}{s}': {s}", .{ ws.zig_lib_directory, name, @errorName(err) });
|
||||||
return error.AlreadyReported;
|
return error.AlreadyReported;
|
||||||
};
|
};
|
||||||
defer gpa.free(file_contents);
|
defer gpa.free(file_contents);
|
||||||
@ -251,10 +251,10 @@ fn buildWasmBinary(
|
|||||||
"-fsingle-threaded", //
|
"-fsingle-threaded", //
|
||||||
"--dep", "Walk", //
|
"--dep", "Walk", //
|
||||||
"--dep", "html_render", //
|
"--dep", "html_render", //
|
||||||
try std.fmt.allocPrint(arena, "-Mroot={}", .{main_src_path}), //
|
try std.fmt.allocPrint(arena, "-Mroot={f}", .{main_src_path}), //
|
||||||
try std.fmt.allocPrint(arena, "-MWalk={}", .{walk_src_path}), //
|
try std.fmt.allocPrint(arena, "-MWalk={f}", .{walk_src_path}), //
|
||||||
"--dep", "Walk", //
|
"--dep", "Walk", //
|
||||||
try std.fmt.allocPrint(arena, "-Mhtml_render={}", .{html_render_src_path}), //
|
try std.fmt.allocPrint(arena, "-Mhtml_render={f}", .{html_render_src_path}), //
|
||||||
"--listen=-",
|
"--listen=-",
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -526,7 +526,7 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {
|
|||||||
|
|
||||||
for (deduped_paths) |joined_path| {
|
for (deduped_paths) |joined_path| {
|
||||||
var file = joined_path.root_dir.handle.openFile(joined_path.sub_path, .{}) catch |err| {
|
var file = joined_path.root_dir.handle.openFile(joined_path.sub_path, .{}) catch |err| {
|
||||||
log.err("failed to open {}: {s}", .{ joined_path, @errorName(err) });
|
log.err("failed to open {f}: {s}", .{ joined_path, @errorName(err) });
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
defer file.close();
|
defer file.close();
|
||||||
@ -604,7 +604,7 @@ fn prepareTables(
|
|||||||
|
|
||||||
const rebuilt_exe_path = run_step.rebuilt_executable.?;
|
const rebuilt_exe_path = run_step.rebuilt_executable.?;
|
||||||
var debug_info = std.debug.Info.load(gpa, rebuilt_exe_path, &gop.value_ptr.coverage) catch |err| {
|
var debug_info = std.debug.Info.load(gpa, rebuilt_exe_path, &gop.value_ptr.coverage) catch |err| {
|
||||||
log.err("step '{s}': failed to load debug information for '{}': {s}", .{
|
log.err("step '{s}': failed to load debug information for '{f}': {s}", .{
|
||||||
run_step.step.name, rebuilt_exe_path, @errorName(err),
|
run_step.step.name, rebuilt_exe_path, @errorName(err),
|
||||||
});
|
});
|
||||||
return error.AlreadyReported;
|
return error.AlreadyReported;
|
||||||
@ -616,7 +616,7 @@ fn prepareTables(
|
|||||||
.sub_path = "v/" ++ std.fmt.hex(coverage_id),
|
.sub_path = "v/" ++ std.fmt.hex(coverage_id),
|
||||||
};
|
};
|
||||||
var coverage_file = coverage_file_path.root_dir.handle.openFile(coverage_file_path.sub_path, .{}) catch |err| {
|
var coverage_file = coverage_file_path.root_dir.handle.openFile(coverage_file_path.sub_path, .{}) catch |err| {
|
||||||
log.err("step '{s}': failed to load coverage file '{}': {s}", .{
|
log.err("step '{s}': failed to load coverage file '{f}': {s}", .{
|
||||||
run_step.step.name, coverage_file_path, @errorName(err),
|
run_step.step.name, coverage_file_path, @errorName(err),
|
||||||
});
|
});
|
||||||
return error.AlreadyReported;
|
return error.AlreadyReported;
|
||||||
@ -624,7 +624,7 @@ fn prepareTables(
|
|||||||
defer coverage_file.close();
|
defer coverage_file.close();
|
||||||
|
|
||||||
const file_size = coverage_file.getEndPos() catch |err| {
|
const file_size = coverage_file.getEndPos() catch |err| {
|
||||||
log.err("unable to check len of coverage file '{}': {s}", .{ coverage_file_path, @errorName(err) });
|
log.err("unable to check len of coverage file '{f}': {s}", .{ coverage_file_path, @errorName(err) });
|
||||||
return error.AlreadyReported;
|
return error.AlreadyReported;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -636,7 +636,7 @@ fn prepareTables(
|
|||||||
coverage_file.handle,
|
coverage_file.handle,
|
||||||
0,
|
0,
|
||||||
) catch |err| {
|
) catch |err| {
|
||||||
log.err("failed to map coverage file '{}': {s}", .{ coverage_file_path, @errorName(err) });
|
log.err("failed to map coverage file '{f}': {s}", .{ coverage_file_path, @errorName(err) });
|
||||||
return error.AlreadyReported;
|
return error.AlreadyReported;
|
||||||
};
|
};
|
||||||
gop.value_ptr.mapped_memory = mapped_memory;
|
gop.value_ptr.mapped_memory = mapped_memory;
|
||||||
|
|||||||
@ -186,7 +186,7 @@ pub const IncludeDir = union(enum) {
|
|||||||
.embed_path => |lazy_path| {
|
.embed_path => |lazy_path| {
|
||||||
// Special case: this is a single arg.
|
// Special case: this is a single arg.
|
||||||
const resolved = lazy_path.getPath3(b, asking_step);
|
const resolved = lazy_path.getPath3(b, asking_step);
|
||||||
const arg = b.fmt("--embed-dir={}", .{resolved});
|
const arg = b.fmt("--embed-dir={f}", .{resolved});
|
||||||
return zig_args.append(arg);
|
return zig_args.append(arg);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -287,7 +287,8 @@ pub fn cast(step: *Step, comptime T: type) ?*T {
|
|||||||
|
|
||||||
/// For debugging purposes, prints identifying information about this Step.
|
/// For debugging purposes, prints identifying information about this Step.
|
||||||
pub fn dump(step: *Step, file: std.fs.File) void {
|
pub fn dump(step: *Step, file: std.fs.File) void {
|
||||||
const w = file.writer();
|
var fw = file.writer(&.{});
|
||||||
|
const w = &fw.interface;
|
||||||
const tty_config = std.io.tty.detectConfig(file);
|
const tty_config = std.io.tty.detectConfig(file);
|
||||||
const debug_info = std.debug.getSelfDebugInfo() catch |err| {
|
const debug_info = std.debug.getSelfDebugInfo() catch |err| {
|
||||||
w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{
|
w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{
|
||||||
@ -482,9 +483,9 @@ pub fn evalZigProcess(
|
|||||||
pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u8) !std.fs.Dir.PrevStatus {
|
pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u8) !std.fs.Dir.PrevStatus {
|
||||||
const b = s.owner;
|
const b = s.owner;
|
||||||
const src_path = src_lazy_path.getPath3(b, s);
|
const src_path = src_lazy_path.getPath3(b, s);
|
||||||
try handleVerbose(b, null, &.{ "install", "-C", b.fmt("{}", .{src_path}), dest_path });
|
try handleVerbose(b, null, &.{ "install", "-C", b.fmt("{f}", .{src_path}), dest_path });
|
||||||
return src_path.root_dir.handle.updateFile(src_path.sub_path, std.fs.cwd(), dest_path, .{}) catch |err| {
|
return src_path.root_dir.handle.updateFile(src_path.sub_path, std.fs.cwd(), dest_path, .{}) catch |err| {
|
||||||
return s.fail("unable to update file from '{}' to '{s}': {s}", .{
|
return s.fail("unable to update file from '{f}' to '{s}': {s}", .{
|
||||||
src_path, dest_path, @errorName(err),
|
src_path, dest_path, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -821,7 +822,7 @@ fn failWithCacheError(s: *Step, man: *const Build.Cache.Manifest, err: Build.Cac
|
|||||||
switch (err) {
|
switch (err) {
|
||||||
error.CacheCheckFailed => switch (man.diagnostic) {
|
error.CacheCheckFailed => switch (man.diagnostic) {
|
||||||
.none => unreachable,
|
.none => unreachable,
|
||||||
.manifest_create, .manifest_read, .manifest_lock, .manifest_seek => |e| return s.fail("failed to check cache: {s} {s}", .{
|
.manifest_create, .manifest_read, .manifest_lock => |e| return s.fail("failed to check cache: {s} {s}", .{
|
||||||
@tagName(man.diagnostic), @errorName(e),
|
@tagName(man.diagnostic), @errorName(e),
|
||||||
}),
|
}),
|
||||||
.file_open, .file_stat, .file_read, .file_hash => |op| {
|
.file_open, .file_stat, .file_read, .file_hash => |op| {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1542,7 +1542,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
|
|||||||
if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) {
|
if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) {
|
||||||
if (compile.version) |version| {
|
if (compile.version) |version| {
|
||||||
try zig_args.append("--version");
|
try zig_args.append("--version");
|
||||||
try zig_args.append(b.fmt("{}", .{version}));
|
try zig_args.append(b.fmt("{f}", .{version}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compile.rootModuleTarget().os.tag.isDarwin()) {
|
if (compile.rootModuleTarget().os.tag.isDarwin()) {
|
||||||
@ -1696,9 +1696,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
|
|||||||
|
|
||||||
if (compile.build_id orelse b.build_id) |build_id| {
|
if (compile.build_id orelse b.build_id) |build_id| {
|
||||||
try zig_args.append(switch (build_id) {
|
try zig_args.append(switch (build_id) {
|
||||||
.hexstring => |hs| b.fmt("--build-id=0x{s}", .{
|
.hexstring => |hs| b.fmt("--build-id=0x{x}", .{hs.toSlice()}),
|
||||||
std.fmt.fmtSliceHexLower(hs.toSlice()),
|
|
||||||
}),
|
|
||||||
.none, .fast, .uuid, .sha1, .md5 => b.fmt("--build-id={s}", .{@tagName(build_id)}),
|
.none, .fast, .uuid, .sha1, .md5 => b.fmt("--build-id={s}", .{@tagName(build_id)}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1706,7 +1704,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
|
|||||||
const opt_zig_lib_dir = if (compile.zig_lib_dir) |dir|
|
const opt_zig_lib_dir = if (compile.zig_lib_dir) |dir|
|
||||||
dir.getPath2(b, step)
|
dir.getPath2(b, step)
|
||||||
else if (b.graph.zig_lib_directory.path) |_|
|
else if (b.graph.zig_lib_directory.path) |_|
|
||||||
b.fmt("{}", .{b.graph.zig_lib_directory})
|
b.fmt("{f}", .{b.graph.zig_lib_directory})
|
||||||
else
|
else
|
||||||
null;
|
null;
|
||||||
|
|
||||||
@ -1746,8 +1744,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (compile.error_limit) |err_limit| try zig_args.appendSlice(&.{
|
if (compile.error_limit) |err_limit| try zig_args.appendSlice(&.{
|
||||||
"--error-limit",
|
"--error-limit", b.fmt("{d}", .{err_limit}),
|
||||||
b.fmt("{}", .{err_limit}),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
try addFlag(&zig_args, "incremental", b.graph.incremental);
|
try addFlag(&zig_args, "incremental", b.graph.incremental);
|
||||||
@ -1793,11 +1790,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
|
|||||||
var args_hash: [Sha256.digest_length]u8 = undefined;
|
var args_hash: [Sha256.digest_length]u8 = undefined;
|
||||||
Sha256.hash(args, &args_hash, .{});
|
Sha256.hash(args, &args_hash, .{});
|
||||||
var args_hex_hash: [Sha256.digest_length * 2]u8 = undefined;
|
var args_hex_hash: [Sha256.digest_length * 2]u8 = undefined;
|
||||||
_ = try std.fmt.bufPrint(
|
_ = try std.fmt.bufPrint(&args_hex_hash, "{x}", .{&args_hash});
|
||||||
&args_hex_hash,
|
|
||||||
"{s}",
|
|
||||||
.{std.fmt.fmtSliceHexLower(&args_hash)},
|
|
||||||
);
|
|
||||||
|
|
||||||
const args_file = "args" ++ fs.path.sep_str ++ args_hex_hash;
|
const args_file = "args" ++ fs.path.sep_str ++ args_hex_hash;
|
||||||
try b.cache_root.handle.writeFile(.{ .sub_path = args_file, .data = args });
|
try b.cache_root.handle.writeFile(.{ .sub_path = args_file, .data = args });
|
||||||
@ -1836,7 +1829,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
// Update generated files
|
// Update generated files
|
||||||
if (maybe_output_dir) |output_dir| {
|
if (maybe_output_dir) |output_dir| {
|
||||||
if (compile.emit_directory) |lp| {
|
if (compile.emit_directory) |lp| {
|
||||||
lp.path = b.fmt("{}", .{output_dir});
|
lp.path = b.fmt("{f}", .{output_dir});
|
||||||
}
|
}
|
||||||
|
|
||||||
// zig fmt: off
|
// zig fmt: off
|
||||||
|
|||||||
@ -2,6 +2,7 @@ const std = @import("std");
|
|||||||
const ConfigHeader = @This();
|
const ConfigHeader = @This();
|
||||||
const Step = std.Build.Step;
|
const Step = std.Build.Step;
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
const Writer = std.io.Writer;
|
||||||
|
|
||||||
pub const Style = union(enum) {
|
pub const Style = union(enum) {
|
||||||
/// A configure format supported by autotools that uses `#undef foo` to
|
/// A configure format supported by autotools that uses `#undef foo` to
|
||||||
@ -87,7 +88,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
|
|||||||
owner.fmt("configure {s} header to {s}", .{ @tagName(options.style), include_path });
|
owner.fmt("configure {s} header to {s}", .{ @tagName(options.style), include_path });
|
||||||
|
|
||||||
config_header.* = .{
|
config_header.* = .{
|
||||||
.step = Step.init(.{
|
.step = .init(.{
|
||||||
.id = base_id,
|
.id = base_id,
|
||||||
.name = name,
|
.name = name,
|
||||||
.owner = owner,
|
.owner = owner,
|
||||||
@ -95,7 +96,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
|
|||||||
.first_ret_addr = options.first_ret_addr orelse @returnAddress(),
|
.first_ret_addr = options.first_ret_addr orelse @returnAddress(),
|
||||||
}),
|
}),
|
||||||
.style = options.style,
|
.style = options.style,
|
||||||
.values = std.StringArrayHashMap(Value).init(owner.allocator),
|
.values = .init(owner.allocator),
|
||||||
|
|
||||||
.max_bytes = options.max_bytes,
|
.max_bytes = options.max_bytes,
|
||||||
.include_path = include_path,
|
.include_path = include_path,
|
||||||
@ -195,8 +196,9 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
man.hash.addBytes(config_header.include_path);
|
man.hash.addBytes(config_header.include_path);
|
||||||
man.hash.addOptionalBytes(config_header.include_guard_override);
|
man.hash.addOptionalBytes(config_header.include_guard_override);
|
||||||
|
|
||||||
var output = std.ArrayList(u8).init(gpa);
|
var aw: std.io.Writer.Allocating = .init(gpa);
|
||||||
defer output.deinit();
|
defer aw.deinit();
|
||||||
|
const bw = &aw.interface;
|
||||||
|
|
||||||
const header_text = "This file was generated by ConfigHeader using the Zig Build System.";
|
const header_text = "This file was generated by ConfigHeader using the Zig Build System.";
|
||||||
const c_generated_line = "/* " ++ header_text ++ " */\n";
|
const c_generated_line = "/* " ++ header_text ++ " */\n";
|
||||||
@ -204,7 +206,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
|
|
||||||
switch (config_header.style) {
|
switch (config_header.style) {
|
||||||
.autoconf_undef, .autoconf, .autoconf_at => |file_source| {
|
.autoconf_undef, .autoconf, .autoconf_at => |file_source| {
|
||||||
try output.appendSlice(c_generated_line);
|
try bw.writeAll(c_generated_line);
|
||||||
const src_path = file_source.getPath2(b, step);
|
const src_path = file_source.getPath2(b, step);
|
||||||
const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| {
|
const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| {
|
||||||
return step.fail("unable to read autoconf input file '{s}': {s}", .{
|
return step.fail("unable to read autoconf input file '{s}': {s}", .{
|
||||||
@ -212,32 +214,33 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
switch (config_header.style) {
|
switch (config_header.style) {
|
||||||
.autoconf_undef, .autoconf => try render_autoconf_undef(step, contents, &output, config_header.values, src_path),
|
.autoconf_undef, .autoconf => try render_autoconf_undef(step, contents, bw, config_header.values, src_path),
|
||||||
.autoconf_at => try render_autoconf_at(step, contents, &output, config_header.values, src_path),
|
.autoconf_at => try render_autoconf_at(step, contents, &aw, config_header.values, src_path),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.cmake => |file_source| {
|
.cmake => |file_source| {
|
||||||
try output.appendSlice(c_generated_line);
|
try bw.writeAll(c_generated_line);
|
||||||
const src_path = file_source.getPath2(b, step);
|
const src_path = file_source.getPath2(b, step);
|
||||||
const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| {
|
const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| {
|
||||||
return step.fail("unable to read cmake input file '{s}': {s}", .{
|
return step.fail("unable to read cmake input file '{s}': {s}", .{
|
||||||
src_path, @errorName(err),
|
src_path, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
try render_cmake(step, contents, &output, config_header.values, src_path);
|
try render_cmake(step, contents, bw, config_header.values, src_path);
|
||||||
},
|
},
|
||||||
.blank => {
|
.blank => {
|
||||||
try output.appendSlice(c_generated_line);
|
try bw.writeAll(c_generated_line);
|
||||||
try render_blank(&output, config_header.values, config_header.include_path, config_header.include_guard_override);
|
try render_blank(gpa, bw, config_header.values, config_header.include_path, config_header.include_guard_override);
|
||||||
},
|
},
|
||||||
.nasm => {
|
.nasm => {
|
||||||
try output.appendSlice(asm_generated_line);
|
try bw.writeAll(asm_generated_line);
|
||||||
try render_nasm(&output, config_header.values);
|
try render_nasm(bw, config_header.values);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
man.hash.addBytes(output.items);
|
const output = aw.getWritten();
|
||||||
|
man.hash.addBytes(output);
|
||||||
|
|
||||||
if (try step.cacheHit(&man)) {
|
if (try step.cacheHit(&man)) {
|
||||||
const digest = man.final();
|
const digest = man.final();
|
||||||
@ -256,13 +259,13 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
const sub_path_dirname = std.fs.path.dirname(sub_path).?;
|
const sub_path_dirname = std.fs.path.dirname(sub_path).?;
|
||||||
|
|
||||||
b.cache_root.handle.makePath(sub_path_dirname) catch |err| {
|
b.cache_root.handle.makePath(sub_path_dirname) catch |err| {
|
||||||
return step.fail("unable to make path '{}{s}': {s}", .{
|
return step.fail("unable to make path '{f}{s}': {s}", .{
|
||||||
b.cache_root, sub_path_dirname, @errorName(err),
|
b.cache_root, sub_path_dirname, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = output.items }) catch |err| {
|
b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = output }) catch |err| {
|
||||||
return step.fail("unable to write file '{}{s}': {s}", .{
|
return step.fail("unable to write file '{f}{s}': {s}", .{
|
||||||
b.cache_root, sub_path, @errorName(err),
|
b.cache_root, sub_path, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -274,7 +277,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
fn render_autoconf_undef(
|
fn render_autoconf_undef(
|
||||||
step: *Step,
|
step: *Step,
|
||||||
contents: []const u8,
|
contents: []const u8,
|
||||||
output: *std.ArrayList(u8),
|
bw: *Writer,
|
||||||
values: std.StringArrayHashMap(Value),
|
values: std.StringArrayHashMap(Value),
|
||||||
src_path: []const u8,
|
src_path: []const u8,
|
||||||
) !void {
|
) !void {
|
||||||
@ -289,15 +292,15 @@ fn render_autoconf_undef(
|
|||||||
var line_it = std.mem.splitScalar(u8, contents, '\n');
|
var line_it = std.mem.splitScalar(u8, contents, '\n');
|
||||||
while (line_it.next()) |line| : (line_index += 1) {
|
while (line_it.next()) |line| : (line_index += 1) {
|
||||||
if (!std.mem.startsWith(u8, line, "#")) {
|
if (!std.mem.startsWith(u8, line, "#")) {
|
||||||
try output.appendSlice(line);
|
try bw.writeAll(line);
|
||||||
try output.appendSlice("\n");
|
try bw.writeByte('\n');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");
|
var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");
|
||||||
const undef = it.next().?;
|
const undef = it.next().?;
|
||||||
if (!std.mem.eql(u8, undef, "undef")) {
|
if (!std.mem.eql(u8, undef, "undef")) {
|
||||||
try output.appendSlice(line);
|
try bw.writeAll(line);
|
||||||
try output.appendSlice("\n");
|
try bw.writeByte('\n');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const name = it.next().?;
|
const name = it.next().?;
|
||||||
@ -309,7 +312,7 @@ fn render_autoconf_undef(
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
is_used.set(index);
|
is_used.set(index);
|
||||||
try renderValueC(output, name, values.values()[index]);
|
try renderValueC(bw, name, values.values()[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var unused_value_it = is_used.iterator(.{ .kind = .unset });
|
var unused_value_it = is_used.iterator(.{ .kind = .unset });
|
||||||
@ -326,12 +329,13 @@ fn render_autoconf_undef(
|
|||||||
fn render_autoconf_at(
|
fn render_autoconf_at(
|
||||||
step: *Step,
|
step: *Step,
|
||||||
contents: []const u8,
|
contents: []const u8,
|
||||||
output: *std.ArrayList(u8),
|
aw: *std.io.Writer.Allocating,
|
||||||
values: std.StringArrayHashMap(Value),
|
values: std.StringArrayHashMap(Value),
|
||||||
src_path: []const u8,
|
src_path: []const u8,
|
||||||
) !void {
|
) !void {
|
||||||
const build = step.owner;
|
const build = step.owner;
|
||||||
const allocator = build.allocator;
|
const allocator = build.allocator;
|
||||||
|
const bw = &aw.interface;
|
||||||
|
|
||||||
const used = allocator.alloc(bool, values.count()) catch @panic("OOM");
|
const used = allocator.alloc(bool, values.count()) catch @panic("OOM");
|
||||||
for (used) |*u| u.* = false;
|
for (used) |*u| u.* = false;
|
||||||
@ -343,11 +347,11 @@ fn render_autoconf_at(
|
|||||||
while (line_it.next()) |line| : (line_index += 1) {
|
while (line_it.next()) |line| : (line_index += 1) {
|
||||||
const last_line = line_it.index == line_it.buffer.len;
|
const last_line = line_it.index == line_it.buffer.len;
|
||||||
|
|
||||||
const old_len = output.items.len;
|
const old_len = aw.getWritten().len;
|
||||||
expand_variables_autoconf_at(output, line, values, used) catch |err| switch (err) {
|
expand_variables_autoconf_at(bw, line, values, used) catch |err| switch (err) {
|
||||||
error.MissingValue => {
|
error.MissingValue => {
|
||||||
const name = output.items[old_len..];
|
const name = aw.getWritten()[old_len..];
|
||||||
defer output.shrinkRetainingCapacity(old_len);
|
defer aw.shrinkRetainingCapacity(old_len);
|
||||||
try step.addError("{s}:{d}: error: unspecified config header value: '{s}'", .{
|
try step.addError("{s}:{d}: error: unspecified config header value: '{s}'", .{
|
||||||
src_path, line_index + 1, name,
|
src_path, line_index + 1, name,
|
||||||
});
|
});
|
||||||
@ -362,9 +366,7 @@ fn render_autoconf_at(
|
|||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if (!last_line) {
|
if (!last_line) try bw.writeByte('\n');
|
||||||
try output.append('\n');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (values.unmanaged.entries.slice().items(.key), used) |name, u| {
|
for (values.unmanaged.entries.slice().items(.key), used) |name, u| {
|
||||||
@ -374,15 +376,13 @@ fn render_autoconf_at(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (any_errors) {
|
if (any_errors) return error.MakeFailed;
|
||||||
return error.MakeFailed;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_cmake(
|
fn render_cmake(
|
||||||
step: *Step,
|
step: *Step,
|
||||||
contents: []const u8,
|
contents: []const u8,
|
||||||
output: *std.ArrayList(u8),
|
bw: *Writer,
|
||||||
values: std.StringArrayHashMap(Value),
|
values: std.StringArrayHashMap(Value),
|
||||||
src_path: []const u8,
|
src_path: []const u8,
|
||||||
) !void {
|
) !void {
|
||||||
@ -417,10 +417,8 @@ fn render_cmake(
|
|||||||
defer allocator.free(line);
|
defer allocator.free(line);
|
||||||
|
|
||||||
if (!std.mem.startsWith(u8, line, "#")) {
|
if (!std.mem.startsWith(u8, line, "#")) {
|
||||||
try output.appendSlice(line);
|
try bw.writeAll(line);
|
||||||
if (!last_line) {
|
if (!last_line) try bw.writeByte('\n');
|
||||||
try output.appendSlice("\n");
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");
|
var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");
|
||||||
@ -428,10 +426,8 @@ fn render_cmake(
|
|||||||
if (!std.mem.eql(u8, cmakedefine, "cmakedefine") and
|
if (!std.mem.eql(u8, cmakedefine, "cmakedefine") and
|
||||||
!std.mem.eql(u8, cmakedefine, "cmakedefine01"))
|
!std.mem.eql(u8, cmakedefine, "cmakedefine01"))
|
||||||
{
|
{
|
||||||
try output.appendSlice(line);
|
try bw.writeAll(line);
|
||||||
if (!last_line) {
|
if (!last_line) try bw.writeByte('\n');
|
||||||
try output.appendSlice("\n");
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,7 +498,7 @@ fn render_cmake(
|
|||||||
value = Value{ .ident = it.rest() };
|
value = Value{ .ident = it.rest() };
|
||||||
}
|
}
|
||||||
|
|
||||||
try renderValueC(output, name, value);
|
try renderValueC(bw, name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (any_errors) {
|
if (any_errors) {
|
||||||
@ -511,13 +507,14 @@ fn render_cmake(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render_blank(
|
fn render_blank(
|
||||||
output: *std.ArrayList(u8),
|
gpa: std.mem.Allocator,
|
||||||
|
bw: *Writer,
|
||||||
defines: std.StringArrayHashMap(Value),
|
defines: std.StringArrayHashMap(Value),
|
||||||
include_path: []const u8,
|
include_path: []const u8,
|
||||||
include_guard_override: ?[]const u8,
|
include_guard_override: ?[]const u8,
|
||||||
) !void {
|
) !void {
|
||||||
const include_guard_name = include_guard_override orelse blk: {
|
const include_guard_name = include_guard_override orelse blk: {
|
||||||
const name = try output.allocator.dupe(u8, include_path);
|
const name = try gpa.dupe(u8, include_path);
|
||||||
for (name) |*byte| {
|
for (name) |*byte| {
|
||||||
switch (byte.*) {
|
switch (byte.*) {
|
||||||
'a'...'z' => byte.* = byte.* - 'a' + 'A',
|
'a'...'z' => byte.* = byte.* - 'a' + 'A',
|
||||||
@ -527,92 +524,53 @@ fn render_blank(
|
|||||||
}
|
}
|
||||||
break :blk name;
|
break :blk name;
|
||||||
};
|
};
|
||||||
|
defer if (include_guard_override == null) gpa.free(include_guard_name);
|
||||||
|
|
||||||
try output.appendSlice("#ifndef ");
|
try bw.print(
|
||||||
try output.appendSlice(include_guard_name);
|
\\#ifndef {[0]s}
|
||||||
try output.appendSlice("\n#define ");
|
\\#define {[0]s}
|
||||||
try output.appendSlice(include_guard_name);
|
\\
|
||||||
try output.appendSlice("\n");
|
, .{include_guard_name});
|
||||||
|
|
||||||
const values = defines.values();
|
const values = defines.values();
|
||||||
for (defines.keys(), 0..) |name, i| {
|
for (defines.keys(), 0..) |name, i| try renderValueC(bw, name, values[i]);
|
||||||
try renderValueC(output, name, values[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
try output.appendSlice("#endif /* ");
|
try bw.print(
|
||||||
try output.appendSlice(include_guard_name);
|
\\#endif /* {s} */
|
||||||
try output.appendSlice(" */\n");
|
\\
|
||||||
|
, .{include_guard_name});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_nasm(output: *std.ArrayList(u8), defines: std.StringArrayHashMap(Value)) !void {
|
fn render_nasm(bw: *Writer, defines: std.StringArrayHashMap(Value)) !void {
|
||||||
const values = defines.values();
|
for (defines.keys(), defines.values()) |name, value| try renderValueNasm(bw, name, value);
|
||||||
for (defines.keys(), 0..) |name, i| {
|
|
||||||
try renderValueNasm(output, name, values[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderValueC(output: *std.ArrayList(u8), name: []const u8, value: Value) !void {
|
fn renderValueC(bw: *Writer, name: []const u8, value: Value) !void {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
.undef => {
|
.undef => try bw.print("/* #undef {s} */\n", .{name}),
|
||||||
try output.appendSlice("/* #undef ");
|
.defined => try bw.print("#define {s}\n", .{name}),
|
||||||
try output.appendSlice(name);
|
.boolean => |b| try bw.print("#define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }),
|
||||||
try output.appendSlice(" */\n");
|
.int => |i| try bw.print("#define {s} {d}\n", .{ name, i }),
|
||||||
},
|
.ident => |ident| try bw.print("#define {s} {s}\n", .{ name, ident }),
|
||||||
.defined => {
|
// TODO: use C-specific escaping instead of zig string literals
|
||||||
try output.appendSlice("#define ");
|
.string => |string| try bw.print("#define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }),
|
||||||
try output.appendSlice(name);
|
|
||||||
try output.appendSlice("\n");
|
|
||||||
},
|
|
||||||
.boolean => |b| {
|
|
||||||
try output.appendSlice("#define ");
|
|
||||||
try output.appendSlice(name);
|
|
||||||
try output.appendSlice(if (b) " 1\n" else " 0\n");
|
|
||||||
},
|
|
||||||
.int => |i| {
|
|
||||||
try output.writer().print("#define {s} {d}\n", .{ name, i });
|
|
||||||
},
|
|
||||||
.ident => |ident| {
|
|
||||||
try output.writer().print("#define {s} {s}\n", .{ name, ident });
|
|
||||||
},
|
|
||||||
.string => |string| {
|
|
||||||
// TODO: use C-specific escaping instead of zig string literals
|
|
||||||
try output.writer().print("#define {s} \"{}\"\n", .{ name, std.zig.fmtEscapes(string) });
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderValueNasm(output: *std.ArrayList(u8), name: []const u8, value: Value) !void {
|
fn renderValueNasm(bw: *Writer, name: []const u8, value: Value) !void {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
.undef => {
|
.undef => try bw.print("; %undef {s}\n", .{name}),
|
||||||
try output.appendSlice("; %undef ");
|
.defined => try bw.print("%define {s}\n", .{name}),
|
||||||
try output.appendSlice(name);
|
.boolean => |b| try bw.print("%define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }),
|
||||||
try output.appendSlice("\n");
|
.int => |i| try bw.print("%define {s} {d}\n", .{ name, i }),
|
||||||
},
|
.ident => |ident| try bw.print("%define {s} {s}\n", .{ name, ident }),
|
||||||
.defined => {
|
// TODO: use nasm-specific escaping instead of zig string literals
|
||||||
try output.appendSlice("%define ");
|
.string => |string| try bw.print("%define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }),
|
||||||
try output.appendSlice(name);
|
|
||||||
try output.appendSlice("\n");
|
|
||||||
},
|
|
||||||
.boolean => |b| {
|
|
||||||
try output.appendSlice("%define ");
|
|
||||||
try output.appendSlice(name);
|
|
||||||
try output.appendSlice(if (b) " 1\n" else " 0\n");
|
|
||||||
},
|
|
||||||
.int => |i| {
|
|
||||||
try output.writer().print("%define {s} {d}\n", .{ name, i });
|
|
||||||
},
|
|
||||||
.ident => |ident| {
|
|
||||||
try output.writer().print("%define {s} {s}\n", .{ name, ident });
|
|
||||||
},
|
|
||||||
.string => |string| {
|
|
||||||
// TODO: use nasm-specific escaping instead of zig string literals
|
|
||||||
try output.writer().print("%define {s} \"{}\"\n", .{ name, std.zig.fmtEscapes(string) });
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_variables_autoconf_at(
|
fn expand_variables_autoconf_at(
|
||||||
output: *std.ArrayList(u8),
|
bw: *Writer,
|
||||||
contents: []const u8,
|
contents: []const u8,
|
||||||
values: std.StringArrayHashMap(Value),
|
values: std.StringArrayHashMap(Value),
|
||||||
used: []bool,
|
used: []bool,
|
||||||
@ -637,23 +595,17 @@ fn expand_variables_autoconf_at(
|
|||||||
const key = contents[curr + 1 .. close_pos];
|
const key = contents[curr + 1 .. close_pos];
|
||||||
const index = values.getIndex(key) orelse {
|
const index = values.getIndex(key) orelse {
|
||||||
// Report the missing key to the caller.
|
// Report the missing key to the caller.
|
||||||
try output.appendSlice(key);
|
try bw.writeAll(key);
|
||||||
return error.MissingValue;
|
return error.MissingValue;
|
||||||
};
|
};
|
||||||
const value = values.unmanaged.entries.slice().items(.value)[index];
|
const value = values.unmanaged.entries.slice().items(.value)[index];
|
||||||
used[index] = true;
|
used[index] = true;
|
||||||
try output.appendSlice(contents[source_offset..curr]);
|
try bw.writeAll(contents[source_offset..curr]);
|
||||||
switch (value) {
|
switch (value) {
|
||||||
.undef, .defined => {},
|
.undef, .defined => {},
|
||||||
.boolean => |b| {
|
.boolean => |b| try bw.writeByte(@as(u8, '0') + @intFromBool(b)),
|
||||||
try output.append(if (b) '1' else '0');
|
.int => |i| try bw.print("{d}", .{i}),
|
||||||
},
|
.ident, .string => |s| try bw.writeAll(s),
|
||||||
.int => |i| {
|
|
||||||
try output.writer().print("{d}", .{i});
|
|
||||||
},
|
|
||||||
.ident, .string => |s| {
|
|
||||||
try output.appendSlice(s);
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
curr = close_pos;
|
curr = close_pos;
|
||||||
@ -661,7 +613,7 @@ fn expand_variables_autoconf_at(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try output.appendSlice(contents[source_offset..]);
|
try bw.writeAll(contents[source_offset..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_variables_cmake(
|
fn expand_variables_cmake(
|
||||||
@ -669,7 +621,7 @@ fn expand_variables_cmake(
|
|||||||
contents: []const u8,
|
contents: []const u8,
|
||||||
values: std.StringArrayHashMap(Value),
|
values: std.StringArrayHashMap(Value),
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
var result = std.ArrayList(u8).init(allocator);
|
var result: std.ArrayList(u8) = .init(allocator);
|
||||||
errdefer result.deinit();
|
errdefer result.deinit();
|
||||||
|
|
||||||
const valid_varname_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/_.+-";
|
const valid_varname_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/_.+-";
|
||||||
@ -681,7 +633,7 @@ fn expand_variables_cmake(
|
|||||||
source: usize,
|
source: usize,
|
||||||
target: usize,
|
target: usize,
|
||||||
};
|
};
|
||||||
var var_stack = std.ArrayList(Position).init(allocator);
|
var var_stack: std.ArrayList(Position) = .init(allocator);
|
||||||
defer var_stack.deinit();
|
defer var_stack.deinit();
|
||||||
loop: while (curr < contents.len) : (curr += 1) {
|
loop: while (curr < contents.len) : (curr += 1) {
|
||||||
switch (contents[curr]) {
|
switch (contents[curr]) {
|
||||||
@ -707,7 +659,7 @@ fn expand_variables_cmake(
|
|||||||
try result.append(if (b) '1' else '0');
|
try result.append(if (b) '1' else '0');
|
||||||
},
|
},
|
||||||
.int => |i| {
|
.int => |i| {
|
||||||
try result.writer().print("{d}", .{i});
|
try result.print("{d}", .{i});
|
||||||
},
|
},
|
||||||
.ident, .string => |s| {
|
.ident, .string => |s| {
|
||||||
try result.appendSlice(s);
|
try result.appendSlice(s);
|
||||||
@ -764,7 +716,7 @@ fn expand_variables_cmake(
|
|||||||
try result.append(if (b) '1' else '0');
|
try result.append(if (b) '1' else '0');
|
||||||
},
|
},
|
||||||
.int => |i| {
|
.int => |i| {
|
||||||
try result.writer().print("{d}", .{i});
|
try result.print("{d}", .{i});
|
||||||
},
|
},
|
||||||
.ident, .string => |s| {
|
.ident, .string => |s| {
|
||||||
try result.appendSlice(s);
|
try result.appendSlice(s);
|
||||||
@ -801,17 +753,17 @@ fn testReplaceVariablesAutoconfAt(
|
|||||||
expected: []const u8,
|
expected: []const u8,
|
||||||
values: std.StringArrayHashMap(Value),
|
values: std.StringArrayHashMap(Value),
|
||||||
) !void {
|
) !void {
|
||||||
var output = std.ArrayList(u8).init(allocator);
|
var output: std.io.Writer.Allocating = .init(allocator);
|
||||||
defer output.deinit();
|
defer output.deinit();
|
||||||
|
|
||||||
const used = try allocator.alloc(bool, values.count());
|
const used = try allocator.alloc(bool, values.count());
|
||||||
for (used) |*u| u.* = false;
|
for (used) |*u| u.* = false;
|
||||||
defer allocator.free(used);
|
defer allocator.free(used);
|
||||||
|
|
||||||
try expand_variables_autoconf_at(&output, contents, values, used);
|
try expand_variables_autoconf_at(&output.interface, contents, values, used);
|
||||||
|
|
||||||
for (used) |u| if (!u) return error.UnusedValue;
|
for (used) |u| if (!u) return error.UnusedValue;
|
||||||
try std.testing.expectEqualStrings(expected, output.items);
|
try std.testing.expectEqualStrings(expected, output.getWritten());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testReplaceVariablesCMake(
|
fn testReplaceVariablesCMake(
|
||||||
@ -828,7 +780,7 @@ fn testReplaceVariablesCMake(
|
|||||||
|
|
||||||
test "expand_variables_autoconf_at simple cases" {
|
test "expand_variables_autoconf_at simple cases" {
|
||||||
const allocator = std.testing.allocator;
|
const allocator = std.testing.allocator;
|
||||||
var values = std.StringArrayHashMap(Value).init(allocator);
|
var values: std.StringArrayHashMap(Value) = .init(allocator);
|
||||||
defer values.deinit();
|
defer values.deinit();
|
||||||
|
|
||||||
// empty strings are preserved
|
// empty strings are preserved
|
||||||
@ -924,7 +876,7 @@ test "expand_variables_autoconf_at simple cases" {
|
|||||||
|
|
||||||
test "expand_variables_autoconf_at edge cases" {
|
test "expand_variables_autoconf_at edge cases" {
|
||||||
const allocator = std.testing.allocator;
|
const allocator = std.testing.allocator;
|
||||||
var values = std.StringArrayHashMap(Value).init(allocator);
|
var values: std.StringArrayHashMap(Value) = .init(allocator);
|
||||||
defer values.deinit();
|
defer values.deinit();
|
||||||
|
|
||||||
// @-vars resolved only when they wrap valid characters, otherwise considered literals
|
// @-vars resolved only when they wrap valid characters, otherwise considered literals
|
||||||
@ -940,7 +892,7 @@ test "expand_variables_autoconf_at edge cases" {
|
|||||||
|
|
||||||
test "expand_variables_cmake simple cases" {
|
test "expand_variables_cmake simple cases" {
|
||||||
const allocator = std.testing.allocator;
|
const allocator = std.testing.allocator;
|
||||||
var values = std.StringArrayHashMap(Value).init(allocator);
|
var values: std.StringArrayHashMap(Value) = .init(allocator);
|
||||||
defer values.deinit();
|
defer values.deinit();
|
||||||
|
|
||||||
try values.putNoClobber("undef", .undef);
|
try values.putNoClobber("undef", .undef);
|
||||||
@ -1028,7 +980,7 @@ test "expand_variables_cmake simple cases" {
|
|||||||
|
|
||||||
test "expand_variables_cmake edge cases" {
|
test "expand_variables_cmake edge cases" {
|
||||||
const allocator = std.testing.allocator;
|
const allocator = std.testing.allocator;
|
||||||
var values = std.StringArrayHashMap(Value).init(allocator);
|
var values: std.StringArrayHashMap(Value) = .init(allocator);
|
||||||
defer values.deinit();
|
defer values.deinit();
|
||||||
|
|
||||||
// special symbols
|
// special symbols
|
||||||
@ -1089,7 +1041,7 @@ test "expand_variables_cmake edge cases" {
|
|||||||
|
|
||||||
test "expand_variables_cmake escaped characters" {
|
test "expand_variables_cmake escaped characters" {
|
||||||
const allocator = std.testing.allocator;
|
const allocator = std.testing.allocator;
|
||||||
var values = std.StringArrayHashMap(Value).init(allocator);
|
var values: std.StringArrayHashMap(Value) = .init(allocator);
|
||||||
defer values.deinit();
|
defer values.deinit();
|
||||||
|
|
||||||
try values.putNoClobber("string", Value{ .string = "text" });
|
try values.putNoClobber("string", Value{ .string = "text" });
|
||||||
|
|||||||
@ -164,7 +164,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
const full_h_prefix = b.getInstallPath(h_dir, dir.dest_rel_path);
|
const full_h_prefix = b.getInstallPath(h_dir, dir.dest_rel_path);
|
||||||
|
|
||||||
var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {
|
var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {
|
||||||
return step.fail("unable to open source directory '{}': {s}", .{
|
return step.fail("unable to open source directory '{f}': {s}", .{
|
||||||
src_dir_path, @errorName(err),
|
src_dir_path, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -65,7 +65,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
const src_dir_path = install_dir.options.source_dir.getPath3(b, step);
|
const src_dir_path = install_dir.options.source_dir.getPath3(b, step);
|
||||||
const need_derived_inputs = try step.addDirectoryWatchInput(install_dir.options.source_dir);
|
const need_derived_inputs = try step.addDirectoryWatchInput(install_dir.options.source_dir);
|
||||||
var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {
|
var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {
|
||||||
return step.fail("unable to open source directory '{}': {s}", .{
|
return step.fail("unable to open source directory '{f}': {s}", .{
|
||||||
src_dir_path, @errorName(err),
|
src_dir_path, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -12,23 +12,23 @@ pub const base_id: Step.Id = .options;
|
|||||||
step: Step,
|
step: Step,
|
||||||
generated_file: GeneratedFile,
|
generated_file: GeneratedFile,
|
||||||
|
|
||||||
contents: std.ArrayList(u8),
|
contents: std.ArrayListUnmanaged(u8),
|
||||||
args: std.ArrayList(Arg),
|
args: std.ArrayListUnmanaged(Arg),
|
||||||
encountered_types: std.StringHashMap(void),
|
encountered_types: std.StringHashMapUnmanaged(void),
|
||||||
|
|
||||||
pub fn create(owner: *std.Build) *Options {
|
pub fn create(owner: *std.Build) *Options {
|
||||||
const options = owner.allocator.create(Options) catch @panic("OOM");
|
const options = owner.allocator.create(Options) catch @panic("OOM");
|
||||||
options.* = .{
|
options.* = .{
|
||||||
.step = Step.init(.{
|
.step = .init(.{
|
||||||
.id = base_id,
|
.id = base_id,
|
||||||
.name = "options",
|
.name = "options",
|
||||||
.owner = owner,
|
.owner = owner,
|
||||||
.makeFn = make,
|
.makeFn = make,
|
||||||
}),
|
}),
|
||||||
.generated_file = undefined,
|
.generated_file = undefined,
|
||||||
.contents = std.ArrayList(u8).init(owner.allocator),
|
.contents = .empty,
|
||||||
.args = std.ArrayList(Arg).init(owner.allocator),
|
.args = .empty,
|
||||||
.encountered_types = std.StringHashMap(void).init(owner.allocator),
|
.encountered_types = .empty,
|
||||||
};
|
};
|
||||||
options.generated_file = .{ .step = &options.step };
|
options.generated_file = .{ .step = &options.step };
|
||||||
|
|
||||||
@ -40,110 +40,119 @@ pub fn addOption(options: *Options, comptime T: type, name: []const u8, value: T
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn addOptionFallible(options: *Options, comptime T: type, name: []const u8, value: T) !void {
|
fn addOptionFallible(options: *Options, comptime T: type, name: []const u8, value: T) !void {
|
||||||
const out = options.contents.writer();
|
try printType(options, &options.contents, T, value, 0, name);
|
||||||
try printType(options, out, T, value, 0, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent: u8, name: ?[]const u8) !void {
|
fn printType(
|
||||||
|
options: *Options,
|
||||||
|
out: *std.ArrayListUnmanaged(u8),
|
||||||
|
comptime T: type,
|
||||||
|
value: T,
|
||||||
|
indent: u8,
|
||||||
|
name: ?[]const u8,
|
||||||
|
) !void {
|
||||||
|
const gpa = options.step.owner.allocator;
|
||||||
switch (T) {
|
switch (T) {
|
||||||
[]const []const u8 => {
|
[]const []const u8 => {
|
||||||
if (name) |payload| {
|
if (name) |payload| {
|
||||||
try out.print("pub const {}: []const []const u8 = ", .{std.zig.fmtId(payload)});
|
try out.print(gpa, "pub const {f}: []const []const u8 = ", .{std.zig.fmtId(payload)});
|
||||||
}
|
}
|
||||||
|
|
||||||
try out.writeAll("&[_][]const u8{\n");
|
try out.appendSlice(gpa, "&[_][]const u8{\n");
|
||||||
|
|
||||||
for (value) |slice| {
|
for (value) |slice| {
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try out.print(" \"{}\",\n", .{std.zig.fmtEscapes(slice)});
|
try out.print(gpa, " \"{f}\",\n", .{std.zig.fmtString(slice)});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
try out.writeAll("};\n");
|
try out.appendSlice(gpa, "};\n");
|
||||||
} else {
|
} else {
|
||||||
try out.writeAll("},\n");
|
try out.appendSlice(gpa, "},\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
[]const u8 => {
|
[]const u8 => {
|
||||||
if (name) |some| {
|
if (name) |some| {
|
||||||
try out.print("pub const {}: []const u8 = \"{}\";", .{ std.zig.fmtId(some), std.zig.fmtEscapes(value) });
|
try out.print(gpa, "pub const {f}: []const u8 = \"{f}\";", .{
|
||||||
|
std.zig.fmtId(some), std.zig.fmtString(value),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
try out.print("\"{}\",", .{std.zig.fmtEscapes(value)});
|
try out.print(gpa, "\"{f}\",", .{std.zig.fmtString(value)});
|
||||||
}
|
}
|
||||||
return out.writeAll("\n");
|
return out.appendSlice(gpa, "\n");
|
||||||
},
|
},
|
||||||
[:0]const u8 => {
|
[:0]const u8 => {
|
||||||
if (name) |some| {
|
if (name) |some| {
|
||||||
try out.print("pub const {}: [:0]const u8 = \"{}\";", .{ std.zig.fmtId(some), std.zig.fmtEscapes(value) });
|
try out.print(gpa, "pub const {f}: [:0]const u8 = \"{f}\";", .{ std.zig.fmtId(some), std.zig.fmtString(value) });
|
||||||
} else {
|
} else {
|
||||||
try out.print("\"{}\",", .{std.zig.fmtEscapes(value)});
|
try out.print(gpa, "\"{f}\",", .{std.zig.fmtString(value)});
|
||||||
}
|
}
|
||||||
return out.writeAll("\n");
|
return out.appendSlice(gpa, "\n");
|
||||||
},
|
},
|
||||||
?[]const u8 => {
|
?[]const u8 => {
|
||||||
if (name) |some| {
|
if (name) |some| {
|
||||||
try out.print("pub const {}: ?[]const u8 = ", .{std.zig.fmtId(some)});
|
try out.print(gpa, "pub const {f}: ?[]const u8 = ", .{std.zig.fmtId(some)});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value) |payload| {
|
if (value) |payload| {
|
||||||
try out.print("\"{}\"", .{std.zig.fmtEscapes(payload)});
|
try out.print(gpa, "\"{f}\"", .{std.zig.fmtString(payload)});
|
||||||
} else {
|
} else {
|
||||||
try out.writeAll("null");
|
try out.appendSlice(gpa, "null");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
try out.writeAll(";\n");
|
try out.appendSlice(gpa, ";\n");
|
||||||
} else {
|
} else {
|
||||||
try out.writeAll(",\n");
|
try out.appendSlice(gpa, ",\n");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
?[:0]const u8 => {
|
?[:0]const u8 => {
|
||||||
if (name) |some| {
|
if (name) |some| {
|
||||||
try out.print("pub const {}: ?[:0]const u8 = ", .{std.zig.fmtId(some)});
|
try out.print(gpa, "pub const {f}: ?[:0]const u8 = ", .{std.zig.fmtId(some)});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value) |payload| {
|
if (value) |payload| {
|
||||||
try out.print("\"{}\"", .{std.zig.fmtEscapes(payload)});
|
try out.print(gpa, "\"{f}\"", .{std.zig.fmtString(payload)});
|
||||||
} else {
|
} else {
|
||||||
try out.writeAll("null");
|
try out.appendSlice(gpa, "null");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
try out.writeAll(";\n");
|
try out.appendSlice(gpa, ";\n");
|
||||||
} else {
|
} else {
|
||||||
try out.writeAll(",\n");
|
try out.appendSlice(gpa, ",\n");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
std.SemanticVersion => {
|
std.SemanticVersion => {
|
||||||
if (name) |some| {
|
if (name) |some| {
|
||||||
try out.print("pub const {}: @import(\"std\").SemanticVersion = ", .{std.zig.fmtId(some)});
|
try out.print(gpa, "pub const {f}: @import(\"std\").SemanticVersion = ", .{std.zig.fmtId(some)});
|
||||||
}
|
}
|
||||||
|
|
||||||
try out.writeAll(".{\n");
|
try out.appendSlice(gpa, ".{\n");
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try out.print(" .major = {d},\n", .{value.major});
|
try out.print(gpa, " .major = {d},\n", .{value.major});
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try out.print(" .minor = {d},\n", .{value.minor});
|
try out.print(gpa, " .minor = {d},\n", .{value.minor});
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try out.print(" .patch = {d},\n", .{value.patch});
|
try out.print(gpa, " .patch = {d},\n", .{value.patch});
|
||||||
|
|
||||||
if (value.pre) |some| {
|
if (value.pre) |some| {
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try out.print(" .pre = \"{}\",\n", .{std.zig.fmtEscapes(some)});
|
try out.print(gpa, " .pre = \"{f}\",\n", .{std.zig.fmtString(some)});
|
||||||
}
|
}
|
||||||
if (value.build) |some| {
|
if (value.build) |some| {
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try out.print(" .build = \"{}\",\n", .{std.zig.fmtEscapes(some)});
|
try out.print(gpa, " .build = \"{f}\",\n", .{std.zig.fmtString(some)});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
try out.writeAll("};\n");
|
try out.appendSlice(gpa, "};\n");
|
||||||
} else {
|
} else {
|
||||||
try out.writeAll("},\n");
|
try out.appendSlice(gpa, "},\n");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
@ -153,21 +162,21 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
|
|||||||
switch (@typeInfo(T)) {
|
switch (@typeInfo(T)) {
|
||||||
.array => {
|
.array => {
|
||||||
if (name) |some| {
|
if (name) |some| {
|
||||||
try out.print("pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
|
try out.print(gpa, "pub const {f}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
|
||||||
}
|
}
|
||||||
|
|
||||||
try out.print("{s} {{\n", .{@typeName(T)});
|
try out.print(gpa, "{s} {{\n", .{@typeName(T)});
|
||||||
for (value) |item| {
|
for (value) |item| {
|
||||||
try out.writeByteNTimes(' ', indent + 4);
|
try out.appendNTimes(gpa, ' ', indent + 4);
|
||||||
try printType(options, out, @TypeOf(item), item, indent + 4, null);
|
try printType(options, out, @TypeOf(item), item, indent + 4, null);
|
||||||
}
|
}
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try out.writeAll("}");
|
try out.appendSlice(gpa, "}");
|
||||||
|
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
try out.writeAll(";\n");
|
try out.appendSlice(gpa, ";\n");
|
||||||
} else {
|
} else {
|
||||||
try out.writeAll(",\n");
|
try out.appendSlice(gpa, ",\n");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
@ -177,27 +186,27 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (name) |some| {
|
if (name) |some| {
|
||||||
try out.print("pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
|
try out.print(gpa, "pub const {f}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
|
||||||
}
|
}
|
||||||
|
|
||||||
try out.print("&[_]{s} {{\n", .{@typeName(p.child)});
|
try out.print(gpa, "&[_]{s} {{\n", .{@typeName(p.child)});
|
||||||
for (value) |item| {
|
for (value) |item| {
|
||||||
try out.writeByteNTimes(' ', indent + 4);
|
try out.appendNTimes(gpa, ' ', indent + 4);
|
||||||
try printType(options, out, @TypeOf(item), item, indent + 4, null);
|
try printType(options, out, @TypeOf(item), item, indent + 4, null);
|
||||||
}
|
}
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try out.writeAll("}");
|
try out.appendSlice(gpa, "}");
|
||||||
|
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
try out.writeAll(";\n");
|
try out.appendSlice(gpa, ";\n");
|
||||||
} else {
|
} else {
|
||||||
try out.writeAll(",\n");
|
try out.appendSlice(gpa, ",\n");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
.optional => {
|
.optional => {
|
||||||
if (name) |some| {
|
if (name) |some| {
|
||||||
try out.print("pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
|
try out.print(gpa, "pub const {f}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value) |inner| {
|
if (value) |inner| {
|
||||||
@ -206,13 +215,13 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
|
|||||||
_ = options.contents.pop();
|
_ = options.contents.pop();
|
||||||
_ = options.contents.pop();
|
_ = options.contents.pop();
|
||||||
} else {
|
} else {
|
||||||
try out.writeAll("null");
|
try out.appendSlice(gpa, "null");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
try out.writeAll(";\n");
|
try out.appendSlice(gpa, ";\n");
|
||||||
} else {
|
} else {
|
||||||
try out.writeAll(",\n");
|
try out.appendSlice(gpa, ",\n");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
@ -224,9 +233,9 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
|
|||||||
.null,
|
.null,
|
||||||
=> {
|
=> {
|
||||||
if (name) |some| {
|
if (name) |some| {
|
||||||
try out.print("pub const {}: {s} = {any};\n", .{ std.zig.fmtId(some), @typeName(T), value });
|
try out.print(gpa, "pub const {f}: {s} = {any};\n", .{ std.zig.fmtId(some), @typeName(T), value });
|
||||||
} else {
|
} else {
|
||||||
try out.print("{any},\n", .{value});
|
try out.print(gpa, "{any},\n", .{value});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
@ -234,10 +243,10 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
|
|||||||
try printEnum(options, out, T, info, indent);
|
try printEnum(options, out, T, info, indent);
|
||||||
|
|
||||||
if (name) |some| {
|
if (name) |some| {
|
||||||
try out.print("pub const {}: {} = .{p_};\n", .{
|
try out.print(gpa, "pub const {f}: {f} = .{f};\n", .{
|
||||||
std.zig.fmtId(some),
|
std.zig.fmtId(some),
|
||||||
std.zig.fmtId(@typeName(T)),
|
std.zig.fmtId(@typeName(T)),
|
||||||
std.zig.fmtId(@tagName(value)),
|
std.zig.fmtIdFlags(@tagName(value), .{ .allow_underscore = true, .allow_primitive = true }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -246,7 +255,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
|
|||||||
try printStruct(options, out, T, info, indent);
|
try printStruct(options, out, T, info, indent);
|
||||||
|
|
||||||
if (name) |some| {
|
if (name) |some| {
|
||||||
try out.print("pub const {}: {} = ", .{
|
try out.print(gpa, "pub const {f}: {f} = ", .{
|
||||||
std.zig.fmtId(some),
|
std.zig.fmtId(some),
|
||||||
std.zig.fmtId(@typeName(T)),
|
std.zig.fmtId(@typeName(T)),
|
||||||
});
|
});
|
||||||
@ -258,7 +267,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printUserDefinedType(options: *Options, out: anytype, comptime T: type, indent: u8) !void {
|
fn printUserDefinedType(options: *Options, out: *std.ArrayListUnmanaged(u8), comptime T: type, indent: u8) !void {
|
||||||
switch (@typeInfo(T)) {
|
switch (@typeInfo(T)) {
|
||||||
.@"enum" => |info| {
|
.@"enum" => |info| {
|
||||||
return try printEnum(options, out, T, info, indent);
|
return try printEnum(options, out, T, info, indent);
|
||||||
@ -270,94 +279,119 @@ fn printUserDefinedType(options: *Options, out: anytype, comptime T: type, inden
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printEnum(options: *Options, out: anytype, comptime T: type, comptime val: std.builtin.Type.Enum, indent: u8) !void {
|
fn printEnum(
|
||||||
const gop = try options.encountered_types.getOrPut(@typeName(T));
|
options: *Options,
|
||||||
|
out: *std.ArrayListUnmanaged(u8),
|
||||||
|
comptime T: type,
|
||||||
|
comptime val: std.builtin.Type.Enum,
|
||||||
|
indent: u8,
|
||||||
|
) !void {
|
||||||
|
const gpa = options.step.owner.allocator;
|
||||||
|
const gop = try options.encountered_types.getOrPut(gpa, @typeName(T));
|
||||||
if (gop.found_existing) return;
|
if (gop.found_existing) return;
|
||||||
|
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try out.print("pub const {} = enum ({s}) {{\n", .{ std.zig.fmtId(@typeName(T)), @typeName(val.tag_type) });
|
try out.print(gpa, "pub const {f} = enum ({s}) {{\n", .{ std.zig.fmtId(@typeName(T)), @typeName(val.tag_type) });
|
||||||
|
|
||||||
inline for (val.fields) |field| {
|
inline for (val.fields) |field| {
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try out.print(" {p} = {d},\n", .{ std.zig.fmtId(field.name), field.value });
|
try out.print(gpa, " {f} = {d},\n", .{
|
||||||
|
std.zig.fmtIdFlags(field.name, .{ .allow_primitive = true }), field.value,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!val.is_exhaustive) {
|
if (!val.is_exhaustive) {
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try out.writeAll(" _,\n");
|
try out.appendSlice(gpa, " _,\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try out.writeAll("};\n");
|
try out.appendSlice(gpa, "};\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printStruct(options: *Options, out: anytype, comptime T: type, comptime val: std.builtin.Type.Struct, indent: u8) !void {
|
fn printStruct(options: *Options, out: *std.ArrayListUnmanaged(u8), comptime T: type, comptime val: std.builtin.Type.Struct, indent: u8) !void {
|
||||||
const gop = try options.encountered_types.getOrPut(@typeName(T));
|
const gpa = options.step.owner.allocator;
|
||||||
|
const gop = try options.encountered_types.getOrPut(gpa, @typeName(T));
|
||||||
if (gop.found_existing) return;
|
if (gop.found_existing) return;
|
||||||
|
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try out.print("pub const {} = ", .{std.zig.fmtId(@typeName(T))});
|
try out.print(gpa, "pub const {f} = ", .{std.zig.fmtId(@typeName(T))});
|
||||||
|
|
||||||
switch (val.layout) {
|
switch (val.layout) {
|
||||||
.@"extern" => try out.writeAll("extern struct"),
|
.@"extern" => try out.appendSlice(gpa, "extern struct"),
|
||||||
.@"packed" => try out.writeAll("packed struct"),
|
.@"packed" => try out.appendSlice(gpa, "packed struct"),
|
||||||
else => try out.writeAll("struct"),
|
else => try out.appendSlice(gpa, "struct"),
|
||||||
}
|
}
|
||||||
|
|
||||||
try out.writeAll(" {\n");
|
try out.appendSlice(gpa, " {\n");
|
||||||
|
|
||||||
inline for (val.fields) |field| {
|
inline for (val.fields) |field| {
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
|
|
||||||
const type_name = @typeName(field.type);
|
const type_name = @typeName(field.type);
|
||||||
|
|
||||||
// If the type name doesn't contains a '.' the type is from zig builtins.
|
// If the type name doesn't contains a '.' the type is from zig builtins.
|
||||||
if (std.mem.containsAtLeast(u8, type_name, 1, ".")) {
|
if (std.mem.containsAtLeast(u8, type_name, 1, ".")) {
|
||||||
try out.print(" {p_}: {}", .{ std.zig.fmtId(field.name), std.zig.fmtId(type_name) });
|
try out.print(gpa, " {f}: {f}", .{
|
||||||
|
std.zig.fmtIdFlags(field.name, .{ .allow_underscore = true, .allow_primitive = true }),
|
||||||
|
std.zig.fmtId(type_name),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
try out.print(" {p_}: {s}", .{ std.zig.fmtId(field.name), type_name });
|
try out.print(gpa, " {f}: {s}", .{
|
||||||
|
std.zig.fmtIdFlags(field.name, .{ .allow_underscore = true, .allow_primitive = true }),
|
||||||
|
type_name,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (field.defaultValue()) |default_value| {
|
if (field.defaultValue()) |default_value| {
|
||||||
try out.writeAll(" = ");
|
try out.appendSlice(gpa, " = ");
|
||||||
switch (@typeInfo(@TypeOf(default_value))) {
|
switch (@typeInfo(@TypeOf(default_value))) {
|
||||||
.@"enum" => try out.print(".{s},\n", .{@tagName(default_value)}),
|
.@"enum" => try out.print(gpa, ".{s},\n", .{@tagName(default_value)}),
|
||||||
.@"struct" => |info| {
|
.@"struct" => |info| {
|
||||||
try printStructValue(options, out, info, default_value, indent + 4);
|
try printStructValue(options, out, info, default_value, indent + 4);
|
||||||
},
|
},
|
||||||
else => try printType(options, out, @TypeOf(default_value), default_value, indent, null),
|
else => try printType(options, out, @TypeOf(default_value), default_value, indent, null),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try out.writeAll(",\n");
|
try out.appendSlice(gpa, ",\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: write declarations
|
// TODO: write declarations
|
||||||
|
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try out.writeAll("};\n");
|
try out.appendSlice(gpa, "};\n");
|
||||||
|
|
||||||
inline for (val.fields) |field| {
|
inline for (val.fields) |field| {
|
||||||
try printUserDefinedType(options, out, field.type, 0);
|
try printUserDefinedType(options, out, field.type, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printStructValue(options: *Options, out: anytype, comptime struct_val: std.builtin.Type.Struct, val: anytype, indent: u8) !void {
|
fn printStructValue(
|
||||||
try out.writeAll(".{\n");
|
options: *Options,
|
||||||
|
out: *std.ArrayListUnmanaged(u8),
|
||||||
|
comptime struct_val: std.builtin.Type.Struct,
|
||||||
|
val: anytype,
|
||||||
|
indent: u8,
|
||||||
|
) !void {
|
||||||
|
const gpa = options.step.owner.allocator;
|
||||||
|
try out.appendSlice(gpa, ".{\n");
|
||||||
|
|
||||||
if (struct_val.is_tuple) {
|
if (struct_val.is_tuple) {
|
||||||
inline for (struct_val.fields) |field| {
|
inline for (struct_val.fields) |field| {
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try printType(options, out, @TypeOf(@field(val, field.name)), @field(val, field.name), indent, null);
|
try printType(options, out, @TypeOf(@field(val, field.name)), @field(val, field.name), indent, null);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
inline for (struct_val.fields) |field| {
|
inline for (struct_val.fields) |field| {
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try out.print(" .{p_} = ", .{std.zig.fmtId(field.name)});
|
try out.print(gpa, " .{f} = ", .{
|
||||||
|
std.zig.fmtIdFlags(field.name, .{ .allow_primitive = true, .allow_underscore = true }),
|
||||||
|
});
|
||||||
|
|
||||||
const field_name = @field(val, field.name);
|
const field_name = @field(val, field.name);
|
||||||
switch (@typeInfo(@TypeOf(field_name))) {
|
switch (@typeInfo(@TypeOf(field_name))) {
|
||||||
.@"enum" => try out.print(".{s},\n", .{@tagName(field_name)}),
|
.@"enum" => try out.print(gpa, ".{s},\n", .{@tagName(field_name)}),
|
||||||
.@"struct" => |struct_info| {
|
.@"struct" => |struct_info| {
|
||||||
try printStructValue(options, out, struct_info, field_name, indent + 4);
|
try printStructValue(options, out, struct_info, field_name, indent + 4);
|
||||||
},
|
},
|
||||||
@ -367,10 +401,10 @@ fn printStructValue(options: *Options, out: anytype, comptime struct_val: std.bu
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (indent == 0) {
|
if (indent == 0) {
|
||||||
try out.writeAll("};\n");
|
try out.appendSlice(gpa, "};\n");
|
||||||
} else {
|
} else {
|
||||||
try out.writeByteNTimes(' ', indent);
|
try out.appendNTimes(gpa, ' ', indent);
|
||||||
try out.writeAll("},\n");
|
try out.appendSlice(gpa, "},\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,7 +474,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
|
|||||||
error.FileNotFound => {
|
error.FileNotFound => {
|
||||||
const sub_dirname = fs.path.dirname(sub_path).?;
|
const sub_dirname = fs.path.dirname(sub_path).?;
|
||||||
b.cache_root.handle.makePath(sub_dirname) catch |e| {
|
b.cache_root.handle.makePath(sub_dirname) catch |e| {
|
||||||
return step.fail("unable to make path '{}{s}': {s}", .{
|
return step.fail("unable to make path '{f}{s}': {s}", .{
|
||||||
b.cache_root, sub_dirname, @errorName(e),
|
b.cache_root, sub_dirname, @errorName(e),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -452,13 +486,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
|
|||||||
const tmp_sub_path_dirname = fs.path.dirname(tmp_sub_path).?;
|
const tmp_sub_path_dirname = fs.path.dirname(tmp_sub_path).?;
|
||||||
|
|
||||||
b.cache_root.handle.makePath(tmp_sub_path_dirname) catch |err| {
|
b.cache_root.handle.makePath(tmp_sub_path_dirname) catch |err| {
|
||||||
return step.fail("unable to make temporary directory '{}{s}': {s}", .{
|
return step.fail("unable to make temporary directory '{f}{s}': {s}", .{
|
||||||
b.cache_root, tmp_sub_path_dirname, @errorName(err),
|
b.cache_root, tmp_sub_path_dirname, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
b.cache_root.handle.writeFile(.{ .sub_path = tmp_sub_path, .data = options.contents.items }) catch |err| {
|
b.cache_root.handle.writeFile(.{ .sub_path = tmp_sub_path, .data = options.contents.items }) catch |err| {
|
||||||
return step.fail("unable to write options to '{}{s}': {s}", .{
|
return step.fail("unable to write options to '{f}{s}': {s}", .{
|
||||||
b.cache_root, tmp_sub_path, @errorName(err),
|
b.cache_root, tmp_sub_path, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -467,7 +501,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
|
|||||||
error.PathAlreadyExists => {
|
error.PathAlreadyExists => {
|
||||||
// Other process beat us to it. Clean up the temp file.
|
// Other process beat us to it. Clean up the temp file.
|
||||||
b.cache_root.handle.deleteFile(tmp_sub_path) catch |e| {
|
b.cache_root.handle.deleteFile(tmp_sub_path) catch |e| {
|
||||||
try step.addError("warning: unable to delete temp file '{}{s}': {s}", .{
|
try step.addError("warning: unable to delete temp file '{f}{s}': {s}", .{
|
||||||
b.cache_root, tmp_sub_path, @errorName(e),
|
b.cache_root, tmp_sub_path, @errorName(e),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -475,7 +509,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
|
|||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
return step.fail("unable to rename options from '{}{s}' to '{}{s}': {s}", .{
|
return step.fail("unable to rename options from '{f}{s}' to '{f}{s}': {s}", .{
|
||||||
b.cache_root, tmp_sub_path,
|
b.cache_root, tmp_sub_path,
|
||||||
b.cache_root, sub_path,
|
b.cache_root, sub_path,
|
||||||
@errorName(err),
|
@errorName(err),
|
||||||
@ -483,7 +517,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
else => |e| return step.fail("unable to access options file '{}{s}': {s}", .{
|
else => |e| return step.fail("unable to access options file '{f}{s}': {s}", .{
|
||||||
b.cache_root, sub_path, @errorName(e),
|
b.cache_root, sub_path, @errorName(e),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
@ -643,5 +677,5 @@ test Options {
|
|||||||
\\
|
\\
|
||||||
, options.contents.items);
|
, options.contents.items);
|
||||||
|
|
||||||
_ = try std.zig.Ast.parse(arena.allocator(), try options.contents.toOwnedSliceSentinel(0), .zig);
|
_ = try std.zig.Ast.parse(arena.allocator(), try options.contents.toOwnedSliceSentinel(arena.allocator(), 0), .zig);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -832,7 +832,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
b.cache_root.handle.makePath(output_sub_dir_path) catch |err| {
|
b.cache_root.handle.makePath(output_sub_dir_path) catch |err| {
|
||||||
return step.fail("unable to make path '{}{s}': {s}", .{
|
return step.fail("unable to make path '{f}{s}': {s}", .{
|
||||||
b.cache_root, output_sub_dir_path, @errorName(err),
|
b.cache_root, output_sub_dir_path, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -864,7 +864,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
b.cache_root.handle.makePath(output_sub_dir_path) catch |err| {
|
b.cache_root.handle.makePath(output_sub_dir_path) catch |err| {
|
||||||
return step.fail("unable to make path '{}{s}': {s}", .{
|
return step.fail("unable to make path '{f}{s}': {s}", .{
|
||||||
b.cache_root, output_sub_dir_path, @errorName(err),
|
b.cache_root, output_sub_dir_path, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -903,21 +903,21 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |err| {
|
b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |err| {
|
||||||
if (err == error.PathAlreadyExists) {
|
if (err == error.PathAlreadyExists) {
|
||||||
b.cache_root.handle.deleteTree(o_sub_path) catch |del_err| {
|
b.cache_root.handle.deleteTree(o_sub_path) catch |del_err| {
|
||||||
return step.fail("unable to remove dir '{}'{s}: {s}", .{
|
return step.fail("unable to remove dir '{f}'{s}: {s}", .{
|
||||||
b.cache_root,
|
b.cache_root,
|
||||||
tmp_dir_path,
|
tmp_dir_path,
|
||||||
@errorName(del_err),
|
@errorName(del_err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |retry_err| {
|
b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |retry_err| {
|
||||||
return step.fail("unable to rename dir '{}{s}' to '{}{s}': {s}", .{
|
return step.fail("unable to rename dir '{f}{s}' to '{f}{s}': {s}", .{
|
||||||
b.cache_root, tmp_dir_path,
|
b.cache_root, tmp_dir_path,
|
||||||
b.cache_root, o_sub_path,
|
b.cache_root, o_sub_path,
|
||||||
@errorName(retry_err),
|
@errorName(retry_err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return step.fail("unable to rename dir '{}{s}' to '{}{s}': {s}", .{
|
return step.fail("unable to rename dir '{f}{s}' to '{f}{s}': {s}", .{
|
||||||
b.cache_root, tmp_dir_path,
|
b.cache_root, tmp_dir_path,
|
||||||
b.cache_root, o_sub_path,
|
b.cache_root, o_sub_path,
|
||||||
@errorName(err),
|
@errorName(err),
|
||||||
@ -964,7 +964,7 @@ pub fn rerunInFuzzMode(
|
|||||||
.artifact => |pa| {
|
.artifact => |pa| {
|
||||||
const artifact = pa.artifact;
|
const artifact = pa.artifact;
|
||||||
const file_path: []const u8 = p: {
|
const file_path: []const u8 = p: {
|
||||||
if (artifact == run.producer.?) break :p b.fmt("{}", .{run.rebuilt_executable.?});
|
if (artifact == run.producer.?) break :p b.fmt("{f}", .{run.rebuilt_executable.?});
|
||||||
break :p artifact.installed_path orelse artifact.generated_bin.?.path.?;
|
break :p artifact.installed_path orelse artifact.generated_bin.?.path.?;
|
||||||
};
|
};
|
||||||
try argv_list.append(arena, b.fmt("{s}{s}", .{
|
try argv_list.append(arena, b.fmt("{s}{s}", .{
|
||||||
@ -1011,24 +1011,17 @@ fn populateGeneratedPaths(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn formatTerm(
|
fn formatTerm(term: ?std.process.Child.Term, w: *std.io.Writer) std.io.Writer.Error!void {
|
||||||
term: ?std.process.Child.Term,
|
|
||||||
comptime fmt: []const u8,
|
|
||||||
options: std.fmt.FormatOptions,
|
|
||||||
writer: anytype,
|
|
||||||
) !void {
|
|
||||||
_ = fmt;
|
|
||||||
_ = options;
|
|
||||||
if (term) |t| switch (t) {
|
if (term) |t| switch (t) {
|
||||||
.Exited => |code| try writer.print("exited with code {}", .{code}),
|
.Exited => |code| try w.print("exited with code {d}", .{code}),
|
||||||
.Signal => |sig| try writer.print("terminated with signal {}", .{sig}),
|
.Signal => |sig| try w.print("terminated with signal {d}", .{sig}),
|
||||||
.Stopped => |sig| try writer.print("stopped with signal {}", .{sig}),
|
.Stopped => |sig| try w.print("stopped with signal {d}", .{sig}),
|
||||||
.Unknown => |code| try writer.print("terminated for unknown reason with code {}", .{code}),
|
.Unknown => |code| try w.print("terminated for unknown reason with code {d}", .{code}),
|
||||||
} else {
|
} else {
|
||||||
try writer.writeAll("exited with any code");
|
try w.writeAll("exited with any code");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn fmtTerm(term: ?std.process.Child.Term) std.fmt.Formatter(formatTerm) {
|
fn fmtTerm(term: ?std.process.Child.Term) std.fmt.Formatter(?std.process.Child.Term, formatTerm) {
|
||||||
return .{ .data = term };
|
return .{ .data = term };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1262,12 +1255,12 @@ fn runCommand(
|
|||||||
const sub_path = b.pathJoin(&output_components);
|
const sub_path = b.pathJoin(&output_components);
|
||||||
const sub_path_dirname = fs.path.dirname(sub_path).?;
|
const sub_path_dirname = fs.path.dirname(sub_path).?;
|
||||||
b.cache_root.handle.makePath(sub_path_dirname) catch |err| {
|
b.cache_root.handle.makePath(sub_path_dirname) catch |err| {
|
||||||
return step.fail("unable to make path '{}{s}': {s}", .{
|
return step.fail("unable to make path '{f}{s}': {s}", .{
|
||||||
b.cache_root, sub_path_dirname, @errorName(err),
|
b.cache_root, sub_path_dirname, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = stream.bytes.? }) catch |err| {
|
b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = stream.bytes.? }) catch |err| {
|
||||||
return step.fail("unable to write file '{}{s}': {s}", .{
|
return step.fail("unable to write file '{f}{s}': {s}", .{
|
||||||
b.cache_root, sub_path, @errorName(err),
|
b.cache_root, sub_path, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -1346,7 +1339,7 @@ fn runCommand(
|
|||||||
},
|
},
|
||||||
.expect_term => |expected_term| {
|
.expect_term => |expected_term| {
|
||||||
if (!termMatches(expected_term, result.term)) {
|
if (!termMatches(expected_term, result.term)) {
|
||||||
return step.fail("the following command {} (expected {}):\n{s}", .{
|
return step.fail("the following command {f} (expected {f}):\n{s}", .{
|
||||||
fmtTerm(result.term),
|
fmtTerm(result.term),
|
||||||
fmtTerm(expected_term),
|
fmtTerm(expected_term),
|
||||||
try Step.allocPrintCmd(arena, cwd, final_argv),
|
try Step.allocPrintCmd(arena, cwd, final_argv),
|
||||||
@ -1366,7 +1359,7 @@ fn runCommand(
|
|||||||
};
|
};
|
||||||
const expected_term: std.process.Child.Term = .{ .Exited = 0 };
|
const expected_term: std.process.Child.Term = .{ .Exited = 0 };
|
||||||
if (!termMatches(expected_term, result.term)) {
|
if (!termMatches(expected_term, result.term)) {
|
||||||
return step.fail("{s}the following command {} (expected {}):\n{s}", .{
|
return step.fail("{s}the following command {f} (expected {f}):\n{s}", .{
|
||||||
prefix,
|
prefix,
|
||||||
fmtTerm(result.term),
|
fmtTerm(result.term),
|
||||||
fmtTerm(expected_term),
|
fmtTerm(expected_term),
|
||||||
@ -1797,10 +1790,10 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {
|
|||||||
stdout_bytes = try poller.fifo(.stdout).toOwnedSlice();
|
stdout_bytes = try poller.fifo(.stdout).toOwnedSlice();
|
||||||
stderr_bytes = try poller.fifo(.stderr).toOwnedSlice();
|
stderr_bytes = try poller.fifo(.stderr).toOwnedSlice();
|
||||||
} else {
|
} else {
|
||||||
stdout_bytes = try stdout.reader().readAllAlloc(arena, run.max_stdio_size);
|
stdout_bytes = try stdout.deprecatedReader().readAllAlloc(arena, run.max_stdio_size);
|
||||||
}
|
}
|
||||||
} else if (child.stderr) |stderr| {
|
} else if (child.stderr) |stderr| {
|
||||||
stderr_bytes = try stderr.reader().readAllAlloc(arena, run.max_stdio_size);
|
stderr_bytes = try stderr.deprecatedReader().readAllAlloc(arena, run.max_stdio_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stderr_bytes) |bytes| if (bytes.len > 0) {
|
if (stderr_bytes) |bytes| if (bytes.len > 0) {
|
||||||
|
|||||||
@ -76,7 +76,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
for (usf.output_source_files.items) |output_source_file| {
|
for (usf.output_source_files.items) |output_source_file| {
|
||||||
if (fs.path.dirname(output_source_file.sub_path)) |dirname| {
|
if (fs.path.dirname(output_source_file.sub_path)) |dirname| {
|
||||||
b.build_root.handle.makePath(dirname) catch |err| {
|
b.build_root.handle.makePath(dirname) catch |err| {
|
||||||
return step.fail("unable to make path '{}{s}': {s}", .{
|
return step.fail("unable to make path '{f}{s}': {s}", .{
|
||||||
b.build_root, dirname, @errorName(err),
|
b.build_root, dirname, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -84,7 +84,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
switch (output_source_file.contents) {
|
switch (output_source_file.contents) {
|
||||||
.bytes => |bytes| {
|
.bytes => |bytes| {
|
||||||
b.build_root.handle.writeFile(.{ .sub_path = output_source_file.sub_path, .data = bytes }) catch |err| {
|
b.build_root.handle.writeFile(.{ .sub_path = output_source_file.sub_path, .data = bytes }) catch |err| {
|
||||||
return step.fail("unable to write file '{}{s}': {s}", .{
|
return step.fail("unable to write file '{f}{s}': {s}", .{
|
||||||
b.build_root, output_source_file.sub_path, @errorName(err),
|
b.build_root, output_source_file.sub_path, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -101,7 +101,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
output_source_file.sub_path,
|
output_source_file.sub_path,
|
||||||
.{},
|
.{},
|
||||||
) catch |err| {
|
) catch |err| {
|
||||||
return step.fail("unable to update file from '{s}' to '{}{s}': {s}", .{
|
return step.fail("unable to update file from '{s}' to '{f}{s}': {s}", .{
|
||||||
source_path, b.build_root, output_source_file.sub_path, @errorName(err),
|
source_path, b.build_root, output_source_file.sub_path, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -217,7 +217,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
const src_dir_path = dir.source.getPath3(b, step);
|
const src_dir_path = dir.source.getPath3(b, step);
|
||||||
|
|
||||||
var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {
|
var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {
|
||||||
return step.fail("unable to open source directory '{}': {s}", .{
|
return step.fail("unable to open source directory '{f}': {s}", .{
|
||||||
src_dir_path, @errorName(err),
|
src_dir_path, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -258,7 +258,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest });
|
write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest });
|
||||||
|
|
||||||
var cache_dir = b.cache_root.handle.makeOpenPath(cache_path, .{}) catch |err| {
|
var cache_dir = b.cache_root.handle.makeOpenPath(cache_path, .{}) catch |err| {
|
||||||
return step.fail("unable to make path '{}{s}': {s}", .{
|
return step.fail("unable to make path '{f}{s}': {s}", .{
|
||||||
b.cache_root, cache_path, @errorName(err),
|
b.cache_root, cache_path, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -269,7 +269,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
for (write_file.files.items) |file| {
|
for (write_file.files.items) |file| {
|
||||||
if (fs.path.dirname(file.sub_path)) |dirname| {
|
if (fs.path.dirname(file.sub_path)) |dirname| {
|
||||||
cache_dir.makePath(dirname) catch |err| {
|
cache_dir.makePath(dirname) catch |err| {
|
||||||
return step.fail("unable to make path '{}{s}{c}{s}': {s}", .{
|
return step.fail("unable to make path '{f}{s}{c}{s}': {s}", .{
|
||||||
b.cache_root, cache_path, fs.path.sep, dirname, @errorName(err),
|
b.cache_root, cache_path, fs.path.sep, dirname, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -277,7 +277,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
switch (file.contents) {
|
switch (file.contents) {
|
||||||
.bytes => |bytes| {
|
.bytes => |bytes| {
|
||||||
cache_dir.writeFile(.{ .sub_path = file.sub_path, .data = bytes }) catch |err| {
|
cache_dir.writeFile(.{ .sub_path = file.sub_path, .data = bytes }) catch |err| {
|
||||||
return step.fail("unable to write file '{}{s}{c}{s}': {s}", .{
|
return step.fail("unable to write file '{f}{s}{c}{s}': {s}", .{
|
||||||
b.cache_root, cache_path, fs.path.sep, file.sub_path, @errorName(err),
|
b.cache_root, cache_path, fs.path.sep, file.sub_path, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -291,7 +291,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
file.sub_path,
|
file.sub_path,
|
||||||
.{},
|
.{},
|
||||||
) catch |err| {
|
) catch |err| {
|
||||||
return step.fail("unable to update file from '{s}' to '{}{s}{c}{s}': {s}", .{
|
return step.fail("unable to update file from '{s}' to '{f}{s}{c}{s}': {s}", .{
|
||||||
source_path,
|
source_path,
|
||||||
b.cache_root,
|
b.cache_root,
|
||||||
cache_path,
|
cache_path,
|
||||||
@ -315,7 +315,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
|
|
||||||
if (dest_dirname.len != 0) {
|
if (dest_dirname.len != 0) {
|
||||||
cache_dir.makePath(dest_dirname) catch |err| {
|
cache_dir.makePath(dest_dirname) catch |err| {
|
||||||
return step.fail("unable to make path '{}{s}{c}{s}': {s}", .{
|
return step.fail("unable to make path '{f}{s}{c}{s}': {s}", .{
|
||||||
b.cache_root, cache_path, fs.path.sep, dest_dirname, @errorName(err),
|
b.cache_root, cache_path, fs.path.sep, dest_dirname, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -338,7 +338,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
|||||||
dest_path,
|
dest_path,
|
||||||
.{},
|
.{},
|
||||||
) catch |err| {
|
) catch |err| {
|
||||||
return step.fail("unable to update file from '{}' to '{}{s}{c}{s}': {s}", .{
|
return step.fail("unable to update file from '{f}' to '{f}{s}{c}{s}': {s}", .{
|
||||||
src_entry_path, b.cache_root, cache_path, fs.path.sep, dest_path, @errorName(err),
|
src_entry_path, b.cache_root, cache_path, fs.path.sep, dest_path, @errorName(err),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -211,7 +211,7 @@ const Os = switch (builtin.os.tag) {
|
|||||||
.ADD = true,
|
.ADD = true,
|
||||||
.ONLYDIR = true,
|
.ONLYDIR = true,
|
||||||
}, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| {
|
}, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| {
|
||||||
fatal("unable to watch {}: {s}", .{ path, @errorName(err) });
|
fatal("unable to watch {f}: {s}", .{ path, @errorName(err) });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
break :rs &dh_gop.value_ptr.reaction_set;
|
break :rs &dh_gop.value_ptr.reaction_set;
|
||||||
@ -265,7 +265,7 @@ const Os = switch (builtin.os.tag) {
|
|||||||
.ONLYDIR = true,
|
.ONLYDIR = true,
|
||||||
}, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| switch (err) {
|
}, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| switch (err) {
|
||||||
error.FileNotFound => {}, // Expected, harmless.
|
error.FileNotFound => {}, // Expected, harmless.
|
||||||
else => |e| std.log.warn("unable to unwatch '{}': {s}", .{ path, @errorName(e) }),
|
else => |e| std.log.warn("unable to unwatch '{f}': {s}", .{ path, @errorName(e) }),
|
||||||
};
|
};
|
||||||
|
|
||||||
w.dir_table.swapRemoveAt(i);
|
w.dir_table.swapRemoveAt(i);
|
||||||
@ -659,7 +659,7 @@ const Os = switch (builtin.os.tag) {
|
|||||||
path.root_dir.handle.fd
|
path.root_dir.handle.fd
|
||||||
else
|
else
|
||||||
posix.openat(path.root_dir.handle.fd, path.sub_path, dir_open_flags, 0) catch |err| {
|
posix.openat(path.root_dir.handle.fd, path.sub_path, dir_open_flags, 0) catch |err| {
|
||||||
fatal("failed to open directory {}: {s}", .{ path, @errorName(err) });
|
fatal("failed to open directory {f}: {s}", .{ path, @errorName(err) });
|
||||||
};
|
};
|
||||||
// Empirically the dir has to stay open or else no events are triggered.
|
// Empirically the dir has to stay open or else no events are triggered.
|
||||||
errdefer if (!skip_open_dir) posix.close(dir_fd);
|
errdefer if (!skip_open_dir) posix.close(dir_fd);
|
||||||
|
|||||||
@ -9,6 +9,7 @@ const Progress = @This();
|
|||||||
const posix = std.posix;
|
const posix = std.posix;
|
||||||
const is_big_endian = builtin.cpu.arch.endian() == .big;
|
const is_big_endian = builtin.cpu.arch.endian() == .big;
|
||||||
const is_windows = builtin.os.tag == .windows;
|
const is_windows = builtin.os.tag == .windows;
|
||||||
|
const Writer = std.io.Writer;
|
||||||
|
|
||||||
/// `null` if the current node (and its children) should
|
/// `null` if the current node (and its children) should
|
||||||
/// not print on update()
|
/// not print on update()
|
||||||
@ -606,6 +607,36 @@ pub fn unlockStdErr() void {
|
|||||||
stderr_mutex.unlock();
|
stderr_mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Protected by `stderr_mutex`.
|
||||||
|
const stderr_writer: *Writer = &stderr_file_writer.interface;
|
||||||
|
/// Protected by `stderr_mutex`.
|
||||||
|
var stderr_file_writer: std.fs.File.Writer = .{
|
||||||
|
.interface = std.fs.File.Writer.initInterface(&.{}),
|
||||||
|
.file = if (is_windows) undefined else .stderr(),
|
||||||
|
.mode = .streaming,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Allows the caller to freely write to the returned `Writer`,
|
||||||
|
/// initialized with `buffer`, until `unlockStderrWriter` is called.
|
||||||
|
///
|
||||||
|
/// During the lock, any `std.Progress` information is cleared from the terminal.
|
||||||
|
///
|
||||||
|
/// The lock is recursive; the same thread may hold the lock multiple times.
|
||||||
|
pub fn lockStderrWriter(buffer: []u8) *Writer {
|
||||||
|
stderr_mutex.lock();
|
||||||
|
clearWrittenWithEscapeCodes() catch {};
|
||||||
|
if (is_windows) stderr_file_writer.file = .stderr();
|
||||||
|
stderr_writer.flush() catch {};
|
||||||
|
stderr_writer.buffer = buffer;
|
||||||
|
return stderr_writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unlockStderrWriter() void {
|
||||||
|
stderr_writer.flush() catch {};
|
||||||
|
stderr_writer.buffer = &.{};
|
||||||
|
stderr_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
fn ipcThreadRun(fd: posix.fd_t) anyerror!void {
|
fn ipcThreadRun(fd: posix.fd_t) anyerror!void {
|
||||||
// Store this data in the thread so that it does not need to be part of the
|
// Store this data in the thread so that it does not need to be part of the
|
||||||
// linker data of the main executable.
|
// linker data of the main executable.
|
||||||
|
|||||||
@ -122,7 +122,7 @@ fn mode(comptime x: comptime_int) comptime_int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
const stdout = std.fs.File.stdout().writer();
|
const stdout = std.fs.File.stdout().deprecatedWriter();
|
||||||
|
|
||||||
var buffer: [1024]u8 = undefined;
|
var buffer: [1024]u8 = undefined;
|
||||||
var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
|
var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
|
||||||
|
|||||||
@ -150,17 +150,11 @@ fn parseNum(text: []const u8) error{ InvalidVersion, Overflow }!usize {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(
|
pub fn format(self: Version, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
|
||||||
self: Version,
|
|
||||||
comptime fmt: []const u8,
|
|
||||||
options: std.fmt.FormatOptions,
|
|
||||||
out_stream: anytype,
|
|
||||||
) !void {
|
|
||||||
_ = options;
|
|
||||||
if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
|
if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
|
||||||
try std.fmt.format(out_stream, "{d}.{d}.{d}", .{ self.major, self.minor, self.patch });
|
try w.print("{d}.{d}.{d}", .{ self.major, self.minor, self.patch });
|
||||||
if (self.pre) |pre| try std.fmt.format(out_stream, "-{s}", .{pre});
|
if (self.pre) |pre| try w.print("-{s}", .{pre});
|
||||||
if (self.build) |build| try std.fmt.format(out_stream, "+{s}", .{build});
|
if (self.build) |build| try w.print("+{s}", .{build});
|
||||||
}
|
}
|
||||||
|
|
||||||
const expect = std.testing.expect;
|
const expect = std.testing.expect;
|
||||||
@ -202,7 +196,7 @@ test format {
|
|||||||
"1.0.0+0.build.1-rc.10000aaa-kk-0.1",
|
"1.0.0+0.build.1-rc.10000aaa-kk-0.1",
|
||||||
"5.4.0-1018-raspi",
|
"5.4.0-1018-raspi",
|
||||||
"5.7.123",
|
"5.7.123",
|
||||||
}) |valid| try std.testing.expectFmt(valid, "{}", .{try parse(valid)});
|
}) |valid| try std.testing.expectFmt(valid, "{f}", .{try parse(valid)});
|
||||||
|
|
||||||
// Invalid version strings should be rejected.
|
// Invalid version strings should be rejected.
|
||||||
for ([_][]const u8{
|
for ([_][]const u8{
|
||||||
@ -269,12 +263,12 @@ test format {
|
|||||||
// Valid version string that may overflow.
|
// Valid version string that may overflow.
|
||||||
const big_valid = "99999999999999999999999.999999999999999999.99999999999999999";
|
const big_valid = "99999999999999999999999.999999999999999999.99999999999999999";
|
||||||
if (parse(big_valid)) |ver| {
|
if (parse(big_valid)) |ver| {
|
||||||
try std.testing.expectFmt(big_valid, "{}", .{ver});
|
try std.testing.expectFmt(big_valid, "{f}", .{ver});
|
||||||
} else |err| try expect(err == error.Overflow);
|
} else |err| try expect(err == error.Overflow);
|
||||||
|
|
||||||
// Invalid version string that may overflow.
|
// Invalid version string that may overflow.
|
||||||
const big_invalid = "99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..12";
|
const big_invalid = "99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..12";
|
||||||
if (parse(big_invalid)) |ver| std.debug.panic("expected error, found {}", .{ver}) else |_| {}
|
if (parse(big_invalid)) |ver| std.debug.panic("expected error, found {f}", .{ver}) else |_| {}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "precedence" {
|
test "precedence" {
|
||||||
|
|||||||
@ -301,29 +301,24 @@ pub const Os = struct {
|
|||||||
|
|
||||||
/// This function is defined to serialize a Zig source code representation of this
|
/// This function is defined to serialize a Zig source code representation of this
|
||||||
/// type, that, when parsed, will deserialize into the same data.
|
/// type, that, when parsed, will deserialize into the same data.
|
||||||
pub fn format(
|
pub fn format(ver: WindowsVersion, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
|
||||||
ver: WindowsVersion,
|
|
||||||
comptime fmt_str: []const u8,
|
|
||||||
_: std.fmt.FormatOptions,
|
|
||||||
writer: anytype,
|
|
||||||
) @TypeOf(writer).Error!void {
|
|
||||||
const maybe_name = std.enums.tagName(WindowsVersion, ver);
|
const maybe_name = std.enums.tagName(WindowsVersion, ver);
|
||||||
if (comptime std.mem.eql(u8, fmt_str, "s")) {
|
if (comptime std.mem.eql(u8, f, "s")) {
|
||||||
if (maybe_name) |name|
|
if (maybe_name) |name|
|
||||||
try writer.print(".{s}", .{name})
|
try w.print(".{s}", .{name})
|
||||||
else
|
else
|
||||||
try writer.print(".{d}", .{@intFromEnum(ver)});
|
try w.print(".{d}", .{@intFromEnum(ver)});
|
||||||
} else if (comptime std.mem.eql(u8, fmt_str, "c")) {
|
} else if (comptime std.mem.eql(u8, f, "c")) {
|
||||||
if (maybe_name) |name|
|
if (maybe_name) |name|
|
||||||
try writer.print(".{s}", .{name})
|
try w.print(".{s}", .{name})
|
||||||
else
|
else
|
||||||
try writer.print("@enumFromInt(0x{X:0>8})", .{@intFromEnum(ver)});
|
try w.print("@enumFromInt(0x{X:0>8})", .{@intFromEnum(ver)});
|
||||||
} else if (fmt_str.len == 0) {
|
} else if (f.len == 0) {
|
||||||
if (maybe_name) |name|
|
if (maybe_name) |name|
|
||||||
try writer.print("WindowsVersion.{s}", .{name})
|
try w.print("WindowsVersion.{s}", .{name})
|
||||||
else
|
else
|
||||||
try writer.print("WindowsVersion(0x{X:0>8})", .{@intFromEnum(ver)});
|
try w.print("WindowsVersion(0x{X:0>8})", .{@intFromEnum(ver)});
|
||||||
} else std.fmt.invalidFmtError(fmt_str, ver);
|
} else std.fmt.invalidFmtError(f, ver);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -394,25 +394,24 @@ pub fn canDetectLibC(self: Query) bool {
|
|||||||
|
|
||||||
/// Formats a version with the patch component omitted if it is zero,
|
/// Formats a version with the patch component omitted if it is zero,
|
||||||
/// unlike SemanticVersion.format which formats all its version components regardless.
|
/// unlike SemanticVersion.format which formats all its version components regardless.
|
||||||
fn formatVersion(version: SemanticVersion, writer: anytype) !void {
|
fn formatVersion(version: SemanticVersion, gpa: Allocator, list: *std.ArrayListUnmanaged(u8)) !void {
|
||||||
if (version.patch == 0) {
|
if (version.patch == 0) {
|
||||||
try writer.print("{d}.{d}", .{ version.major, version.minor });
|
try list.print(gpa, "{d}.{d}", .{ version.major, version.minor });
|
||||||
} else {
|
} else {
|
||||||
try writer.print("{d}.{d}.{d}", .{ version.major, version.minor, version.patch });
|
try list.print(gpa, "{d}.{d}.{d}", .{ version.major, version.minor, version.patch });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {
|
pub fn zigTriple(self: Query, gpa: Allocator) Allocator.Error![]u8 {
|
||||||
if (self.isNativeTriple())
|
if (self.isNativeTriple()) return gpa.dupe(u8, "native");
|
||||||
return allocator.dupe(u8, "native");
|
|
||||||
|
|
||||||
const arch_name = if (self.cpu_arch) |arch| @tagName(arch) else "native";
|
const arch_name = if (self.cpu_arch) |arch| @tagName(arch) else "native";
|
||||||
const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native";
|
const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native";
|
||||||
|
|
||||||
var result = std.ArrayList(u8).init(allocator);
|
var result: std.ArrayListUnmanaged(u8) = .empty;
|
||||||
defer result.deinit();
|
defer result.deinit(gpa);
|
||||||
|
|
||||||
try result.writer().print("{s}-{s}", .{ arch_name, os_name });
|
try result.print(gpa, "{s}-{s}", .{ arch_name, os_name });
|
||||||
|
|
||||||
// The zig target syntax does not allow specifying a max os version with no min, so
|
// The zig target syntax does not allow specifying a max os version with no min, so
|
||||||
// if either are present, we need the min.
|
// if either are present, we need the min.
|
||||||
@ -420,11 +419,11 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {
|
|||||||
switch (min) {
|
switch (min) {
|
||||||
.none => {},
|
.none => {},
|
||||||
.semver => |v| {
|
.semver => |v| {
|
||||||
try result.writer().writeAll(".");
|
try result.appendSlice(gpa, ".");
|
||||||
try formatVersion(v, result.writer());
|
try formatVersion(v, gpa, &result);
|
||||||
},
|
},
|
||||||
.windows => |v| {
|
.windows => |v| {
|
||||||
try result.writer().print("{s}", .{v});
|
try result.print(gpa, "{d}", .{v});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -432,39 +431,39 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {
|
|||||||
switch (max) {
|
switch (max) {
|
||||||
.none => {},
|
.none => {},
|
||||||
.semver => |v| {
|
.semver => |v| {
|
||||||
try result.writer().writeAll("...");
|
try result.appendSlice(gpa, "...");
|
||||||
try formatVersion(v, result.writer());
|
try formatVersion(v, gpa, &result);
|
||||||
},
|
},
|
||||||
.windows => |v| {
|
.windows => |v| {
|
||||||
// This is counting on a custom format() function defined on `WindowsVersion`
|
// This is counting on a custom format() function defined on `WindowsVersion`
|
||||||
// to add a prefix '.' and make there be a total of three dots.
|
// to add a prefix '.' and make there be a total of three dots.
|
||||||
try result.writer().print("..{s}", .{v});
|
try result.print(gpa, "..{d}", .{v});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.glibc_version) |v| {
|
if (self.glibc_version) |v| {
|
||||||
const name = if (self.abi) |abi| @tagName(abi) else "gnu";
|
const name = if (self.abi) |abi| @tagName(abi) else "gnu";
|
||||||
try result.ensureUnusedCapacity(name.len + 2);
|
try result.ensureUnusedCapacity(gpa, name.len + 2);
|
||||||
result.appendAssumeCapacity('-');
|
result.appendAssumeCapacity('-');
|
||||||
result.appendSliceAssumeCapacity(name);
|
result.appendSliceAssumeCapacity(name);
|
||||||
result.appendAssumeCapacity('.');
|
result.appendAssumeCapacity('.');
|
||||||
try formatVersion(v, result.writer());
|
try formatVersion(v, gpa, &result);
|
||||||
} else if (self.android_api_level) |lvl| {
|
} else if (self.android_api_level) |lvl| {
|
||||||
const name = if (self.abi) |abi| @tagName(abi) else "android";
|
const name = if (self.abi) |abi| @tagName(abi) else "android";
|
||||||
try result.ensureUnusedCapacity(name.len + 2);
|
try result.ensureUnusedCapacity(gpa, name.len + 2);
|
||||||
result.appendAssumeCapacity('-');
|
result.appendAssumeCapacity('-');
|
||||||
result.appendSliceAssumeCapacity(name);
|
result.appendSliceAssumeCapacity(name);
|
||||||
result.appendAssumeCapacity('.');
|
result.appendAssumeCapacity('.');
|
||||||
try result.writer().print("{d}", .{lvl});
|
try result.print(gpa, "{d}", .{lvl});
|
||||||
} else if (self.abi) |abi| {
|
} else if (self.abi) |abi| {
|
||||||
const name = @tagName(abi);
|
const name = @tagName(abi);
|
||||||
try result.ensureUnusedCapacity(name.len + 1);
|
try result.ensureUnusedCapacity(gpa, name.len + 1);
|
||||||
result.appendAssumeCapacity('-');
|
result.appendAssumeCapacity('-');
|
||||||
result.appendSliceAssumeCapacity(name);
|
result.appendSliceAssumeCapacity(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.toOwnedSlice();
|
return result.toOwnedSlice(gpa);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renders the query into a textual representation that can be parsed via the
|
/// Renders the query into a textual representation that can be parsed via the
|
||||||
|
|||||||
@ -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 });
|
const file = try std.fs.cwd().openFile(path, .{ .mode = .write_only });
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
try file.writer().writeAll(name);
|
try file.deprecatedWriter().writeAll(name);
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
.windows => {
|
.windows => {
|
||||||
@ -281,7 +281,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co
|
|||||||
const file = try std.fs.cwd().openFile(path, .{});
|
const file = try std.fs.cwd().openFile(path, .{});
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
const data_len = try file.reader().readAll(buffer_ptr[0 .. max_name_len + 1]);
|
const data_len = try file.deprecatedReader().readAll(buffer_ptr[0 .. max_name_len + 1]);
|
||||||
|
|
||||||
return if (data_len >= 1) buffer[0 .. data_len - 1] else null;
|
return if (data_len >= 1) buffer[0 .. data_len - 1] else null;
|
||||||
},
|
},
|
||||||
@ -1163,7 +1163,7 @@ const LinuxThreadImpl = struct {
|
|||||||
|
|
||||||
fn getCurrentId() Id {
|
fn getCurrentId() Id {
|
||||||
return tls_thread_id orelse {
|
return tls_thread_id orelse {
|
||||||
const tid = @as(u32, @bitCast(linux.gettid()));
|
const tid: u32 = @bitCast(linux.gettid());
|
||||||
tls_thread_id = tid;
|
tls_thread_id = tid;
|
||||||
return tid;
|
return tid;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -34,27 +34,22 @@ pub const Component = union(enum) {
|
|||||||
return switch (component) {
|
return switch (component) {
|
||||||
.raw => |raw| raw,
|
.raw => |raw| raw,
|
||||||
.percent_encoded => |percent_encoded| if (std.mem.indexOfScalar(u8, percent_encoded, '%')) |_|
|
.percent_encoded => |percent_encoded| if (std.mem.indexOfScalar(u8, percent_encoded, '%')) |_|
|
||||||
try std.fmt.allocPrint(arena, "{raw}", .{component})
|
try std.fmt.allocPrint(arena, "{fraw}", .{component})
|
||||||
else
|
else
|
||||||
percent_encoded,
|
percent_encoded,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(
|
pub fn format(component: Component, w: *std.io.Writer, comptime fmt_str: []const u8) std.io.Writer.Error!void {
|
||||||
component: Component,
|
|
||||||
comptime fmt_str: []const u8,
|
|
||||||
_: std.fmt.FormatOptions,
|
|
||||||
writer: anytype,
|
|
||||||
) @TypeOf(writer).Error!void {
|
|
||||||
if (fmt_str.len == 0) {
|
if (fmt_str.len == 0) {
|
||||||
try writer.print("std.Uri.Component{{ .{s} = \"{}\" }}", .{
|
try w.print("std.Uri.Component{{ .{s} = \"{f}\" }}", .{
|
||||||
@tagName(component),
|
@tagName(component),
|
||||||
std.zig.fmtEscapes(switch (component) {
|
std.zig.fmtString(switch (component) {
|
||||||
.raw, .percent_encoded => |string| string,
|
.raw, .percent_encoded => |string| string,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
} else if (comptime std.mem.eql(u8, fmt_str, "raw")) switch (component) {
|
} else if (comptime std.mem.eql(u8, fmt_str, "raw")) switch (component) {
|
||||||
.raw => |raw| try writer.writeAll(raw),
|
.raw => |raw| try w.writeAll(raw),
|
||||||
.percent_encoded => |percent_encoded| {
|
.percent_encoded => |percent_encoded| {
|
||||||
var start: usize = 0;
|
var start: usize = 0;
|
||||||
var index: usize = 0;
|
var index: usize = 0;
|
||||||
@ -63,51 +58,47 @@ pub const Component = union(enum) {
|
|||||||
if (percent_encoded.len - index < 2) continue;
|
if (percent_encoded.len - index < 2) continue;
|
||||||
const percent_encoded_char =
|
const percent_encoded_char =
|
||||||
std.fmt.parseInt(u8, percent_encoded[index..][0..2], 16) catch continue;
|
std.fmt.parseInt(u8, percent_encoded[index..][0..2], 16) catch continue;
|
||||||
try writer.print("{s}{c}", .{
|
try w.print("{s}{c}", .{
|
||||||
percent_encoded[start..percent],
|
percent_encoded[start..percent],
|
||||||
percent_encoded_char,
|
percent_encoded_char,
|
||||||
});
|
});
|
||||||
start = percent + 3;
|
start = percent + 3;
|
||||||
index = percent + 3;
|
index = percent + 3;
|
||||||
}
|
}
|
||||||
try writer.writeAll(percent_encoded[start..]);
|
try w.writeAll(percent_encoded[start..]);
|
||||||
},
|
},
|
||||||
} else if (comptime std.mem.eql(u8, fmt_str, "%")) switch (component) {
|
} else if (comptime std.mem.eql(u8, fmt_str, "%")) switch (component) {
|
||||||
.raw => |raw| try percentEncode(writer, raw, isUnreserved),
|
.raw => |raw| try percentEncode(w, raw, isUnreserved),
|
||||||
.percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
|
.percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
|
||||||
} else if (comptime std.mem.eql(u8, fmt_str, "user")) switch (component) {
|
} else if (comptime std.mem.eql(u8, fmt_str, "user")) switch (component) {
|
||||||
.raw => |raw| try percentEncode(writer, raw, isUserChar),
|
.raw => |raw| try percentEncode(w, raw, isUserChar),
|
||||||
.percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
|
.percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
|
||||||
} else if (comptime std.mem.eql(u8, fmt_str, "password")) switch (component) {
|
} else if (comptime std.mem.eql(u8, fmt_str, "password")) switch (component) {
|
||||||
.raw => |raw| try percentEncode(writer, raw, isPasswordChar),
|
.raw => |raw| try percentEncode(w, raw, isPasswordChar),
|
||||||
.percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
|
.percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
|
||||||
} else if (comptime std.mem.eql(u8, fmt_str, "host")) switch (component) {
|
} else if (comptime std.mem.eql(u8, fmt_str, "host")) switch (component) {
|
||||||
.raw => |raw| try percentEncode(writer, raw, isHostChar),
|
.raw => |raw| try percentEncode(w, raw, isHostChar),
|
||||||
.percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
|
.percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
|
||||||
} else if (comptime std.mem.eql(u8, fmt_str, "path")) switch (component) {
|
} else if (comptime std.mem.eql(u8, fmt_str, "path")) switch (component) {
|
||||||
.raw => |raw| try percentEncode(writer, raw, isPathChar),
|
.raw => |raw| try percentEncode(w, raw, isPathChar),
|
||||||
.percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
|
.percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
|
||||||
} else if (comptime std.mem.eql(u8, fmt_str, "query")) switch (component) {
|
} else if (comptime std.mem.eql(u8, fmt_str, "query")) switch (component) {
|
||||||
.raw => |raw| try percentEncode(writer, raw, isQueryChar),
|
.raw => |raw| try percentEncode(w, raw, isQueryChar),
|
||||||
.percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
|
.percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
|
||||||
} else if (comptime std.mem.eql(u8, fmt_str, "fragment")) switch (component) {
|
} else if (comptime std.mem.eql(u8, fmt_str, "fragment")) switch (component) {
|
||||||
.raw => |raw| try percentEncode(writer, raw, isFragmentChar),
|
.raw => |raw| try percentEncode(w, raw, isFragmentChar),
|
||||||
.percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
|
.percent_encoded => |percent_encoded| try w.writeAll(percent_encoded),
|
||||||
} else @compileError("invalid format string '" ++ fmt_str ++ "'");
|
} else @compileError("invalid format string '" ++ fmt_str ++ "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn percentEncode(
|
pub fn percentEncode(w: *std.io.Writer, raw: []const u8, comptime isValidChar: fn (u8) bool) std.io.Writer.Error!void {
|
||||||
writer: anytype,
|
|
||||||
raw: []const u8,
|
|
||||||
comptime isValidChar: fn (u8) bool,
|
|
||||||
) @TypeOf(writer).Error!void {
|
|
||||||
var start: usize = 0;
|
var start: usize = 0;
|
||||||
for (raw, 0..) |char, index| {
|
for (raw, 0..) |char, index| {
|
||||||
if (isValidChar(char)) continue;
|
if (isValidChar(char)) continue;
|
||||||
try writer.print("{s}%{X:0>2}", .{ raw[start..index], char });
|
try w.print("{s}%{X:0>2}", .{ raw[start..index], char });
|
||||||
start = index + 1;
|
start = index + 1;
|
||||||
}
|
}
|
||||||
try writer.writeAll(raw[start..]);
|
try w.writeAll(raw[start..]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -247,11 +238,7 @@ pub const WriteToStreamOptions = struct {
|
|||||||
port: bool = true,
|
port: bool = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn writeToStream(
|
pub fn writeToStream(uri: Uri, writer: *std.io.Writer, options: WriteToStreamOptions) std.io.Writer.Error!void {
|
||||||
uri: Uri,
|
|
||||||
options: WriteToStreamOptions,
|
|
||||||
writer: anytype,
|
|
||||||
) @TypeOf(writer).Error!void {
|
|
||||||
if (options.scheme) {
|
if (options.scheme) {
|
||||||
try writer.print("{s}:", .{uri.scheme});
|
try writer.print("{s}:", .{uri.scheme});
|
||||||
if (options.authority and uri.host != null) {
|
if (options.authority and uri.host != null) {
|
||||||
@ -261,39 +248,34 @@ pub fn writeToStream(
|
|||||||
if (options.authority) {
|
if (options.authority) {
|
||||||
if (options.authentication and uri.host != null) {
|
if (options.authentication and uri.host != null) {
|
||||||
if (uri.user) |user| {
|
if (uri.user) |user| {
|
||||||
try writer.print("{user}", .{user});
|
try writer.print("{fuser}", .{user});
|
||||||
if (uri.password) |password| {
|
if (uri.password) |password| {
|
||||||
try writer.print(":{password}", .{password});
|
try writer.print(":{fpassword}", .{password});
|
||||||
}
|
}
|
||||||
try writer.writeByte('@');
|
try writer.writeByte('@');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uri.host) |host| {
|
if (uri.host) |host| {
|
||||||
try writer.print("{host}", .{host});
|
try writer.print("{fhost}", .{host});
|
||||||
if (options.port) {
|
if (options.port) {
|
||||||
if (uri.port) |port| try writer.print(":{d}", .{port});
|
if (uri.port) |port| try writer.print(":{d}", .{port});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (options.path) {
|
if (options.path) {
|
||||||
try writer.print("{path}", .{
|
try writer.print("{fpath}", .{
|
||||||
if (uri.path.isEmpty()) Uri.Component{ .percent_encoded = "/" } else uri.path,
|
if (uri.path.isEmpty()) Uri.Component{ .percent_encoded = "/" } else uri.path,
|
||||||
});
|
});
|
||||||
if (options.query) {
|
if (options.query) {
|
||||||
if (uri.query) |query| try writer.print("?{query}", .{query});
|
if (uri.query) |query| try writer.print("?{fquery}", .{query});
|
||||||
}
|
}
|
||||||
if (options.fragment) {
|
if (options.fragment) {
|
||||||
if (uri.fragment) |fragment| try writer.print("#{fragment}", .{fragment});
|
if (uri.fragment) |fragment| try writer.print("#{ffragment}", .{fragment});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(
|
pub fn format(uri: Uri, writer: *std.io.Writer, comptime fmt_str: []const u8) std.io.Writer.Error!void {
|
||||||
uri: Uri,
|
|
||||||
comptime fmt_str: []const u8,
|
|
||||||
_: std.fmt.FormatOptions,
|
|
||||||
writer: anytype,
|
|
||||||
) @TypeOf(writer).Error!void {
|
|
||||||
const scheme = comptime std.mem.indexOfScalar(u8, fmt_str, ';') != null or fmt_str.len == 0;
|
const scheme = comptime std.mem.indexOfScalar(u8, fmt_str, ';') != null or fmt_str.len == 0;
|
||||||
const authentication = comptime std.mem.indexOfScalar(u8, fmt_str, '@') != null or fmt_str.len == 0;
|
const authentication = comptime std.mem.indexOfScalar(u8, fmt_str, '@') != null or fmt_str.len == 0;
|
||||||
const authority = comptime std.mem.indexOfScalar(u8, fmt_str, '+') != null or fmt_str.len == 0;
|
const authority = comptime std.mem.indexOfScalar(u8, fmt_str, '+') != null or fmt_str.len == 0;
|
||||||
@ -301,14 +283,14 @@ pub fn format(
|
|||||||
const query = comptime std.mem.indexOfScalar(u8, fmt_str, '?') != null or fmt_str.len == 0;
|
const query = comptime std.mem.indexOfScalar(u8, fmt_str, '?') != null or fmt_str.len == 0;
|
||||||
const fragment = comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null or fmt_str.len == 0;
|
const fragment = comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null or fmt_str.len == 0;
|
||||||
|
|
||||||
return writeToStream(uri, .{
|
return writeToStream(uri, writer, .{
|
||||||
.scheme = scheme,
|
.scheme = scheme,
|
||||||
.authentication = authentication,
|
.authentication = authentication,
|
||||||
.authority = authority,
|
.authority = authority,
|
||||||
.path = path,
|
.path = path,
|
||||||
.query = query,
|
.query = query,
|
||||||
.fragment = fragment,
|
.fragment = fragment,
|
||||||
}, writer);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the URI or returns an error.
|
/// Parses the URI or returns an error.
|
||||||
@ -447,7 +429,7 @@ test remove_dot_segments {
|
|||||||
fn merge_paths(base: Component, new: []u8, aux_buf: *[]u8) error{NoSpaceLeft}!Component {
|
fn merge_paths(base: Component, new: []u8, aux_buf: *[]u8) error{NoSpaceLeft}!Component {
|
||||||
var aux = std.io.fixedBufferStream(aux_buf.*);
|
var aux = std.io.fixedBufferStream(aux_buf.*);
|
||||||
if (!base.isEmpty()) {
|
if (!base.isEmpty()) {
|
||||||
try aux.writer().print("{path}", .{base});
|
try aux.writer().print("{fpath}", .{base});
|
||||||
aux.pos = std.mem.lastIndexOfScalar(u8, aux.getWritten(), '/') orelse
|
aux.pos = std.mem.lastIndexOfScalar(u8, aux.getWritten(), '/') orelse
|
||||||
return remove_dot_segments(new);
|
return remove_dot_segments(new);
|
||||||
}
|
}
|
||||||
@ -812,7 +794,7 @@ test "Special test" {
|
|||||||
test "URI percent encoding" {
|
test "URI percent encoding" {
|
||||||
try std.testing.expectFmt(
|
try std.testing.expectFmt(
|
||||||
"%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad",
|
"%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad",
|
||||||
"{%}",
|
"{f%}",
|
||||||
.{Component{ .raw = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad" }},
|
.{Component{ .raw = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad" }},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -822,7 +804,7 @@ test "URI percent decoding" {
|
|||||||
const expected = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad";
|
const expected = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad";
|
||||||
var input = "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad".*;
|
var input = "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad".*;
|
||||||
|
|
||||||
try std.testing.expectFmt(expected, "{raw}", .{Component{ .percent_encoded = &input }});
|
try std.testing.expectFmt(expected, "{fraw}", .{Component{ .percent_encoded = &input }});
|
||||||
|
|
||||||
var output: [expected.len]u8 = undefined;
|
var output: [expected.len]u8 = undefined;
|
||||||
try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected);
|
try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected);
|
||||||
@ -834,7 +816,7 @@ test "URI percent decoding" {
|
|||||||
const expected = "/abc%";
|
const expected = "/abc%";
|
||||||
var input = expected.*;
|
var input = expected.*;
|
||||||
|
|
||||||
try std.testing.expectFmt(expected, "{raw}", .{Component{ .percent_encoded = &input }});
|
try std.testing.expectFmt(expected, "{fraw}", .{Component{ .percent_encoded = &input }});
|
||||||
|
|
||||||
var output: [expected.len]u8 = undefined;
|
var output: [expected.len]u8 = undefined;
|
||||||
try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected);
|
try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected);
|
||||||
@ -848,7 +830,7 @@ test "URI query encoding" {
|
|||||||
const parsed = try Uri.parse(address);
|
const parsed = try Uri.parse(address);
|
||||||
|
|
||||||
// format the URI to percent encode it
|
// format the URI to percent encode it
|
||||||
try std.testing.expectFmt("/?response-content-type=application%2Foctet-stream", "{/?}", .{parsed});
|
try std.testing.expectFmt("/?response-content-type=application%2Foctet-stream", "{f/?}", .{parsed});
|
||||||
}
|
}
|
||||||
|
|
||||||
test "format" {
|
test "format" {
|
||||||
@ -862,7 +844,7 @@ test "format" {
|
|||||||
.query = null,
|
.query = null,
|
||||||
.fragment = null,
|
.fragment = null,
|
||||||
};
|
};
|
||||||
try std.testing.expectFmt("file:/foo/bar/baz", "{;/?#}", .{uri});
|
try std.testing.expectFmt("file:/foo/bar/baz", "{f;/?#}", .{uri});
|
||||||
}
|
}
|
||||||
|
|
||||||
test "URI malformed input" {
|
test "URI malformed input" {
|
||||||
|
|||||||
@ -435,3 +435,44 @@ pub fn orderIgnoreCase(lhs: []const u8, rhs: []const u8) std.math.Order {
|
|||||||
pub fn lessThanIgnoreCase(lhs: []const u8, rhs: []const u8) bool {
|
pub fn lessThanIgnoreCase(lhs: []const u8, rhs: []const u8) bool {
|
||||||
return orderIgnoreCase(lhs, rhs) == .lt;
|
return orderIgnoreCase(lhs, rhs) == .lt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const HexEscape = struct {
|
||||||
|
bytes: []const u8,
|
||||||
|
charset: *const [16]u8,
|
||||||
|
|
||||||
|
pub const upper_charset = "0123456789ABCDEF";
|
||||||
|
pub const lower_charset = "0123456789abcdef";
|
||||||
|
|
||||||
|
pub fn format(se: HexEscape, w: *std.io.Writer) std.io.Writer.Error!void {
|
||||||
|
const charset = se.charset;
|
||||||
|
|
||||||
|
var buf: [4]u8 = undefined;
|
||||||
|
buf[0] = '\\';
|
||||||
|
buf[1] = 'x';
|
||||||
|
|
||||||
|
for (se.bytes) |c| {
|
||||||
|
if (std.ascii.isPrint(c)) {
|
||||||
|
try w.writeByte(c);
|
||||||
|
} else {
|
||||||
|
buf[2] = charset[c >> 4];
|
||||||
|
buf[3] = charset[c & 15];
|
||||||
|
try w.writeAll(&buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Replaces non-ASCII bytes with hex escapes.
|
||||||
|
pub fn hexEscape(bytes: []const u8, case: std.fmt.Case) std.fmt.Formatter(HexEscape, HexEscape.format) {
|
||||||
|
return .{ .data = .{ .bytes = bytes, .charset = switch (case) {
|
||||||
|
.lower => HexEscape.lower_charset,
|
||||||
|
.upper => HexEscape.upper_charset,
|
||||||
|
} } };
|
||||||
|
}
|
||||||
|
|
||||||
|
test hexEscape {
|
||||||
|
try std.testing.expectFmt("abc 123", "{f}", .{hexEscape("abc 123", .lower)});
|
||||||
|
try std.testing.expectFmt("ab\\xffc", "{f}", .{hexEscape("ab\xffc", .lower)});
|
||||||
|
try std.testing.expectFmt("abc 123", "{f}", .{hexEscape("abc 123", .upper)});
|
||||||
|
try std.testing.expectFmt("ab\\xFFc", "{f}", .{hexEscape("ab\xffc", .upper)});
|
||||||
|
}
|
||||||
|
|||||||
@ -34,20 +34,14 @@ pub const StackTrace = struct {
|
|||||||
index: usize,
|
index: usize,
|
||||||
instruction_addresses: []usize,
|
instruction_addresses: []usize,
|
||||||
|
|
||||||
pub fn format(
|
pub fn format(self: StackTrace, writer: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
|
||||||
self: StackTrace,
|
if (fmt.len != 0) unreachable;
|
||||||
comptime fmt: []const u8,
|
|
||||||
options: std.fmt.FormatOptions,
|
|
||||||
writer: anytype,
|
|
||||||
) !void {
|
|
||||||
if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
|
|
||||||
|
|
||||||
// TODO: re-evaluate whether to use format() methods at all.
|
// TODO: re-evaluate whether to use format() methods at all.
|
||||||
// Until then, avoid an error when using GeneralPurposeAllocator with WebAssembly
|
// Until then, avoid an error when using GeneralPurposeAllocator with WebAssembly
|
||||||
// where it tries to call detectTTYConfig here.
|
// where it tries to call detectTTYConfig here.
|
||||||
if (builtin.os.tag == .freestanding) return;
|
if (builtin.os.tag == .freestanding) return;
|
||||||
|
|
||||||
_ = options;
|
|
||||||
const debug_info = std.debug.getSelfDebugInfo() catch |err| {
|
const debug_info = std.debug.getSelfDebugInfo() catch |err| {
|
||||||
return writer.print("\nUnable to print stack trace: Unable to open debug info: {s}\n", .{@errorName(err)});
|
return writer.print("\nUnable to print stack trace: Unable to open debug info: {s}\n", .{@errorName(err)});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -124,9 +124,9 @@ test "curve25519" {
|
|||||||
const p = try Curve25519.basePoint.clampedMul(s);
|
const p = try Curve25519.basePoint.clampedMul(s);
|
||||||
try p.rejectIdentity();
|
try p.rejectIdentity();
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&p.toBytes())}), "E6F2A4D1C28EE5C7AD0329268255A468AD407D2672824C0C0EB30EA6EF450145");
|
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&p.toBytes()}), "E6F2A4D1C28EE5C7AD0329268255A468AD407D2672824C0C0EB30EA6EF450145");
|
||||||
const q = try p.clampedMul(s);
|
const q = try p.clampedMul(s);
|
||||||
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&q.toBytes())}), "3614E119FFE55EC55B87D6B19971A9F4CBC78EFE80BEC55B96392BABCC712537");
|
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&q.toBytes()}), "3614E119FFE55EC55B87D6B19971A9F4CBC78EFE80BEC55B96392BABCC712537");
|
||||||
|
|
||||||
try Curve25519.rejectNonCanonical(s);
|
try Curve25519.rejectNonCanonical(s);
|
||||||
s[31] |= 0x80;
|
s[31] |= 0x80;
|
||||||
|
|||||||
@ -509,8 +509,8 @@ test "key pair creation" {
|
|||||||
_ = try fmt.hexToBytes(seed[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");
|
_ = try fmt.hexToBytes(seed[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");
|
||||||
const key_pair = try Ed25519.KeyPair.generateDeterministic(seed);
|
const key_pair = try Ed25519.KeyPair.generateDeterministic(seed);
|
||||||
var buf: [256]u8 = undefined;
|
var buf: [256]u8 = undefined;
|
||||||
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&key_pair.secret_key.toBytes())}), "8052030376D47112BE7F73ED7A019293DD12AD910B654455798B4667D73DE1662D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083");
|
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&key_pair.secret_key.toBytes()}), "8052030376D47112BE7F73ED7A019293DD12AD910B654455798B4667D73DE1662D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083");
|
||||||
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&key_pair.public_key.toBytes())}), "2D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083");
|
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&key_pair.public_key.toBytes()}), "2D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083");
|
||||||
}
|
}
|
||||||
|
|
||||||
test "signature" {
|
test "signature" {
|
||||||
@ -520,7 +520,7 @@ test "signature" {
|
|||||||
|
|
||||||
const sig = try key_pair.sign("test", null);
|
const sig = try key_pair.sign("test", null);
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&sig.toBytes())}), "10A442B4A80CC4225B154F43BEF28D2472CA80221951262EB8E0DF9091575E2687CC486E77263C3418C757522D54F84B0359236ABBBD4ACD20DC297FDCA66808");
|
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&sig.toBytes()}), "10A442B4A80CC4225B154F43BEF28D2472CA80221951262EB8E0DF9091575E2687CC486E77263C3418C757522D54F84B0359236ABBBD4ACD20DC297FDCA66808");
|
||||||
try sig.verify("test", key_pair.public_key);
|
try sig.verify("test", key_pair.public_key);
|
||||||
try std.testing.expectError(error.SignatureVerificationFailed, sig.verify("TEST", key_pair.public_key));
|
try std.testing.expectError(error.SignatureVerificationFailed, sig.verify("TEST", key_pair.public_key));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -546,7 +546,7 @@ test "packing/unpacking" {
|
|||||||
var b = Edwards25519.basePoint;
|
var b = Edwards25519.basePoint;
|
||||||
const pk = try b.mul(s);
|
const pk = try b.mul(s);
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&pk.toBytes())}), "074BC7E0FCBD587FDBC0969444245FADC562809C8F6E97E949AF62484B5B81A6");
|
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&pk.toBytes()}), "074BC7E0FCBD587FDBC0969444245FADC562809C8F6E97E949AF62484B5B81A6");
|
||||||
|
|
||||||
const small_order_ss: [7][32]u8 = .{
|
const small_order_ss: [7][32]u8 = .{
|
||||||
.{
|
.{
|
||||||
|
|||||||
@ -175,21 +175,21 @@ pub const Ristretto255 = struct {
|
|||||||
test "ristretto255" {
|
test "ristretto255" {
|
||||||
const p = Ristretto255.basePoint;
|
const p = Ristretto255.basePoint;
|
||||||
var buf: [256]u8 = undefined;
|
var buf: [256]u8 = undefined;
|
||||||
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&p.toBytes())}), "E2F2AE0A6ABC4E71A884A961C500515F58E30B6AA582DD8DB6A65945E08D2D76");
|
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&p.toBytes()}), "E2F2AE0A6ABC4E71A884A961C500515F58E30B6AA582DD8DB6A65945E08D2D76");
|
||||||
|
|
||||||
var r: [Ristretto255.encoded_length]u8 = undefined;
|
var r: [Ristretto255.encoded_length]u8 = undefined;
|
||||||
_ = try fmt.hexToBytes(r[0..], "6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919");
|
_ = try fmt.hexToBytes(r[0..], "6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919");
|
||||||
var q = try Ristretto255.fromBytes(r);
|
var q = try Ristretto255.fromBytes(r);
|
||||||
q = q.dbl().add(p);
|
q = q.dbl().add(p);
|
||||||
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&q.toBytes())}), "E882B131016B52C1D3337080187CF768423EFCCBB517BB495AB812C4160FF44E");
|
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&q.toBytes()}), "E882B131016B52C1D3337080187CF768423EFCCBB517BB495AB812C4160FF44E");
|
||||||
|
|
||||||
const s = [_]u8{15} ++ [_]u8{0} ** 31;
|
const s = [_]u8{15} ++ [_]u8{0} ** 31;
|
||||||
const w = try p.mul(s);
|
const w = try p.mul(s);
|
||||||
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&w.toBytes())}), "E0C418F7C8D9C4CDD7395B93EA124F3AD99021BB681DFC3302A9D99A2E53E64E");
|
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&w.toBytes()}), "E0C418F7C8D9C4CDD7395B93EA124F3AD99021BB681DFC3302A9D99A2E53E64E");
|
||||||
|
|
||||||
try std.testing.expect(p.dbl().dbl().dbl().dbl().equivalent(w.add(p)));
|
try std.testing.expect(p.dbl().dbl().dbl().dbl().equivalent(w.add(p)));
|
||||||
|
|
||||||
const h = [_]u8{69} ** 32 ++ [_]u8{42} ** 32;
|
const h = [_]u8{69} ** 32 ++ [_]u8{42} ** 32;
|
||||||
const ph = Ristretto255.fromUniform(h);
|
const ph = Ristretto255.fromUniform(h);
|
||||||
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&ph.toBytes())}), "DCCA54E037A4311EFBEEF413ACD21D35276518970B7A61DC88F8587B493D5E19");
|
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&ph.toBytes()}), "DCCA54E037A4311EFBEEF413ACD21D35276518970B7A61DC88F8587B493D5E19");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -850,10 +850,10 @@ test "scalar25519" {
|
|||||||
var y = x.toBytes();
|
var y = x.toBytes();
|
||||||
try rejectNonCanonical(y);
|
try rejectNonCanonical(y);
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&y)}), "1E979B917937F3DE71D18077F961F6CEFF01030405060708010203040506070F");
|
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&y}), "1E979B917937F3DE71D18077F961F6CEFF01030405060708010203040506070F");
|
||||||
|
|
||||||
const reduced = reduce(field_order_s);
|
const reduced = reduce(field_order_s);
|
||||||
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&reduced)}), "0000000000000000000000000000000000000000000000000000000000000000");
|
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&reduced}), "0000000000000000000000000000000000000000000000000000000000000000");
|
||||||
}
|
}
|
||||||
|
|
||||||
test "non-canonical scalar25519" {
|
test "non-canonical scalar25519" {
|
||||||
@ -867,7 +867,7 @@ test "mulAdd overflow check" {
|
|||||||
const c: [32]u8 = [_]u8{0xff} ** 32;
|
const c: [32]u8 = [_]u8{0xff} ** 32;
|
||||||
const x = mulAdd(a, b, c);
|
const x = mulAdd(a, b, c);
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&x)}), "D14DF91389432C25AD60FF9791B9FD1D67BEF517D273ECCE3D9A307C1B419903");
|
try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&x}), "D14DF91389432C25AD60FF9791B9FD1D67BEF517D273ECCE3D9A307C1B419903");
|
||||||
}
|
}
|
||||||
|
|
||||||
test "scalar field inversion" {
|
test "scalar field inversion" {
|
||||||
|
|||||||
@ -458,7 +458,7 @@ fn mode(comptime x: comptime_int) comptime_int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
const stdout = std.fs.File.stdout().writer();
|
const stdout = std.fs.File.stdout().deprecatedWriter();
|
||||||
|
|
||||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
|
|||||||
@ -1145,7 +1145,7 @@ test "xchacha20" {
|
|||||||
var c: [m.len]u8 = undefined;
|
var c: [m.len]u8 = undefined;
|
||||||
XChaCha20IETF.xor(c[0..], m[0..], 0, key, nonce);
|
XChaCha20IETF.xor(c[0..], m[0..], 0, key, nonce);
|
||||||
var buf: [2 * c.len]u8 = undefined;
|
var buf: [2 * c.len]u8 = undefined;
|
||||||
try testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&c)}), "E0A1BCF939654AFDBDC1746EC49832647C19D891F0D1A81FC0C1703B4514BDEA584B512F6908C2C5E9DD18D5CBC1805DE5803FE3B9CA5F193FB8359E91FAB0C3BB40309A292EB1CF49685C65C4A3ADF4F11DB0CD2B6B67FBC174BC2E860E8F769FD3565BBFAD1C845E05A0FED9BE167C240D");
|
try testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&c}), "E0A1BCF939654AFDBDC1746EC49832647C19D891F0D1A81FC0C1703B4514BDEA584B512F6908C2C5E9DD18D5CBC1805DE5803FE3B9CA5F193FB8359E91FAB0C3BB40309A292EB1CF49685C65C4A3ADF4F11DB0CD2B6B67FBC174BC2E860E8F769FD3565BBFAD1C845E05A0FED9BE167C240D");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const ad = "Additional data";
|
const ad = "Additional data";
|
||||||
@ -1154,7 +1154,7 @@ test "xchacha20" {
|
|||||||
var out: [m.len]u8 = undefined;
|
var out: [m.len]u8 = undefined;
|
||||||
try XChaCha20Poly1305.decrypt(out[0..], c[0..m.len], c[m.len..].*, ad, nonce, key);
|
try XChaCha20Poly1305.decrypt(out[0..], c[0..m.len], c[m.len..].*, ad, nonce, key);
|
||||||
var buf: [2 * c.len]u8 = undefined;
|
var buf: [2 * c.len]u8 = undefined;
|
||||||
try testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&c)}), "994D2DD32333F48E53650C02C7A2ABB8E018B0836D7175AEC779F52E961780768F815C58F1AA52D211498DB89B9216763F569C9433A6BBFCEFB4D4A49387A4C5207FBB3B5A92B5941294DF30588C6740D39DC16FA1F0E634F7246CF7CDCB978E44347D89381B7A74EB7084F754B90BDE9AAF5A94B8F2A85EFD0B50692AE2D425E234");
|
try testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{&c}), "994D2DD32333F48E53650C02C7A2ABB8E018B0836D7175AEC779F52E961780768F815C58F1AA52D211498DB89B9216763F569C9433A6BBFCEFB4D4A49387A4C5207FBB3B5A92B5941294DF30588C6740D39DC16FA1F0E634F7246CF7CDCB978E44347D89381B7A74EB7084F754B90BDE9AAF5A94B8F2A85EFD0B50692AE2D425E234");
|
||||||
try testing.expectEqualSlices(u8, out[0..], m);
|
try testing.expectEqualSlices(u8, out[0..], m);
|
||||||
c[0] +%= 1;
|
c[0] +%= 1;
|
||||||
try testing.expectError(error.AuthenticationFailed, XChaCha20Poly1305.decrypt(out[0..], c[0..m.len], c[m.len..].*, ad, nonce, key));
|
try testing.expectError(error.AuthenticationFailed, XChaCha20Poly1305.decrypt(out[0..], c[0..m.len], c[m.len..].*, ad, nonce, key));
|
||||||
|
|||||||
@ -1737,11 +1737,11 @@ test "NIST KAT test" {
|
|||||||
var f = sha2.Sha256.init(.{});
|
var f = sha2.Sha256.init(.{});
|
||||||
const fw = f.writer();
|
const fw = f.writer();
|
||||||
var g = NistDRBG.init(seed);
|
var g = NistDRBG.init(seed);
|
||||||
try std.fmt.format(fw, "# {s}\n\n", .{mode.name});
|
try std.fmt.deprecatedFormat(fw, "# {s}\n\n", .{mode.name});
|
||||||
for (0..100) |i| {
|
for (0..100) |i| {
|
||||||
g.fill(&seed);
|
g.fill(&seed);
|
||||||
try std.fmt.format(fw, "count = {}\n", .{i});
|
try std.fmt.deprecatedFormat(fw, "count = {}\n", .{i});
|
||||||
try std.fmt.format(fw, "seed = {s}\n", .{std.fmt.fmtSliceHexUpper(&seed)});
|
try std.fmt.deprecatedFormat(fw, "seed = {X}\n", .{&seed});
|
||||||
var g2 = NistDRBG.init(seed);
|
var g2 = NistDRBG.init(seed);
|
||||||
|
|
||||||
// This is not equivalent to g2.fill(kseed[:]). As the reference
|
// This is not equivalent to g2.fill(kseed[:]). As the reference
|
||||||
@ -1756,16 +1756,16 @@ test "NIST KAT test" {
|
|||||||
const e = kp.public_key.encaps(eseed);
|
const e = kp.public_key.encaps(eseed);
|
||||||
const ss2 = try kp.secret_key.decaps(&e.ciphertext);
|
const ss2 = try kp.secret_key.decaps(&e.ciphertext);
|
||||||
try testing.expectEqual(ss2, e.shared_secret);
|
try testing.expectEqual(ss2, e.shared_secret);
|
||||||
try std.fmt.format(fw, "pk = {s}\n", .{std.fmt.fmtSliceHexUpper(&kp.public_key.toBytes())});
|
try std.fmt.deprecatedFormat(fw, "pk = {X}\n", .{&kp.public_key.toBytes()});
|
||||||
try std.fmt.format(fw, "sk = {s}\n", .{std.fmt.fmtSliceHexUpper(&kp.secret_key.toBytes())});
|
try std.fmt.deprecatedFormat(fw, "sk = {X}\n", .{&kp.secret_key.toBytes()});
|
||||||
try std.fmt.format(fw, "ct = {s}\n", .{std.fmt.fmtSliceHexUpper(&e.ciphertext)});
|
try std.fmt.deprecatedFormat(fw, "ct = {X}\n", .{&e.ciphertext});
|
||||||
try std.fmt.format(fw, "ss = {s}\n\n", .{std.fmt.fmtSliceHexUpper(&e.shared_secret)});
|
try std.fmt.deprecatedFormat(fw, "ss = {X}\n\n", .{&e.shared_secret});
|
||||||
}
|
}
|
||||||
|
|
||||||
var out: [32]u8 = undefined;
|
var out: [32]u8 = undefined;
|
||||||
f.final(&out);
|
f.final(&out);
|
||||||
var outHex: [64]u8 = undefined;
|
var outHex: [64]u8 = undefined;
|
||||||
_ = try std.fmt.bufPrint(&outHex, "{s}", .{std.fmt.fmtSliceHexLower(&out)});
|
_ = try std.fmt.bufPrint(&outHex, "{x}", .{&out});
|
||||||
try testing.expectEqual(outHex, modeHash[1].*);
|
try testing.expectEqual(outHex, modeHash[1].*);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1512,11 +1512,11 @@ fn logSecrets(key_log_file: std.fs.File, context: anytype, secrets: anytype) voi
|
|||||||
const locked = if (key_log_file.lock(.exclusive)) |_| true else |_| false;
|
const locked = if (key_log_file.lock(.exclusive)) |_| true else |_| false;
|
||||||
defer if (locked) key_log_file.unlock();
|
defer if (locked) key_log_file.unlock();
|
||||||
key_log_file.seekFromEnd(0) catch {};
|
key_log_file.seekFromEnd(0) catch {};
|
||||||
inline for (@typeInfo(@TypeOf(secrets)).@"struct".fields) |field| key_log_file.writer().print("{s}" ++
|
inline for (@typeInfo(@TypeOf(secrets)).@"struct".fields) |field| key_log_file.deprecatedWriter().print("{s}" ++
|
||||||
(if (@hasField(@TypeOf(context), "counter")) "_{d}" else "") ++ " {} {}\n", .{field.name} ++
|
(if (@hasField(@TypeOf(context), "counter")) "_{d}" else "") ++ " {x} {x}\n", .{field.name} ++
|
||||||
(if (@hasField(@TypeOf(context), "counter")) .{context.counter} else .{}) ++ .{
|
(if (@hasField(@TypeOf(context), "counter")) .{context.counter} else .{}) ++ .{
|
||||||
std.fmt.fmtSliceHexLower(context.client_random),
|
context.client_random,
|
||||||
std.fmt.fmtSliceHexLower(@field(secrets, field.name)),
|
@field(secrets, field.name),
|
||||||
}) catch {};
|
}) catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,7 @@ const windows = std.os.windows;
|
|||||||
const native_arch = builtin.cpu.arch;
|
const native_arch = builtin.cpu.arch;
|
||||||
const native_os = builtin.os.tag;
|
const native_os = builtin.os.tag;
|
||||||
const native_endian = native_arch.endian();
|
const native_endian = native_arch.endian();
|
||||||
|
const Writer = std.io.Writer;
|
||||||
|
|
||||||
pub const MemoryAccessor = @import("debug/MemoryAccessor.zig");
|
pub const MemoryAccessor = @import("debug/MemoryAccessor.zig");
|
||||||
pub const FixedBufferReader = @import("debug/FixedBufferReader.zig");
|
pub const FixedBufferReader = @import("debug/FixedBufferReader.zig");
|
||||||
@ -204,13 +205,26 @@ pub fn unlockStdErr() void {
|
|||||||
std.Progress.unlockStdErr();
|
std.Progress.unlockStdErr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Allows the caller to freely write to stderr until `unlockStdErr` is called.
|
||||||
|
///
|
||||||
|
/// During the lock, any `std.Progress` information is cleared from the terminal.
|
||||||
|
///
|
||||||
|
/// Returns a `Writer` with empty buffer, meaning that it is
|
||||||
|
/// in fact unbuffered and does not need to be flushed.
|
||||||
|
pub fn lockStderrWriter(buffer: []u8) *Writer {
|
||||||
|
return std.Progress.lockStderrWriter(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unlockStderrWriter() void {
|
||||||
|
std.Progress.unlockStderrWriter();
|
||||||
|
}
|
||||||
|
|
||||||
/// Print to stderr, unbuffered, and silently returning on failure. Intended
|
/// Print to stderr, unbuffered, and silently returning on failure. Intended
|
||||||
/// for use in "printf debugging." Use `std.log` functions for proper logging.
|
/// for use in "printf debugging". Use `std.log` functions for proper logging.
|
||||||
pub fn print(comptime fmt: []const u8, args: anytype) void {
|
pub fn print(comptime fmt: []const u8, args: anytype) void {
|
||||||
lockStdErr();
|
const bw = lockStderrWriter(&.{});
|
||||||
defer unlockStdErr();
|
defer unlockStderrWriter();
|
||||||
const stderr = fs.File.stderr().writer();
|
nosuspend bw.print(fmt, args) catch return;
|
||||||
nosuspend stderr.print(fmt, args) catch return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getStderrMutex() *std.Thread.Mutex {
|
pub fn getStderrMutex() *std.Thread.Mutex {
|
||||||
@ -232,50 +246,44 @@ pub fn getSelfDebugInfo() !*SelfInfo {
|
|||||||
/// Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned.
|
/// Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned.
|
||||||
/// Obtains the stderr mutex while dumping.
|
/// Obtains the stderr mutex while dumping.
|
||||||
pub fn dumpHex(bytes: []const u8) void {
|
pub fn dumpHex(bytes: []const u8) void {
|
||||||
lockStdErr();
|
const bw = lockStderrWriter(&.{});
|
||||||
defer unlockStdErr();
|
defer unlockStderrWriter();
|
||||||
dumpHexFallible(bytes) catch {};
|
const ttyconf = std.io.tty.detectConfig(.stderr());
|
||||||
|
dumpHexFallible(bw, ttyconf, bytes) catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prints a hexadecimal view of the bytes, unbuffered, returning any error that occurs.
|
/// Prints a hexadecimal view of the bytes, returning any error that occurs.
|
||||||
pub fn dumpHexFallible(bytes: []const u8) !void {
|
pub fn dumpHexFallible(bw: *Writer, ttyconf: std.io.tty.Config, bytes: []const u8) !void {
|
||||||
const stderr: fs.File = .stderr();
|
|
||||||
const ttyconf = std.io.tty.detectConfig(stderr);
|
|
||||||
const writer = stderr.writer();
|
|
||||||
try dumpHexInternal(bytes, ttyconf, writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dumpHexInternal(bytes: []const u8, ttyconf: std.io.tty.Config, writer: anytype) !void {
|
|
||||||
var chunks = mem.window(u8, bytes, 16, 16);
|
var chunks = mem.window(u8, bytes, 16, 16);
|
||||||
while (chunks.next()) |window| {
|
while (chunks.next()) |window| {
|
||||||
// 1. Print the address.
|
// 1. Print the address.
|
||||||
const address = (@intFromPtr(bytes.ptr) + 0x10 * (std.math.divCeil(usize, chunks.index orelse bytes.len, 16) catch unreachable)) - 0x10;
|
const address = (@intFromPtr(bytes.ptr) + 0x10 * (std.math.divCeil(usize, chunks.index orelse bytes.len, 16) catch unreachable)) - 0x10;
|
||||||
try ttyconf.setColor(writer, .dim);
|
try ttyconf.setColor(bw, .dim);
|
||||||
// We print the address in lowercase and the bytes in uppercase hexadecimal to distinguish them more.
|
// We print the address in lowercase and the bytes in uppercase hexadecimal to distinguish them more.
|
||||||
// Also, make sure all lines are aligned by padding the address.
|
// Also, make sure all lines are aligned by padding the address.
|
||||||
try writer.print("{x:0>[1]} ", .{ address, @sizeOf(usize) * 2 });
|
try bw.print("{x:0>[1]} ", .{ address, @sizeOf(usize) * 2 });
|
||||||
try ttyconf.setColor(writer, .reset);
|
try ttyconf.setColor(bw, .reset);
|
||||||
|
|
||||||
// 2. Print the bytes.
|
// 2. Print the bytes.
|
||||||
for (window, 0..) |byte, index| {
|
for (window, 0..) |byte, index| {
|
||||||
try writer.print("{X:0>2} ", .{byte});
|
try bw.print("{X:0>2} ", .{byte});
|
||||||
if (index == 7) try writer.writeByte(' ');
|
if (index == 7) try bw.writeByte(' ');
|
||||||
}
|
}
|
||||||
try writer.writeByte(' ');
|
try bw.writeByte(' ');
|
||||||
if (window.len < 16) {
|
if (window.len < 16) {
|
||||||
var missing_columns = (16 - window.len) * 3;
|
var missing_columns = (16 - window.len) * 3;
|
||||||
if (window.len < 8) missing_columns += 1;
|
if (window.len < 8) missing_columns += 1;
|
||||||
try writer.writeByteNTimes(' ', missing_columns);
|
try bw.splatByteAll(' ', missing_columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Print the characters.
|
// 3. Print the characters.
|
||||||
for (window) |byte| {
|
for (window) |byte| {
|
||||||
if (std.ascii.isPrint(byte)) {
|
if (std.ascii.isPrint(byte)) {
|
||||||
try writer.writeByte(byte);
|
try bw.writeByte(byte);
|
||||||
} else {
|
} else {
|
||||||
// Related: https://github.com/ziglang/zig/issues/7600
|
// Related: https://github.com/ziglang/zig/issues/7600
|
||||||
if (ttyconf == .windows_api) {
|
if (ttyconf == .windows_api) {
|
||||||
try writer.writeByte('.');
|
try bw.writeByte('.');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,22 +291,23 @@ fn dumpHexInternal(bytes: []const u8, ttyconf: std.io.tty.Config, writer: anytyp
|
|||||||
// We don't want to do this for all control codes because most control codes apart from
|
// We don't want to do this for all control codes because most control codes apart from
|
||||||
// the ones that Zig has escape sequences for are likely not very useful to print as symbols.
|
// the ones that Zig has escape sequences for are likely not very useful to print as symbols.
|
||||||
switch (byte) {
|
switch (byte) {
|
||||||
'\n' => try writer.writeAll("␊"),
|
'\n' => try bw.writeAll("␊"),
|
||||||
'\r' => try writer.writeAll("␍"),
|
'\r' => try bw.writeAll("␍"),
|
||||||
'\t' => try writer.writeAll("␉"),
|
'\t' => try bw.writeAll("␉"),
|
||||||
else => try writer.writeByte('.'),
|
else => try bw.writeByte('.'),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try writer.writeByte('\n');
|
try bw.writeByte('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test dumpHexInternal {
|
test dumpHexFallible {
|
||||||
const bytes: []const u8 = &.{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01, 0x12, 0x13 };
|
const bytes: []const u8 = &.{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01, 0x12, 0x13 };
|
||||||
var output = std.ArrayList(u8).init(std.testing.allocator);
|
var aw: std.io.Writer.Allocating = .init(std.testing.allocator);
|
||||||
defer output.deinit();
|
defer aw.deinit();
|
||||||
try dumpHexInternal(bytes, .no_color, output.writer());
|
|
||||||
|
try dumpHexFallible(&aw.interface, .no_color, bytes);
|
||||||
const expected = try std.fmt.allocPrint(std.testing.allocator,
|
const expected = try std.fmt.allocPrint(std.testing.allocator,
|
||||||
\\{x:0>[2]} 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF .."3DUfw........
|
\\{x:0>[2]} 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF .."3DUfw........
|
||||||
\\{x:0>[2]} 01 12 13 ...
|
\\{x:0>[2]} 01 12 13 ...
|
||||||
@ -309,34 +318,36 @@ test dumpHexInternal {
|
|||||||
@sizeOf(usize) * 2,
|
@sizeOf(usize) * 2,
|
||||||
});
|
});
|
||||||
defer std.testing.allocator.free(expected);
|
defer std.testing.allocator.free(expected);
|
||||||
try std.testing.expectEqualStrings(expected, output.items);
|
try std.testing.expectEqualStrings(expected, aw.getWritten());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned.
|
/// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned.
|
||||||
/// TODO multithreaded awareness
|
|
||||||
pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
|
pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
|
||||||
nosuspend {
|
const stderr = lockStderrWriter(&.{});
|
||||||
if (builtin.target.cpu.arch.isWasm()) {
|
defer unlockStderrWriter();
|
||||||
if (native_os == .wasi) {
|
nosuspend dumpCurrentStackTraceToWriter(start_addr, stderr) catch return;
|
||||||
const stderr = fs.File.stderr().writer();
|
}
|
||||||
stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
|
|
||||||
}
|
/// Prints the current stack trace to the provided writer.
|
||||||
return;
|
pub fn dumpCurrentStackTraceToWriter(start_addr: ?usize, writer: *Writer) !void {
|
||||||
|
if (builtin.target.cpu.arch.isWasm()) {
|
||||||
|
if (native_os == .wasi) {
|
||||||
|
try writer.writeAll("Unable to dump stack trace: not implemented for Wasm\n");
|
||||||
}
|
}
|
||||||
const stderr = fs.File.stderr().writer();
|
return;
|
||||||
if (builtin.strip_debug_info) {
|
|
||||||
stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const debug_info = getSelfDebugInfo() catch |err| {
|
|
||||||
stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
writeCurrentStackTrace(stderr, debug_info, io.tty.detectConfig(fs.File.stderr()), start_addr) catch |err| {
|
|
||||||
stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return;
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
if (builtin.strip_debug_info) {
|
||||||
|
try writer.writeAll("Unable to dump stack trace: debug info stripped\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const debug_info = getSelfDebugInfo() catch |err| {
|
||||||
|
try writer.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
writeCurrentStackTrace(writer, debug_info, io.tty.detectConfig(.stderr()), start_addr) catch |err| {
|
||||||
|
try writer.print("Unable to dump stack trace: {s}\n", .{@errorName(err)});
|
||||||
|
return;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const have_ucontext = posix.ucontext_t != void;
|
pub const have_ucontext = posix.ucontext_t != void;
|
||||||
@ -402,16 +413,14 @@ pub inline fn getContext(context: *ThreadContext) bool {
|
|||||||
/// Tries to print the stack trace starting from the supplied base pointer to stderr,
|
/// Tries to print the stack trace starting from the supplied base pointer to stderr,
|
||||||
/// unbuffered, and ignores any error returned.
|
/// unbuffered, and ignores any error returned.
|
||||||
/// TODO multithreaded awareness
|
/// TODO multithreaded awareness
|
||||||
pub fn dumpStackTraceFromBase(context: *ThreadContext) void {
|
pub fn dumpStackTraceFromBase(context: *ThreadContext, stderr: *Writer) void {
|
||||||
nosuspend {
|
nosuspend {
|
||||||
if (builtin.target.cpu.arch.isWasm()) {
|
if (builtin.target.cpu.arch.isWasm()) {
|
||||||
if (native_os == .wasi) {
|
if (native_os == .wasi) {
|
||||||
const stderr = fs.File.stderr().writer();
|
|
||||||
stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
|
stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const stderr = fs.File.stderr().writer();
|
|
||||||
if (builtin.strip_debug_info) {
|
if (builtin.strip_debug_info) {
|
||||||
stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
|
stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
|
||||||
return;
|
return;
|
||||||
@ -420,7 +429,7 @@ pub fn dumpStackTraceFromBase(context: *ThreadContext) void {
|
|||||||
stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;
|
stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
const tty_config = io.tty.detectConfig(fs.File.stderr());
|
const tty_config = io.tty.detectConfig(.stderr());
|
||||||
if (native_os == .windows) {
|
if (native_os == .windows) {
|
||||||
// On x86_64 and aarch64, the stack will be unwound using RtlVirtualUnwind using the context
|
// On x86_64 and aarch64, the stack will be unwound using RtlVirtualUnwind using the context
|
||||||
// provided by the exception handler. On x86, RtlVirtualUnwind doesn't exist. Instead, a new backtrace
|
// provided by the exception handler. On x86, RtlVirtualUnwind doesn't exist. Instead, a new backtrace
|
||||||
@ -510,21 +519,23 @@ pub fn dumpStackTrace(stack_trace: std.builtin.StackTrace) void {
|
|||||||
nosuspend {
|
nosuspend {
|
||||||
if (builtin.target.cpu.arch.isWasm()) {
|
if (builtin.target.cpu.arch.isWasm()) {
|
||||||
if (native_os == .wasi) {
|
if (native_os == .wasi) {
|
||||||
const stderr = fs.File.stderr().writer();
|
const stderr = lockStderrWriter(&.{});
|
||||||
stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
|
defer unlockStderrWriter();
|
||||||
|
stderr.writeAll("Unable to dump stack trace: not implemented for Wasm\n") catch return;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const stderr = fs.File.stderr().writer();
|
const stderr = lockStderrWriter(&.{});
|
||||||
|
defer unlockStderrWriter();
|
||||||
if (builtin.strip_debug_info) {
|
if (builtin.strip_debug_info) {
|
||||||
stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
|
stderr.writeAll("Unable to dump stack trace: debug info stripped\n") catch return;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const debug_info = getSelfDebugInfo() catch |err| {
|
const debug_info = getSelfDebugInfo() catch |err| {
|
||||||
stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;
|
stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
writeStackTrace(stack_trace, stderr, debug_info, io.tty.detectConfig(fs.File.stderr())) catch |err| {
|
writeStackTrace(stack_trace, stderr, debug_info, io.tty.detectConfig(.stderr())) catch |err| {
|
||||||
stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return;
|
stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return;
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@ -573,14 +584,13 @@ pub fn panicExtra(
|
|||||||
const size = 0x1000;
|
const size = 0x1000;
|
||||||
const trunc_msg = "(msg truncated)";
|
const trunc_msg = "(msg truncated)";
|
||||||
var buf: [size + trunc_msg.len]u8 = undefined;
|
var buf: [size + trunc_msg.len]u8 = undefined;
|
||||||
|
var bw: Writer = .fixed(buf[0..size]);
|
||||||
// a minor annoyance with this is that it will result in the NoSpaceLeft
|
// a minor annoyance with this is that it will result in the NoSpaceLeft
|
||||||
// error being part of the @panic stack trace (but that error should
|
// error being part of the @panic stack trace (but that error should
|
||||||
// only happen rarely)
|
// only happen rarely)
|
||||||
const msg = std.fmt.bufPrint(buf[0..size], format, args) catch |err| switch (err) {
|
const msg = if (bw.print(format, args)) |_| bw.buffered() else |_| blk: {
|
||||||
error.NoSpaceLeft => blk: {
|
@memcpy(buf[size..], trunc_msg);
|
||||||
@memcpy(buf[size..], trunc_msg);
|
break :blk &buf;
|
||||||
break :blk &buf;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
std.builtin.panic.call(msg, ret_addr);
|
std.builtin.panic.call(msg, ret_addr);
|
||||||
}
|
}
|
||||||
@ -675,10 +685,9 @@ pub fn defaultPanic(
|
|||||||
_ = panicking.fetchAdd(1, .seq_cst);
|
_ = panicking.fetchAdd(1, .seq_cst);
|
||||||
|
|
||||||
{
|
{
|
||||||
lockStdErr();
|
const stderr = lockStderrWriter(&.{});
|
||||||
defer unlockStdErr();
|
defer unlockStderrWriter();
|
||||||
|
|
||||||
const stderr = fs.File.stderr().writer();
|
|
||||||
if (builtin.single_threaded) {
|
if (builtin.single_threaded) {
|
||||||
stderr.print("panic: ", .{}) catch posix.abort();
|
stderr.print("panic: ", .{}) catch posix.abort();
|
||||||
} else {
|
} else {
|
||||||
@ -688,7 +697,7 @@ pub fn defaultPanic(
|
|||||||
stderr.print("{s}\n", .{msg}) catch posix.abort();
|
stderr.print("{s}\n", .{msg}) catch posix.abort();
|
||||||
|
|
||||||
if (@errorReturnTrace()) |t| dumpStackTrace(t.*);
|
if (@errorReturnTrace()) |t| dumpStackTrace(t.*);
|
||||||
dumpCurrentStackTrace(first_trace_addr orelse @returnAddress());
|
dumpCurrentStackTraceToWriter(first_trace_addr orelse @returnAddress(), stderr) catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForOtherThreadToFinishPanicking();
|
waitForOtherThreadToFinishPanicking();
|
||||||
@ -723,7 +732,7 @@ fn waitForOtherThreadToFinishPanicking() void {
|
|||||||
|
|
||||||
pub fn writeStackTrace(
|
pub fn writeStackTrace(
|
||||||
stack_trace: std.builtin.StackTrace,
|
stack_trace: std.builtin.StackTrace,
|
||||||
out_stream: anytype,
|
writer: *Writer,
|
||||||
debug_info: *SelfInfo,
|
debug_info: *SelfInfo,
|
||||||
tty_config: io.tty.Config,
|
tty_config: io.tty.Config,
|
||||||
) !void {
|
) !void {
|
||||||
@ -736,15 +745,15 @@ pub fn writeStackTrace(
|
|||||||
frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len;
|
frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len;
|
||||||
}) {
|
}) {
|
||||||
const return_address = stack_trace.instruction_addresses[frame_index];
|
const return_address = stack_trace.instruction_addresses[frame_index];
|
||||||
try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_config);
|
try printSourceAtAddress(debug_info, writer, return_address - 1, tty_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stack_trace.index > stack_trace.instruction_addresses.len) {
|
if (stack_trace.index > stack_trace.instruction_addresses.len) {
|
||||||
const dropped_frames = stack_trace.index - stack_trace.instruction_addresses.len;
|
const dropped_frames = stack_trace.index - stack_trace.instruction_addresses.len;
|
||||||
|
|
||||||
tty_config.setColor(out_stream, .bold) catch {};
|
tty_config.setColor(writer, .bold) catch {};
|
||||||
try out_stream.print("({d} additional stack frames skipped...)\n", .{dropped_frames});
|
try writer.print("({d} additional stack frames skipped...)\n", .{dropped_frames});
|
||||||
tty_config.setColor(out_stream, .reset) catch {};
|
tty_config.setColor(writer, .reset) catch {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -954,7 +963,7 @@ pub const StackIterator = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn writeCurrentStackTrace(
|
pub fn writeCurrentStackTrace(
|
||||||
out_stream: anytype,
|
writer: *Writer,
|
||||||
debug_info: *SelfInfo,
|
debug_info: *SelfInfo,
|
||||||
tty_config: io.tty.Config,
|
tty_config: io.tty.Config,
|
||||||
start_addr: ?usize,
|
start_addr: ?usize,
|
||||||
@ -962,7 +971,7 @@ pub fn writeCurrentStackTrace(
|
|||||||
if (native_os == .windows) {
|
if (native_os == .windows) {
|
||||||
var context: ThreadContext = undefined;
|
var context: ThreadContext = undefined;
|
||||||
assert(getContext(&context));
|
assert(getContext(&context));
|
||||||
return writeStackTraceWindows(out_stream, debug_info, tty_config, &context, start_addr);
|
return writeStackTraceWindows(writer, debug_info, tty_config, &context, start_addr);
|
||||||
}
|
}
|
||||||
var context: ThreadContext = undefined;
|
var context: ThreadContext = undefined;
|
||||||
const has_context = getContext(&context);
|
const has_context = getContext(&context);
|
||||||
@ -973,7 +982,7 @@ pub fn writeCurrentStackTrace(
|
|||||||
defer it.deinit();
|
defer it.deinit();
|
||||||
|
|
||||||
while (it.next()) |return_address| {
|
while (it.next()) |return_address| {
|
||||||
printLastUnwindError(&it, debug_info, out_stream, tty_config);
|
printLastUnwindError(&it, debug_info, writer, tty_config);
|
||||||
|
|
||||||
// On arm64 macOS, the address of the last frame is 0x0 rather than 0x1 as on x86_64 macOS,
|
// On arm64 macOS, the address of the last frame is 0x0 rather than 0x1 as on x86_64 macOS,
|
||||||
// therefore, we do a check for `return_address == 0` before subtracting 1 from it to avoid
|
// therefore, we do a check for `return_address == 0` before subtracting 1 from it to avoid
|
||||||
@ -981,8 +990,8 @@ pub fn writeCurrentStackTrace(
|
|||||||
// condition on the subsequent iteration and return `null` thus terminating the loop.
|
// condition on the subsequent iteration and return `null` thus terminating the loop.
|
||||||
// same behaviour for x86-windows-msvc
|
// same behaviour for x86-windows-msvc
|
||||||
const address = return_address -| 1;
|
const address = return_address -| 1;
|
||||||
try printSourceAtAddress(debug_info, out_stream, address, tty_config);
|
try printSourceAtAddress(debug_info, writer, address, tty_config);
|
||||||
} else printLastUnwindError(&it, debug_info, out_stream, tty_config);
|
} else printLastUnwindError(&it, debug_info, writer, tty_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const windows.CONTEXT) usize {
|
pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const windows.CONTEXT) usize {
|
||||||
@ -1042,7 +1051,7 @@ pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const w
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeStackTraceWindows(
|
pub fn writeStackTraceWindows(
|
||||||
out_stream: anytype,
|
writer: *Writer,
|
||||||
debug_info: *SelfInfo,
|
debug_info: *SelfInfo,
|
||||||
tty_config: io.tty.Config,
|
tty_config: io.tty.Config,
|
||||||
context: *const windows.CONTEXT,
|
context: *const windows.CONTEXT,
|
||||||
@ -1058,14 +1067,14 @@ pub fn writeStackTraceWindows(
|
|||||||
return;
|
return;
|
||||||
} else 0;
|
} else 0;
|
||||||
for (addrs[start_i..]) |addr| {
|
for (addrs[start_i..]) |addr| {
|
||||||
try printSourceAtAddress(debug_info, out_stream, addr - 1, tty_config);
|
try printSourceAtAddress(debug_info, writer, addr - 1, tty_config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printUnknownSource(debug_info: *SelfInfo, out_stream: anytype, address: usize, tty_config: io.tty.Config) !void {
|
fn printUnknownSource(debug_info: *SelfInfo, writer: *Writer, address: usize, tty_config: io.tty.Config) !void {
|
||||||
const module_name = debug_info.getModuleNameForAddress(address);
|
const module_name = debug_info.getModuleNameForAddress(address);
|
||||||
return printLineInfo(
|
return printLineInfo(
|
||||||
out_stream,
|
writer,
|
||||||
null,
|
null,
|
||||||
address,
|
address,
|
||||||
"???",
|
"???",
|
||||||
@ -1075,38 +1084,38 @@ fn printUnknownSource(debug_info: *SelfInfo, out_stream: anytype, address: usize
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printLastUnwindError(it: *StackIterator, debug_info: *SelfInfo, out_stream: anytype, tty_config: io.tty.Config) void {
|
fn printLastUnwindError(it: *StackIterator, debug_info: *SelfInfo, writer: *Writer, tty_config: io.tty.Config) void {
|
||||||
if (!have_ucontext) return;
|
if (!have_ucontext) return;
|
||||||
if (it.getLastError()) |unwind_error| {
|
if (it.getLastError()) |unwind_error| {
|
||||||
printUnwindError(debug_info, out_stream, unwind_error.address, unwind_error.err, tty_config) catch {};
|
printUnwindError(debug_info, writer, unwind_error.address, unwind_error.err, tty_config) catch {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printUnwindError(debug_info: *SelfInfo, out_stream: anytype, address: usize, err: UnwindError, tty_config: io.tty.Config) !void {
|
fn printUnwindError(debug_info: *SelfInfo, writer: *Writer, address: usize, err: UnwindError, tty_config: io.tty.Config) !void {
|
||||||
const module_name = debug_info.getModuleNameForAddress(address) orelse "???";
|
const module_name = debug_info.getModuleNameForAddress(address) orelse "???";
|
||||||
try tty_config.setColor(out_stream, .dim);
|
try tty_config.setColor(writer, .dim);
|
||||||
if (err == error.MissingDebugInfo) {
|
if (err == error.MissingDebugInfo) {
|
||||||
try out_stream.print("Unwind information for `{s}:0x{x}` was not available, trace may be incomplete\n\n", .{ module_name, address });
|
try writer.print("Unwind information for `{s}:0x{x}` was not available, trace may be incomplete\n\n", .{ module_name, address });
|
||||||
} else {
|
} else {
|
||||||
try out_stream.print("Unwind error at address `{s}:0x{x}` ({}), trace may be incomplete\n\n", .{ module_name, address, err });
|
try writer.print("Unwind error at address `{s}:0x{x}` ({}), trace may be incomplete\n\n", .{ module_name, address, err });
|
||||||
}
|
}
|
||||||
try tty_config.setColor(out_stream, .reset);
|
try tty_config.setColor(writer, .reset);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn printSourceAtAddress(debug_info: *SelfInfo, out_stream: anytype, address: usize, tty_config: io.tty.Config) !void {
|
pub fn printSourceAtAddress(debug_info: *SelfInfo, writer: *Writer, address: usize, tty_config: io.tty.Config) !void {
|
||||||
const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {
|
const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {
|
||||||
error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, out_stream, address, tty_config),
|
error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, writer, address, tty_config),
|
||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
|
|
||||||
const symbol_info = module.getSymbolAtAddress(debug_info.allocator, address) catch |err| switch (err) {
|
const symbol_info = module.getSymbolAtAddress(debug_info.allocator, address) catch |err| switch (err) {
|
||||||
error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, out_stream, address, tty_config),
|
error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, writer, address, tty_config),
|
||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
defer if (symbol_info.source_location) |sl| debug_info.allocator.free(sl.file_name);
|
defer if (symbol_info.source_location) |sl| debug_info.allocator.free(sl.file_name);
|
||||||
|
|
||||||
return printLineInfo(
|
return printLineInfo(
|
||||||
out_stream,
|
writer,
|
||||||
symbol_info.source_location,
|
symbol_info.source_location,
|
||||||
address,
|
address,
|
||||||
symbol_info.name,
|
symbol_info.name,
|
||||||
@ -1117,7 +1126,7 @@ pub fn printSourceAtAddress(debug_info: *SelfInfo, out_stream: anytype, address:
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn printLineInfo(
|
fn printLineInfo(
|
||||||
out_stream: anytype,
|
writer: *Writer,
|
||||||
source_location: ?SourceLocation,
|
source_location: ?SourceLocation,
|
||||||
address: usize,
|
address: usize,
|
||||||
symbol_name: []const u8,
|
symbol_name: []const u8,
|
||||||
@ -1126,34 +1135,34 @@ fn printLineInfo(
|
|||||||
comptime printLineFromFile: anytype,
|
comptime printLineFromFile: anytype,
|
||||||
) !void {
|
) !void {
|
||||||
nosuspend {
|
nosuspend {
|
||||||
try tty_config.setColor(out_stream, .bold);
|
try tty_config.setColor(writer, .bold);
|
||||||
|
|
||||||
if (source_location) |*sl| {
|
if (source_location) |*sl| {
|
||||||
try out_stream.print("{s}:{d}:{d}", .{ sl.file_name, sl.line, sl.column });
|
try writer.print("{s}:{d}:{d}", .{ sl.file_name, sl.line, sl.column });
|
||||||
} else {
|
} else {
|
||||||
try out_stream.writeAll("???:?:?");
|
try writer.writeAll("???:?:?");
|
||||||
}
|
}
|
||||||
|
|
||||||
try tty_config.setColor(out_stream, .reset);
|
try tty_config.setColor(writer, .reset);
|
||||||
try out_stream.writeAll(": ");
|
try writer.writeAll(": ");
|
||||||
try tty_config.setColor(out_stream, .dim);
|
try tty_config.setColor(writer, .dim);
|
||||||
try out_stream.print("0x{x} in {s} ({s})", .{ address, symbol_name, compile_unit_name });
|
try writer.print("0x{x} in {s} ({s})", .{ address, symbol_name, compile_unit_name });
|
||||||
try tty_config.setColor(out_stream, .reset);
|
try tty_config.setColor(writer, .reset);
|
||||||
try out_stream.writeAll("\n");
|
try writer.writeAll("\n");
|
||||||
|
|
||||||
// Show the matching source code line if possible
|
// Show the matching source code line if possible
|
||||||
if (source_location) |sl| {
|
if (source_location) |sl| {
|
||||||
if (printLineFromFile(out_stream, sl)) {
|
if (printLineFromFile(writer, sl)) {
|
||||||
if (sl.column > 0) {
|
if (sl.column > 0) {
|
||||||
// The caret already takes one char
|
// The caret already takes one char
|
||||||
const space_needed = @as(usize, @intCast(sl.column - 1));
|
const space_needed = @as(usize, @intCast(sl.column - 1));
|
||||||
|
|
||||||
try out_stream.writeByteNTimes(' ', space_needed);
|
try writer.splatByteAll(' ', space_needed);
|
||||||
try tty_config.setColor(out_stream, .green);
|
try tty_config.setColor(writer, .green);
|
||||||
try out_stream.writeAll("^");
|
try writer.writeAll("^");
|
||||||
try tty_config.setColor(out_stream, .reset);
|
try tty_config.setColor(writer, .reset);
|
||||||
}
|
}
|
||||||
try out_stream.writeAll("\n");
|
try writer.writeAll("\n");
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
error.EndOfFile, error.FileNotFound => {},
|
error.EndOfFile, error.FileNotFound => {},
|
||||||
error.BadPathName => {},
|
error.BadPathName => {},
|
||||||
@ -1164,7 +1173,7 @@ fn printLineInfo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printLineFromFileAnyOs(out_stream: anytype, source_location: SourceLocation) !void {
|
fn printLineFromFileAnyOs(writer: *Writer, source_location: SourceLocation) !void {
|
||||||
// Need this to always block even in async I/O mode, because this could potentially
|
// Need this to always block even in async I/O mode, because this could potentially
|
||||||
// be called from e.g. the event loop code crashing.
|
// be called from e.g. the event loop code crashing.
|
||||||
var f = try fs.cwd().openFile(source_location.file_name, .{});
|
var f = try fs.cwd().openFile(source_location.file_name, .{});
|
||||||
@ -1197,31 +1206,31 @@ fn printLineFromFileAnyOs(out_stream: anytype, source_location: SourceLocation)
|
|||||||
if (mem.indexOfScalar(u8, slice, '\n')) |pos| {
|
if (mem.indexOfScalar(u8, slice, '\n')) |pos| {
|
||||||
const line = slice[0 .. pos + 1];
|
const line = slice[0 .. pos + 1];
|
||||||
mem.replaceScalar(u8, line, '\t', ' ');
|
mem.replaceScalar(u8, line, '\t', ' ');
|
||||||
return out_stream.writeAll(line);
|
return writer.writeAll(line);
|
||||||
} else { // Line is the last inside the buffer, and requires another read to find delimiter. Alternatively the file ends.
|
} else { // Line is the last inside the buffer, and requires another read to find delimiter. Alternatively the file ends.
|
||||||
mem.replaceScalar(u8, slice, '\t', ' ');
|
mem.replaceScalar(u8, slice, '\t', ' ');
|
||||||
try out_stream.writeAll(slice);
|
try writer.writeAll(slice);
|
||||||
while (amt_read == buf.len) {
|
while (amt_read == buf.len) {
|
||||||
amt_read = try f.read(buf[0..]);
|
amt_read = try f.read(buf[0..]);
|
||||||
if (mem.indexOfScalar(u8, buf[0..amt_read], '\n')) |pos| {
|
if (mem.indexOfScalar(u8, buf[0..amt_read], '\n')) |pos| {
|
||||||
const line = buf[0 .. pos + 1];
|
const line = buf[0 .. pos + 1];
|
||||||
mem.replaceScalar(u8, line, '\t', ' ');
|
mem.replaceScalar(u8, line, '\t', ' ');
|
||||||
return out_stream.writeAll(line);
|
return writer.writeAll(line);
|
||||||
} else {
|
} else {
|
||||||
const line = buf[0..amt_read];
|
const line = buf[0..amt_read];
|
||||||
mem.replaceScalar(u8, line, '\t', ' ');
|
mem.replaceScalar(u8, line, '\t', ' ');
|
||||||
try out_stream.writeAll(line);
|
try writer.writeAll(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Make sure printing last line of file inserts extra newline
|
// Make sure printing last line of file inserts extra newline
|
||||||
try out_stream.writeByte('\n');
|
try writer.writeByte('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test printLineFromFileAnyOs {
|
test printLineFromFileAnyOs {
|
||||||
var output = std.ArrayList(u8).init(std.testing.allocator);
|
var aw: Writer.Allocating = .init(std.testing.allocator);
|
||||||
defer output.deinit();
|
defer aw.deinit();
|
||||||
const output_stream = output.writer();
|
const output_stream = &aw.interface;
|
||||||
|
|
||||||
const allocator = std.testing.allocator;
|
const allocator = std.testing.allocator;
|
||||||
const join = std.fs.path.join;
|
const join = std.fs.path.join;
|
||||||
@ -1243,8 +1252,8 @@ test printLineFromFileAnyOs {
|
|||||||
try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }));
|
try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }));
|
||||||
|
|
||||||
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
|
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
|
||||||
try expectEqualStrings("no new lines in this file, but one is printed anyway\n", output.items);
|
try expectEqualStrings("no new lines in this file, but one is printed anyway\n", aw.getWritten());
|
||||||
output.clearRetainingCapacity();
|
aw.clearRetainingCapacity();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const path = try fs.path.join(allocator, &.{ test_dir_path, "three_lines.zig" });
|
const path = try fs.path.join(allocator, &.{ test_dir_path, "three_lines.zig" });
|
||||||
@ -1259,12 +1268,12 @@ test printLineFromFileAnyOs {
|
|||||||
});
|
});
|
||||||
|
|
||||||
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
|
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
|
||||||
try expectEqualStrings("1\n", output.items);
|
try expectEqualStrings("1\n", aw.getWritten());
|
||||||
output.clearRetainingCapacity();
|
aw.clearRetainingCapacity();
|
||||||
|
|
||||||
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 3, .column = 0 });
|
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 3, .column = 0 });
|
||||||
try expectEqualStrings("3\n", output.items);
|
try expectEqualStrings("3\n", aw.getWritten());
|
||||||
output.clearRetainingCapacity();
|
aw.clearRetainingCapacity();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const file = try test_dir.dir.createFile("line_overlaps_page_boundary.zig", .{});
|
const file = try test_dir.dir.createFile("line_overlaps_page_boundary.zig", .{});
|
||||||
@ -1273,14 +1282,15 @@ test printLineFromFileAnyOs {
|
|||||||
defer allocator.free(path);
|
defer allocator.free(path);
|
||||||
|
|
||||||
const overlap = 10;
|
const overlap = 10;
|
||||||
var writer = file.writer();
|
var file_writer = file.writer(&.{});
|
||||||
try writer.writeByteNTimes('a', std.heap.page_size_min - overlap);
|
const writer = &file_writer.interface;
|
||||||
|
try writer.splatByteAll('a', std.heap.page_size_min - overlap);
|
||||||
try writer.writeByte('\n');
|
try writer.writeByte('\n');
|
||||||
try writer.writeByteNTimes('a', overlap);
|
try writer.splatByteAll('a', overlap);
|
||||||
|
|
||||||
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 });
|
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 });
|
||||||
try expectEqualStrings(("a" ** overlap) ++ "\n", output.items);
|
try expectEqualStrings(("a" ** overlap) ++ "\n", aw.getWritten());
|
||||||
output.clearRetainingCapacity();
|
aw.clearRetainingCapacity();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const file = try test_dir.dir.createFile("file_ends_on_page_boundary.zig", .{});
|
const file = try test_dir.dir.createFile("file_ends_on_page_boundary.zig", .{});
|
||||||
@ -1288,12 +1298,13 @@ test printLineFromFileAnyOs {
|
|||||||
const path = try fs.path.join(allocator, &.{ test_dir_path, "file_ends_on_page_boundary.zig" });
|
const path = try fs.path.join(allocator, &.{ test_dir_path, "file_ends_on_page_boundary.zig" });
|
||||||
defer allocator.free(path);
|
defer allocator.free(path);
|
||||||
|
|
||||||
var writer = file.writer();
|
var file_writer = file.writer(&.{});
|
||||||
try writer.writeByteNTimes('a', std.heap.page_size_max);
|
const writer = &file_writer.interface;
|
||||||
|
try writer.splatByteAll('a', std.heap.page_size_max);
|
||||||
|
|
||||||
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
|
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
|
||||||
try expectEqualStrings(("a" ** std.heap.page_size_max) ++ "\n", output.items);
|
try expectEqualStrings(("a" ** std.heap.page_size_max) ++ "\n", aw.getWritten());
|
||||||
output.clearRetainingCapacity();
|
aw.clearRetainingCapacity();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const file = try test_dir.dir.createFile("very_long_first_line_spanning_multiple_pages.zig", .{});
|
const file = try test_dir.dir.createFile("very_long_first_line_spanning_multiple_pages.zig", .{});
|
||||||
@ -1301,24 +1312,25 @@ test printLineFromFileAnyOs {
|
|||||||
const path = try fs.path.join(allocator, &.{ test_dir_path, "very_long_first_line_spanning_multiple_pages.zig" });
|
const path = try fs.path.join(allocator, &.{ test_dir_path, "very_long_first_line_spanning_multiple_pages.zig" });
|
||||||
defer allocator.free(path);
|
defer allocator.free(path);
|
||||||
|
|
||||||
var writer = file.writer();
|
var file_writer = file.writer(&.{});
|
||||||
try writer.writeByteNTimes('a', 3 * std.heap.page_size_max);
|
const writer = &file_writer.interface;
|
||||||
|
try writer.splatByteAll('a', 3 * std.heap.page_size_max);
|
||||||
|
|
||||||
try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }));
|
try expectError(error.EndOfFile, printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 }));
|
||||||
|
|
||||||
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
|
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
|
||||||
try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "\n", output.items);
|
try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "\n", aw.getWritten());
|
||||||
output.clearRetainingCapacity();
|
aw.clearRetainingCapacity();
|
||||||
|
|
||||||
try writer.writeAll("a\na");
|
try writer.writeAll("a\na");
|
||||||
|
|
||||||
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
|
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 1, .column = 0 });
|
||||||
try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "a\n", output.items);
|
try expectEqualStrings(("a" ** (3 * std.heap.page_size_max)) ++ "a\n", aw.getWritten());
|
||||||
output.clearRetainingCapacity();
|
aw.clearRetainingCapacity();
|
||||||
|
|
||||||
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 });
|
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = 2, .column = 0 });
|
||||||
try expectEqualStrings("a\n", output.items);
|
try expectEqualStrings("a\n", aw.getWritten());
|
||||||
output.clearRetainingCapacity();
|
aw.clearRetainingCapacity();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const file = try test_dir.dir.createFile("file_of_newlines.zig", .{});
|
const file = try test_dir.dir.createFile("file_of_newlines.zig", .{});
|
||||||
@ -1326,18 +1338,19 @@ test printLineFromFileAnyOs {
|
|||||||
const path = try fs.path.join(allocator, &.{ test_dir_path, "file_of_newlines.zig" });
|
const path = try fs.path.join(allocator, &.{ test_dir_path, "file_of_newlines.zig" });
|
||||||
defer allocator.free(path);
|
defer allocator.free(path);
|
||||||
|
|
||||||
var writer = file.writer();
|
var file_writer = file.writer(&.{});
|
||||||
|
const writer = &file_writer.interface;
|
||||||
const real_file_start = 3 * std.heap.page_size_min;
|
const real_file_start = 3 * std.heap.page_size_min;
|
||||||
try writer.writeByteNTimes('\n', real_file_start);
|
try writer.splatByteAll('\n', real_file_start);
|
||||||
try writer.writeAll("abc\ndef");
|
try writer.writeAll("abc\ndef");
|
||||||
|
|
||||||
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = real_file_start + 1, .column = 0 });
|
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = real_file_start + 1, .column = 0 });
|
||||||
try expectEqualStrings("abc\n", output.items);
|
try expectEqualStrings("abc\n", aw.getWritten());
|
||||||
output.clearRetainingCapacity();
|
aw.clearRetainingCapacity();
|
||||||
|
|
||||||
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = real_file_start + 2, .column = 0 });
|
try printLineFromFileAnyOs(output_stream, .{ .file_name = path, .line = real_file_start + 2, .column = 0 });
|
||||||
try expectEqualStrings("def\n", output.items);
|
try expectEqualStrings("def\n", aw.getWritten());
|
||||||
output.clearRetainingCapacity();
|
aw.clearRetainingCapacity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1461,7 +1474,8 @@ fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopa
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque) void {
|
fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque) void {
|
||||||
const stderr = fs.File.stderr().writer();
|
const stderr = lockStderrWriter(&.{});
|
||||||
|
defer unlockStderrWriter();
|
||||||
_ = switch (sig) {
|
_ = switch (sig) {
|
||||||
posix.SIG.SEGV => if (native_arch == .x86_64 and native_os == .linux and code == 128) // SI_KERNEL
|
posix.SIG.SEGV => if (native_arch == .x86_64 and native_os == .linux and code == 128) // SI_KERNEL
|
||||||
// x86_64 doesn't have a full 64-bit virtual address space.
|
// x86_64 doesn't have a full 64-bit virtual address space.
|
||||||
@ -1471,7 +1485,7 @@ fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque)
|
|||||||
// but can also happen when no addressable memory is involved;
|
// but can also happen when no addressable memory is involved;
|
||||||
// for example when reading/writing model-specific registers
|
// for example when reading/writing model-specific registers
|
||||||
// by executing `rdmsr` or `wrmsr` in user-space (unprivileged mode).
|
// by executing `rdmsr` or `wrmsr` in user-space (unprivileged mode).
|
||||||
stderr.print("General protection exception (no address available)\n", .{})
|
stderr.writeAll("General protection exception (no address available)\n")
|
||||||
else
|
else
|
||||||
stderr.print("Segmentation fault at address 0x{x}\n", .{addr}),
|
stderr.print("Segmentation fault at address 0x{x}\n", .{addr}),
|
||||||
posix.SIG.ILL => stderr.print("Illegal instruction at address 0x{x}\n", .{addr}),
|
posix.SIG.ILL => stderr.print("Illegal instruction at address 0x{x}\n", .{addr}),
|
||||||
@ -1509,7 +1523,7 @@ fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque)
|
|||||||
}, @ptrCast(ctx)).__mcontext_data;
|
}, @ptrCast(ctx)).__mcontext_data;
|
||||||
}
|
}
|
||||||
relocateContext(&new_ctx);
|
relocateContext(&new_ctx);
|
||||||
dumpStackTraceFromBase(&new_ctx);
|
dumpStackTraceFromBase(&new_ctx, stderr);
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
@ -1539,10 +1553,10 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label:
|
|||||||
_ = panicking.fetchAdd(1, .seq_cst);
|
_ = panicking.fetchAdd(1, .seq_cst);
|
||||||
|
|
||||||
{
|
{
|
||||||
lockStdErr();
|
const stderr = lockStderrWriter(&.{});
|
||||||
defer unlockStdErr();
|
defer unlockStderrWriter();
|
||||||
|
|
||||||
dumpSegfaultInfoWindows(info, msg, label);
|
dumpSegfaultInfoWindows(info, msg, label, stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForOtherThreadToFinishPanicking();
|
waitForOtherThreadToFinishPanicking();
|
||||||
@ -1556,8 +1570,7 @@ fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label:
|
|||||||
posix.abort();
|
posix.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8) void {
|
fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8, stderr: *Writer) void {
|
||||||
const stderr = fs.File.stderr().writer();
|
|
||||||
_ = switch (msg) {
|
_ = switch (msg) {
|
||||||
0 => stderr.print("{s}\n", .{label.?}),
|
0 => stderr.print("{s}\n", .{label.?}),
|
||||||
1 => stderr.print("Segmentation fault at address 0x{x}\n", .{info.ExceptionRecord.ExceptionInformation[1]}),
|
1 => stderr.print("Segmentation fault at address 0x{x}\n", .{info.ExceptionRecord.ExceptionInformation[1]}),
|
||||||
@ -1565,7 +1578,7 @@ fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[
|
|||||||
else => unreachable,
|
else => unreachable,
|
||||||
} catch posix.abort();
|
} catch posix.abort();
|
||||||
|
|
||||||
dumpStackTraceFromBase(info.ContextRecord);
|
dumpStackTraceFromBase(info.ContextRecord, stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dumpStackPointerAddr(prefix: []const u8) void {
|
pub fn dumpStackPointerAddr(prefix: []const u8) void {
|
||||||
@ -1588,10 +1601,10 @@ test "manage resources correctly" {
|
|||||||
// self-hosted debug info is still too buggy
|
// self-hosted debug info is still too buggy
|
||||||
if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest;
|
if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest;
|
||||||
|
|
||||||
const writer = std.io.null_writer;
|
var writer: std.io.Writer = .discarding(&.{});
|
||||||
var di = try SelfInfo.open(testing.allocator);
|
var di = try SelfInfo.open(testing.allocator);
|
||||||
defer di.deinit();
|
defer di.deinit();
|
||||||
try printSourceAtAddress(&di, writer, showMyTrace(), io.tty.detectConfig(std.fs.File.stderr()));
|
try printSourceAtAddress(&di, &writer, showMyTrace(), io.tty.detectConfig(.stderr()));
|
||||||
}
|
}
|
||||||
|
|
||||||
noinline fn showMyTrace() usize {
|
noinline fn showMyTrace() usize {
|
||||||
@ -1657,8 +1670,9 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize
|
|||||||
pub fn dump(t: @This()) void {
|
pub fn dump(t: @This()) void {
|
||||||
if (!enabled) return;
|
if (!enabled) return;
|
||||||
|
|
||||||
const tty_config = io.tty.detectConfig(std.fs.File.stderr());
|
const tty_config = io.tty.detectConfig(.stderr());
|
||||||
const stderr = fs.File.stderr().writer();
|
const stderr = lockStderrWriter(&.{});
|
||||||
|
defer unlockStderrWriter();
|
||||||
const end = @min(t.index, size);
|
const end = @min(t.index, size);
|
||||||
const debug_info = getSelfDebugInfo() catch |err| {
|
const debug_info = getSelfDebugInfo() catch |err| {
|
||||||
stderr.print(
|
stderr.print(
|
||||||
@ -1688,7 +1702,7 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize
|
|||||||
t: @This(),
|
t: @This(),
|
||||||
comptime fmt: []const u8,
|
comptime fmt: []const u8,
|
||||||
options: std.fmt.FormatOptions,
|
options: std.fmt.FormatOptions,
|
||||||
writer: anytype,
|
writer: *Writer,
|
||||||
) !void {
|
) !void {
|
||||||
if (fmt.len != 0) std.fmt.invalidFmtError(fmt, t);
|
if (fmt.len != 0) std.fmt.invalidFmtError(fmt, t);
|
||||||
_ = options;
|
_ = options;
|
||||||
|
|||||||
@ -2302,11 +2302,7 @@ pub const ElfModule = struct {
|
|||||||
};
|
};
|
||||||
defer debuginfod_dir.close();
|
defer debuginfod_dir.close();
|
||||||
|
|
||||||
const filename = std.fmt.allocPrint(
|
const filename = std.fmt.allocPrint(gpa, "{x}/debuginfo", .{id}) catch break :blk;
|
||||||
gpa,
|
|
||||||
"{s}/debuginfo",
|
|
||||||
.{std.fmt.fmtSliceHexLower(id)},
|
|
||||||
) catch break :blk;
|
|
||||||
defer gpa.free(filename);
|
defer gpa.free(filename);
|
||||||
|
|
||||||
const path: Path = .{
|
const path: Path = .{
|
||||||
@ -2330,12 +2326,8 @@ pub const ElfModule = struct {
|
|||||||
var id_prefix_buf: [2]u8 = undefined;
|
var id_prefix_buf: [2]u8 = undefined;
|
||||||
var filename_buf: [38 + extension.len]u8 = undefined;
|
var filename_buf: [38 + extension.len]u8 = undefined;
|
||||||
|
|
||||||
_ = std.fmt.bufPrint(&id_prefix_buf, "{s}", .{std.fmt.fmtSliceHexLower(id[0..1])}) catch unreachable;
|
_ = std.fmt.bufPrint(&id_prefix_buf, "{x}", .{id[0..1]}) catch unreachable;
|
||||||
const filename = std.fmt.bufPrint(
|
const filename = std.fmt.bufPrint(&filename_buf, "{x}" ++ extension, .{id[1..]}) catch break :blk;
|
||||||
&filename_buf,
|
|
||||||
"{s}" ++ extension,
|
|
||||||
.{std.fmt.fmtSliceHexLower(id[1..])},
|
|
||||||
) catch break :blk;
|
|
||||||
|
|
||||||
for (global_debug_directories) |global_directory| {
|
for (global_debug_directories) |global_directory| {
|
||||||
const path: Path = .{
|
const path: Path = .{
|
||||||
|
|||||||
@ -395,7 +395,7 @@ const Msf = struct {
|
|||||||
streams: []MsfStream,
|
streams: []MsfStream,
|
||||||
|
|
||||||
fn init(allocator: Allocator, file: File) !Msf {
|
fn init(allocator: Allocator, file: File) !Msf {
|
||||||
const in = file.reader();
|
const in = file.deprecatedReader();
|
||||||
|
|
||||||
const superblock = try in.readStruct(pdb.SuperBlock);
|
const superblock = try in.readStruct(pdb.SuperBlock);
|
||||||
|
|
||||||
@ -514,7 +514,7 @@ const MsfStream = struct {
|
|||||||
var offset = self.pos % self.block_size;
|
var offset = self.pos % self.block_size;
|
||||||
|
|
||||||
try self.in_file.seekTo(block * self.block_size + offset);
|
try self.in_file.seekTo(block * self.block_size + offset);
|
||||||
const in = self.in_file.reader();
|
const in = self.in_file.deprecatedReader();
|
||||||
|
|
||||||
var size: usize = 0;
|
var size: usize = 0;
|
||||||
var rem_buffer = buffer;
|
var rem_buffer = buffer;
|
||||||
|
|||||||
1649
lib/std/fmt.zig
1649
lib/std/fmt.zig
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@ const special_exponent = 0x7fffffff;
|
|||||||
pub const min_buffer_size = 53;
|
pub const min_buffer_size = 53;
|
||||||
|
|
||||||
/// Returns the minimum buffer size needed to print every float of a specific type and format.
|
/// Returns the minimum buffer size needed to print every float of a specific type and format.
|
||||||
pub fn bufferSize(comptime mode: Format, comptime T: type) comptime_int {
|
pub fn bufferSize(comptime mode: Mode, comptime T: type) comptime_int {
|
||||||
comptime std.debug.assert(@typeInfo(T) == .float);
|
comptime std.debug.assert(@typeInfo(T) == .float);
|
||||||
return switch (mode) {
|
return switch (mode) {
|
||||||
.scientific => 53,
|
.scientific => 53,
|
||||||
@ -27,17 +27,17 @@ pub fn bufferSize(comptime mode: Format, comptime T: type) comptime_int {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const FormatError = error{
|
pub const Error = error{
|
||||||
BufferTooSmall,
|
BufferTooSmall,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Format = enum {
|
pub const Mode = enum {
|
||||||
scientific,
|
scientific,
|
||||||
decimal,
|
decimal,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const FormatOptions = struct {
|
pub const Options = struct {
|
||||||
mode: Format = .scientific,
|
mode: Mode = .scientific,
|
||||||
precision: ?usize = null,
|
precision: ?usize = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -52,11 +52,11 @@ pub const FormatOptions = struct {
|
|||||||
///
|
///
|
||||||
/// When printing full precision decimals, use `bufferSize` to get the required space. It is
|
/// When printing full precision decimals, use `bufferSize` to get the required space. It is
|
||||||
/// recommended to bound decimal output with a fixed precision to reduce the required buffer size.
|
/// recommended to bound decimal output with a fixed precision to reduce the required buffer size.
|
||||||
pub fn formatFloat(buf: []u8, v_: anytype, options: FormatOptions) FormatError![]const u8 {
|
pub fn render(buf: []u8, value: anytype, options: Options) Error![]const u8 {
|
||||||
const v = switch (@TypeOf(v_)) {
|
const v = switch (@TypeOf(value)) {
|
||||||
// comptime_float internally is a f128; this preserves precision.
|
// comptime_float internally is a f128; this preserves precision.
|
||||||
comptime_float => @as(f128, v_),
|
comptime_float => @as(f128, value),
|
||||||
else => v_,
|
else => value,
|
||||||
};
|
};
|
||||||
|
|
||||||
const T = @TypeOf(v);
|
const T = @TypeOf(v);
|
||||||
@ -192,7 +192,7 @@ fn round(comptime T: type, f: FloatDecimal(T), mode: RoundMode, precision: usize
|
|||||||
/// will not fit.
|
/// will not fit.
|
||||||
///
|
///
|
||||||
/// It is recommended to bound decimal formatting with an exact precision.
|
/// It is recommended to bound decimal formatting with an exact precision.
|
||||||
pub fn formatScientific(comptime T: type, buf: []u8, f_: FloatDecimal(T), precision: ?usize) FormatError![]const u8 {
|
pub fn formatScientific(comptime T: type, buf: []u8, f_: FloatDecimal(T), precision: ?usize) Error![]const u8 {
|
||||||
std.debug.assert(buf.len >= min_buffer_size);
|
std.debug.assert(buf.len >= min_buffer_size);
|
||||||
var f = f_;
|
var f = f_;
|
||||||
|
|
||||||
@ -263,7 +263,7 @@ pub fn formatScientific(comptime T: type, buf: []u8, f_: FloatDecimal(T), precis
|
|||||||
/// The buffer provided must be greater than `min_buffer_size` bytes in length. If no precision is
|
/// The buffer provided must be greater than `min_buffer_size` bytes in length. If no precision is
|
||||||
/// specified, this may still return an error. If precision is specified, `2 + precision` bytes will
|
/// specified, this may still return an error. If precision is specified, `2 + precision` bytes will
|
||||||
/// always be written.
|
/// always be written.
|
||||||
pub fn formatDecimal(comptime T: type, buf: []u8, f_: FloatDecimal(T), precision: ?usize) FormatError![]const u8 {
|
pub fn formatDecimal(comptime T: type, buf: []u8, f_: FloatDecimal(T), precision: ?usize) Error![]const u8 {
|
||||||
std.debug.assert(buf.len >= min_buffer_size);
|
std.debug.assert(buf.len >= min_buffer_size);
|
||||||
var f = f_;
|
var f = f_;
|
||||||
|
|
||||||
@ -1520,7 +1520,7 @@ fn check(comptime T: type, value: T, comptime expected: []const u8) !void {
|
|||||||
|
|
||||||
var buf: [6000]u8 = undefined;
|
var buf: [6000]u8 = undefined;
|
||||||
const value_bits: I = @bitCast(value);
|
const value_bits: I = @bitCast(value);
|
||||||
const s = try formatFloat(&buf, value, .{});
|
const s = try render(&buf, value, .{});
|
||||||
try std.testing.expectEqualStrings(expected, s);
|
try std.testing.expectEqualStrings(expected, s);
|
||||||
|
|
||||||
if (T == f80 and builtin.target.os.tag == .windows and builtin.target.cpu.arch == .x86_64) return;
|
if (T == f80 and builtin.target.os.tag == .windows and builtin.target.cpu.arch == .x86_64) return;
|
||||||
1235
lib/std/fs/File.zig
1235
lib/std/fs/File.zig
File diff suppressed because it is too large
Load Diff
@ -146,14 +146,11 @@ pub fn joinZ(allocator: Allocator, paths: []const []const u8) ![:0]u8 {
|
|||||||
return out[0 .. out.len - 1 :0];
|
return out[0 .. out.len - 1 :0];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmtJoin(paths: []const []const u8) std.fmt.Formatter(formatJoin) {
|
pub fn fmtJoin(paths: []const []const u8) std.fmt.Formatter([]const []const u8, formatJoin) {
|
||||||
return .{ .data = paths };
|
return .{ .data = paths };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn formatJoin(paths: []const []const u8, comptime fmt: []const u8, options: std.fmt.FormatOptions, w: anytype) !void {
|
fn formatJoin(paths: []const []const u8, w: *std.io.Writer) std.io.Writer.Error!void {
|
||||||
_ = fmt;
|
|
||||||
_ = options;
|
|
||||||
|
|
||||||
const first_path_idx = for (paths, 0..) |p, idx| {
|
const first_path_idx = for (paths, 0..) |p, idx| {
|
||||||
if (p.len != 0) break idx;
|
if (p.len != 0) break idx;
|
||||||
} else return;
|
} else return;
|
||||||
|
|||||||
@ -1798,11 +1798,11 @@ test "walker" {
|
|||||||
var num_walked: usize = 0;
|
var num_walked: usize = 0;
|
||||||
while (try walker.next()) |entry| {
|
while (try walker.next()) |entry| {
|
||||||
testing.expect(expected_basenames.has(entry.basename)) catch |err| {
|
testing.expect(expected_basenames.has(entry.basename)) catch |err| {
|
||||||
std.debug.print("found unexpected basename: {s}\n", .{std.fmt.fmtSliceEscapeLower(entry.basename)});
|
std.debug.print("found unexpected basename: {f}\n", .{std.ascii.hexEscape(entry.basename, .lower)});
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
testing.expect(expected_paths.has(entry.path)) catch |err| {
|
testing.expect(expected_paths.has(entry.path)) catch |err| {
|
||||||
std.debug.print("found unexpected path: {s}\n", .{std.fmt.fmtSliceEscapeLower(entry.path)});
|
std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)});
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
// make sure that the entry.dir is the containing dir
|
// make sure that the entry.dir is the containing dir
|
||||||
@ -1953,113 +1953,6 @@ test "chown" {
|
|||||||
try dir.chown(null, null);
|
try dir.chown(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "File.Metadata" {
|
|
||||||
var tmp = tmpDir(.{});
|
|
||||||
defer tmp.cleanup();
|
|
||||||
|
|
||||||
const file = try tmp.dir.createFile("test_file", .{ .read = true });
|
|
||||||
defer file.close();
|
|
||||||
|
|
||||||
const metadata = try file.metadata();
|
|
||||||
try testing.expectEqual(File.Kind.file, metadata.kind());
|
|
||||||
try testing.expectEqual(@as(u64, 0), metadata.size());
|
|
||||||
_ = metadata.accessed();
|
|
||||||
_ = metadata.modified();
|
|
||||||
_ = metadata.created();
|
|
||||||
}
|
|
||||||
|
|
||||||
test "File.Permissions" {
|
|
||||||
if (native_os == .wasi)
|
|
||||||
return error.SkipZigTest;
|
|
||||||
|
|
||||||
var tmp = tmpDir(.{});
|
|
||||||
defer tmp.cleanup();
|
|
||||||
|
|
||||||
const file = try tmp.dir.createFile("test_file", .{ .read = true });
|
|
||||||
defer file.close();
|
|
||||||
|
|
||||||
const metadata = try file.metadata();
|
|
||||||
var permissions = metadata.permissions();
|
|
||||||
|
|
||||||
try testing.expect(!permissions.readOnly());
|
|
||||||
permissions.setReadOnly(true);
|
|
||||||
try testing.expect(permissions.readOnly());
|
|
||||||
|
|
||||||
try file.setPermissions(permissions);
|
|
||||||
const new_permissions = (try file.metadata()).permissions();
|
|
||||||
try testing.expect(new_permissions.readOnly());
|
|
||||||
|
|
||||||
// Must be set to non-read-only to delete
|
|
||||||
permissions.setReadOnly(false);
|
|
||||||
try file.setPermissions(permissions);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "File.PermissionsUnix" {
|
|
||||||
if (native_os == .windows or native_os == .wasi)
|
|
||||||
return error.SkipZigTest;
|
|
||||||
|
|
||||||
var tmp = tmpDir(.{});
|
|
||||||
defer tmp.cleanup();
|
|
||||||
|
|
||||||
const file = try tmp.dir.createFile("test_file", .{ .mode = 0o666, .read = true });
|
|
||||||
defer file.close();
|
|
||||||
|
|
||||||
const metadata = try file.metadata();
|
|
||||||
var permissions = metadata.permissions();
|
|
||||||
|
|
||||||
permissions.setReadOnly(true);
|
|
||||||
try testing.expect(permissions.readOnly());
|
|
||||||
try testing.expect(!permissions.inner.unixHas(.user, .write));
|
|
||||||
permissions.inner.unixSet(.user, .{ .write = true });
|
|
||||||
try testing.expect(!permissions.readOnly());
|
|
||||||
try testing.expect(permissions.inner.unixHas(.user, .write));
|
|
||||||
try testing.expect(permissions.inner.mode & 0o400 != 0);
|
|
||||||
|
|
||||||
permissions.setReadOnly(true);
|
|
||||||
try file.setPermissions(permissions);
|
|
||||||
permissions = (try file.metadata()).permissions();
|
|
||||||
try testing.expect(permissions.readOnly());
|
|
||||||
|
|
||||||
// Must be set to non-read-only to delete
|
|
||||||
permissions.setReadOnly(false);
|
|
||||||
try file.setPermissions(permissions);
|
|
||||||
|
|
||||||
const permissions_unix = File.PermissionsUnix.unixNew(0o754);
|
|
||||||
try testing.expect(permissions_unix.unixHas(.user, .execute));
|
|
||||||
try testing.expect(!permissions_unix.unixHas(.other, .execute));
|
|
||||||
}
|
|
||||||
|
|
||||||
test "delete a read-only file on windows" {
|
|
||||||
if (native_os != .windows)
|
|
||||||
return error.SkipZigTest;
|
|
||||||
|
|
||||||
var tmp = testing.tmpDir(.{});
|
|
||||||
defer tmp.cleanup();
|
|
||||||
|
|
||||||
const file = try tmp.dir.createFile("test_file", .{ .read = true });
|
|
||||||
defer file.close();
|
|
||||||
// Create a file and make it read-only
|
|
||||||
const metadata = try file.metadata();
|
|
||||||
var permissions = metadata.permissions();
|
|
||||||
permissions.setReadOnly(true);
|
|
||||||
try file.setPermissions(permissions);
|
|
||||||
|
|
||||||
// If the OS and filesystem support it, POSIX_SEMANTICS and IGNORE_READONLY_ATTRIBUTE
|
|
||||||
// is used meaning that the deletion of a read-only file will succeed.
|
|
||||||
// Otherwise, this delete will fail and the read-only flag must be unset before it's
|
|
||||||
// able to be deleted.
|
|
||||||
const delete_result = tmp.dir.deleteFile("test_file");
|
|
||||||
if (delete_result) {
|
|
||||||
try testing.expectError(error.FileNotFound, tmp.dir.deleteFile("test_file"));
|
|
||||||
} else |err| {
|
|
||||||
try testing.expectEqual(@as(anyerror, error.AccessDenied), err);
|
|
||||||
// Now make the file not read-only
|
|
||||||
permissions.setReadOnly(false);
|
|
||||||
try file.setPermissions(permissions);
|
|
||||||
try tmp.dir.deleteFile("test_file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test "delete a setAsCwd directory on Windows" {
|
test "delete a setAsCwd directory on Windows" {
|
||||||
if (native_os != .windows) return error.SkipZigTest;
|
if (native_os != .windows) return error.SkipZigTest;
|
||||||
|
|
||||||
|
|||||||
@ -346,7 +346,7 @@ fn mode(comptime x: comptime_int) comptime_int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
const stdout = std.fs.File.stdout().writer();
|
const stdout = std.fs.File.stdout().deprecatedWriter();
|
||||||
|
|
||||||
var buffer: [1024]u8 = undefined;
|
var buffer: [1024]u8 = undefined;
|
||||||
var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
|
var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
|
||||||
|
|||||||
@ -436,7 +436,7 @@ pub fn DebugAllocator(comptime config: Config) type {
|
|||||||
const stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc);
|
const stack_trace = bucketStackTrace(bucket, slot_count, slot_index, .alloc);
|
||||||
const page_addr = @intFromPtr(bucket) & ~(page_size - 1);
|
const page_addr = @intFromPtr(bucket) & ~(page_size - 1);
|
||||||
const addr = page_addr + slot_index * size_class;
|
const addr = page_addr + slot_index * size_class;
|
||||||
log.err("memory address 0x{x} leaked: {}", .{ addr, stack_trace });
|
log.err("memory address 0x{x} leaked: {f}", .{ addr, stack_trace });
|
||||||
leaks = true;
|
leaks = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -463,7 +463,7 @@ pub fn DebugAllocator(comptime config: Config) type {
|
|||||||
while (it.next()) |large_alloc| {
|
while (it.next()) |large_alloc| {
|
||||||
if (config.retain_metadata and large_alloc.freed) continue;
|
if (config.retain_metadata and large_alloc.freed) continue;
|
||||||
const stack_trace = large_alloc.getStackTrace(.alloc);
|
const stack_trace = large_alloc.getStackTrace(.alloc);
|
||||||
log.err("memory address 0x{x} leaked: {}", .{
|
log.err("memory address 0x{x} leaked: {f}", .{
|
||||||
@intFromPtr(large_alloc.bytes.ptr), stack_trace,
|
@intFromPtr(large_alloc.bytes.ptr), stack_trace,
|
||||||
});
|
});
|
||||||
leaks = true;
|
leaks = true;
|
||||||
@ -522,7 +522,7 @@ pub fn DebugAllocator(comptime config: Config) type {
|
|||||||
.index = 0,
|
.index = 0,
|
||||||
};
|
};
|
||||||
std.debug.captureStackTrace(ret_addr, &second_free_stack_trace);
|
std.debug.captureStackTrace(ret_addr, &second_free_stack_trace);
|
||||||
log.err("Double free detected. Allocation: {} First free: {} Second free: {}", .{
|
log.err("Double free detected. Allocation: {f} First free: {f} Second free: {f}", .{
|
||||||
alloc_stack_trace, free_stack_trace, second_free_stack_trace,
|
alloc_stack_trace, free_stack_trace, second_free_stack_trace,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -568,7 +568,7 @@ pub fn DebugAllocator(comptime config: Config) type {
|
|||||||
.index = 0,
|
.index = 0,
|
||||||
};
|
};
|
||||||
std.debug.captureStackTrace(ret_addr, &free_stack_trace);
|
std.debug.captureStackTrace(ret_addr, &free_stack_trace);
|
||||||
log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {} Free: {}", .{
|
log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
|
||||||
entry.value_ptr.bytes.len,
|
entry.value_ptr.bytes.len,
|
||||||
old_mem.len,
|
old_mem.len,
|
||||||
entry.value_ptr.getStackTrace(.alloc),
|
entry.value_ptr.getStackTrace(.alloc),
|
||||||
@ -678,7 +678,7 @@ pub fn DebugAllocator(comptime config: Config) type {
|
|||||||
.index = 0,
|
.index = 0,
|
||||||
};
|
};
|
||||||
std.debug.captureStackTrace(ret_addr, &free_stack_trace);
|
std.debug.captureStackTrace(ret_addr, &free_stack_trace);
|
||||||
log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {} Free: {}", .{
|
log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
|
||||||
entry.value_ptr.bytes.len,
|
entry.value_ptr.bytes.len,
|
||||||
old_mem.len,
|
old_mem.len,
|
||||||
entry.value_ptr.getStackTrace(.alloc),
|
entry.value_ptr.getStackTrace(.alloc),
|
||||||
@ -907,7 +907,7 @@ pub fn DebugAllocator(comptime config: Config) type {
|
|||||||
};
|
};
|
||||||
std.debug.captureStackTrace(return_address, &free_stack_trace);
|
std.debug.captureStackTrace(return_address, &free_stack_trace);
|
||||||
if (old_memory.len != requested_size) {
|
if (old_memory.len != requested_size) {
|
||||||
log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {} Free: {}", .{
|
log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
|
||||||
requested_size,
|
requested_size,
|
||||||
old_memory.len,
|
old_memory.len,
|
||||||
bucketStackTrace(bucket, slot_count, slot_index, .alloc),
|
bucketStackTrace(bucket, slot_count, slot_index, .alloc),
|
||||||
@ -915,7 +915,7 @@ pub fn DebugAllocator(comptime config: Config) type {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (alignment != slot_alignment) {
|
if (alignment != slot_alignment) {
|
||||||
log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {} Free: {}", .{
|
log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {f} Free: {f}", .{
|
||||||
slot_alignment.toByteUnits(),
|
slot_alignment.toByteUnits(),
|
||||||
alignment.toByteUnits(),
|
alignment.toByteUnits(),
|
||||||
bucketStackTrace(bucket, slot_count, slot_index, .alloc),
|
bucketStackTrace(bucket, slot_count, slot_index, .alloc),
|
||||||
@ -1006,7 +1006,7 @@ pub fn DebugAllocator(comptime config: Config) type {
|
|||||||
};
|
};
|
||||||
std.debug.captureStackTrace(return_address, &free_stack_trace);
|
std.debug.captureStackTrace(return_address, &free_stack_trace);
|
||||||
if (memory.len != requested_size) {
|
if (memory.len != requested_size) {
|
||||||
log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {} Free: {}", .{
|
log.err("Allocation size {d} bytes does not match free size {d}. Allocation: {f} Free: {f}", .{
|
||||||
requested_size,
|
requested_size,
|
||||||
memory.len,
|
memory.len,
|
||||||
bucketStackTrace(bucket, slot_count, slot_index, .alloc),
|
bucketStackTrace(bucket, slot_count, slot_index, .alloc),
|
||||||
@ -1014,7 +1014,7 @@ pub fn DebugAllocator(comptime config: Config) type {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (alignment != slot_alignment) {
|
if (alignment != slot_alignment) {
|
||||||
log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {} Free: {}", .{
|
log.err("Allocation alignment {d} does not match free alignment {d}. Allocation: {f} Free: {f}", .{
|
||||||
slot_alignment.toByteUnits(),
|
slot_alignment.toByteUnits(),
|
||||||
alignment.toByteUnits(),
|
alignment.toByteUnits(),
|
||||||
bucketStackTrace(bucket, slot_count, slot_index, .alloc),
|
bucketStackTrace(bucket, slot_count, slot_index, .alloc),
|
||||||
@ -1054,7 +1054,7 @@ const TraceKind = enum {
|
|||||||
free,
|
free,
|
||||||
};
|
};
|
||||||
|
|
||||||
const test_config = Config{};
|
const test_config: Config = .{};
|
||||||
|
|
||||||
test "small allocations - free in same order" {
|
test "small allocations - free in same order" {
|
||||||
var gpa = DebugAllocator(test_config){};
|
var gpa = DebugAllocator(test_config){};
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
const builtin = @import("builtin");
|
||||||
|
const std = @import("std.zig");
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
pub const Client = @import("http/Client.zig");
|
pub const Client = @import("http/Client.zig");
|
||||||
pub const Server = @import("http/Server.zig");
|
pub const Server = @import("http/Server.zig");
|
||||||
pub const protocol = @import("http/protocol.zig");
|
pub const protocol = @import("http/protocol.zig");
|
||||||
@ -38,8 +42,9 @@ pub const Method = enum(u64) {
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(self: Method, w: anytype) !void {
|
pub fn format(self: Method, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
|
||||||
const bytes = std.mem.asBytes(&@intFromEnum(self));
|
comptime assert(f.len == 0);
|
||||||
|
const bytes: []const u8 = @ptrCast(&@intFromEnum(self));
|
||||||
const str = std.mem.sliceTo(bytes, 0);
|
const str = std.mem.sliceTo(bytes, 0);
|
||||||
try w.writeAll(str);
|
try w.writeAll(str);
|
||||||
}
|
}
|
||||||
@ -77,7 +82,9 @@ pub const Method = enum(u64) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An HTTP method is idempotent if an identical request can be made once or several times in a row with the same effect while leaving the server in the same state.
|
/// An HTTP method is idempotent if an identical request can be made once
|
||||||
|
/// or several times in a row with the same effect while leaving the server
|
||||||
|
/// in the same state.
|
||||||
///
|
///
|
||||||
/// https://developer.mozilla.org/en-US/docs/Glossary/Idempotent
|
/// https://developer.mozilla.org/en-US/docs/Glossary/Idempotent
|
||||||
///
|
///
|
||||||
@ -90,7 +97,8 @@ pub const Method = enum(u64) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A cacheable response is an HTTP response that can be cached, that is stored to be retrieved and used later, saving a new request to the server.
|
/// A cacheable response can be stored to be retrieved and used later,
|
||||||
|
/// saving a new request to the server.
|
||||||
///
|
///
|
||||||
/// https://developer.mozilla.org/en-US/docs/Glossary/cacheable
|
/// https://developer.mozilla.org/en-US/docs/Glossary/cacheable
|
||||||
///
|
///
|
||||||
@ -282,10 +290,10 @@ pub const Status = enum(u10) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// compression is intentionally omitted here since it is handled in `ContentEncoding`.
|
||||||
pub const TransferEncoding = enum {
|
pub const TransferEncoding = enum {
|
||||||
chunked,
|
chunked,
|
||||||
none,
|
none,
|
||||||
// compression is intentionally omitted here, as std.http.Client stores it as content-encoding
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ContentEncoding = enum {
|
pub const ContentEncoding = enum {
|
||||||
@ -308,9 +316,6 @@ pub const Header = struct {
|
|||||||
value: []const u8,
|
value: []const u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
const builtin = @import("builtin");
|
|
||||||
const std = @import("std.zig");
|
|
||||||
|
|
||||||
test {
|
test {
|
||||||
if (builtin.os.tag != .wasi) {
|
if (builtin.os.tag != .wasi) {
|
||||||
_ = Client;
|
_ = Client;
|
||||||
|
|||||||
@ -823,21 +823,28 @@ pub const Request = struct {
|
|||||||
return error.UnsupportedTransferEncoding;
|
return error.UnsupportedTransferEncoding;
|
||||||
|
|
||||||
const connection = req.connection.?;
|
const connection = req.connection.?;
|
||||||
const w = connection.writer();
|
var connection_writer_adapter = connection.writer().adaptToNewApi();
|
||||||
|
const w = &connection_writer_adapter.new_interface;
|
||||||
|
sendAdapted(req, connection, w) catch |err| switch (err) {
|
||||||
|
error.WriteFailed => return connection_writer_adapter.err.?,
|
||||||
|
else => |e| return e,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
try req.method.write(w);
|
fn sendAdapted(req: *Request, connection: *Connection, w: *std.io.Writer) !void {
|
||||||
|
try req.method.format(w, "");
|
||||||
try w.writeByte(' ');
|
try w.writeByte(' ');
|
||||||
|
|
||||||
if (req.method == .CONNECT) {
|
if (req.method == .CONNECT) {
|
||||||
try req.uri.writeToStream(.{ .authority = true }, w);
|
try req.uri.writeToStream(w, .{ .authority = true });
|
||||||
} else {
|
} else {
|
||||||
try req.uri.writeToStream(.{
|
try req.uri.writeToStream(w, .{
|
||||||
.scheme = connection.proxied,
|
.scheme = connection.proxied,
|
||||||
.authentication = connection.proxied,
|
.authentication = connection.proxied,
|
||||||
.authority = connection.proxied,
|
.authority = connection.proxied,
|
||||||
.path = true,
|
.path = true,
|
||||||
.query = true,
|
.query = true,
|
||||||
}, w);
|
});
|
||||||
}
|
}
|
||||||
try w.writeByte(' ');
|
try w.writeByte(' ');
|
||||||
try w.writeAll(@tagName(req.version));
|
try w.writeAll(@tagName(req.version));
|
||||||
@ -845,7 +852,7 @@ pub const Request = struct {
|
|||||||
|
|
||||||
if (try emitOverridableHeader("host: ", req.headers.host, w)) {
|
if (try emitOverridableHeader("host: ", req.headers.host, w)) {
|
||||||
try w.writeAll("host: ");
|
try w.writeAll("host: ");
|
||||||
try req.uri.writeToStream(.{ .authority = true }, w);
|
try req.uri.writeToStream(w, .{ .authority = true });
|
||||||
try w.writeAll("\r\n");
|
try w.writeAll("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1284,10 +1291,10 @@ pub const basic_authorization = struct {
|
|||||||
|
|
||||||
pub fn valueLengthFromUri(uri: Uri) usize {
|
pub fn valueLengthFromUri(uri: Uri) usize {
|
||||||
var stream = std.io.countingWriter(std.io.null_writer);
|
var stream = std.io.countingWriter(std.io.null_writer);
|
||||||
try stream.writer().print("{user}", .{uri.user orelse Uri.Component.empty});
|
try stream.writer().print("{fuser}", .{uri.user orelse Uri.Component.empty});
|
||||||
const user_len = stream.bytes_written;
|
const user_len = stream.bytes_written;
|
||||||
stream.bytes_written = 0;
|
stream.bytes_written = 0;
|
||||||
try stream.writer().print("{password}", .{uri.password orelse Uri.Component.empty});
|
try stream.writer().print("{fpassword}", .{uri.password orelse Uri.Component.empty});
|
||||||
const password_len = stream.bytes_written;
|
const password_len = stream.bytes_written;
|
||||||
return valueLength(@intCast(user_len), @intCast(password_len));
|
return valueLength(@intCast(user_len), @intCast(password_len));
|
||||||
}
|
}
|
||||||
@ -1295,10 +1302,10 @@ pub const basic_authorization = struct {
|
|||||||
pub fn value(uri: Uri, out: []u8) []u8 {
|
pub fn value(uri: Uri, out: []u8) []u8 {
|
||||||
var buf: [max_user_len + ":".len + max_password_len]u8 = undefined;
|
var buf: [max_user_len + ":".len + max_password_len]u8 = undefined;
|
||||||
var stream = std.io.fixedBufferStream(&buf);
|
var stream = std.io.fixedBufferStream(&buf);
|
||||||
stream.writer().print("{user}", .{uri.user orelse Uri.Component.empty}) catch
|
stream.writer().print("{fuser}", .{uri.user orelse Uri.Component.empty}) catch
|
||||||
unreachable;
|
unreachable;
|
||||||
assert(stream.pos <= max_user_len);
|
assert(stream.pos <= max_user_len);
|
||||||
stream.writer().print(":{password}", .{uri.password orelse Uri.Component.empty}) catch
|
stream.writer().print(":{fpassword}", .{uri.password orelse Uri.Component.empty}) catch
|
||||||
unreachable;
|
unreachable;
|
||||||
|
|
||||||
@memcpy(out[0..prefix.len], prefix);
|
@memcpy(out[0..prefix.len], prefix);
|
||||||
|
|||||||
@ -385,10 +385,8 @@ test "general client/server API coverage" {
|
|||||||
fn handleRequest(request: *http.Server.Request, listen_port: u16) !void {
|
fn handleRequest(request: *http.Server.Request, listen_port: u16) !void {
|
||||||
const log = std.log.scoped(.server);
|
const log = std.log.scoped(.server);
|
||||||
|
|
||||||
log.info("{} {s} {s}", .{
|
log.info("{f} {s} {s}", .{
|
||||||
request.head.method,
|
request.head.method, @tagName(request.head.version), request.head.target,
|
||||||
@tagName(request.head.version),
|
|
||||||
request.head.target,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const gpa = std.testing.allocator;
|
const gpa = std.testing.allocator;
|
||||||
|
|||||||
@ -364,6 +364,32 @@ pub fn GenericWriter(
|
|||||||
const ptr: *const Context = @alignCast(@ptrCast(context));
|
const ptr: *const Context = @alignCast(@ptrCast(context));
|
||||||
return writeFn(ptr.*, bytes);
|
return writeFn(ptr.*, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper for bridging to the new `Writer` API while upgrading.
|
||||||
|
pub fn adaptToNewApi(self: *const Self) Adapter {
|
||||||
|
return .{
|
||||||
|
.derp_writer = self.*,
|
||||||
|
.new_interface = .{
|
||||||
|
.buffer = &.{},
|
||||||
|
.vtable = &.{ .drain = Adapter.drain },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const Adapter = struct {
|
||||||
|
derp_writer: Self,
|
||||||
|
new_interface: Writer,
|
||||||
|
err: ?Error = null,
|
||||||
|
|
||||||
|
fn drain(w: *Writer, data: []const []const u8, splat: usize) Writer.Error!usize {
|
||||||
|
_ = splat;
|
||||||
|
const a: *@This() = @fieldParentPtr("new_interface", w);
|
||||||
|
return a.derp_writer.write(data[0]) catch |err| {
|
||||||
|
a.err = err;
|
||||||
|
return error.WriteFailed;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,7 +445,7 @@ pub const tty = @import("io/tty.zig");
|
|||||||
/// A Writer that doesn't write to anything.
|
/// A Writer that doesn't write to anything.
|
||||||
pub const null_writer: NullWriter = .{ .context = {} };
|
pub const null_writer: NullWriter = .{ .context = {} };
|
||||||
|
|
||||||
pub const NullWriter = Writer(void, error{}, dummyWrite);
|
pub const NullWriter = GenericWriter(void, error{}, dummyWrite);
|
||||||
fn dummyWrite(context: void, data: []const u8) error{}!usize {
|
fn dummyWrite(context: void, data: []const u8) error{}!usize {
|
||||||
_ = context;
|
_ = context;
|
||||||
return data.len;
|
return data.len;
|
||||||
|
|||||||
@ -21,7 +21,7 @@ pub fn writeAll(self: Self, bytes: []const u8) anyerror!void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn print(self: Self, comptime format: []const u8, args: anytype) anyerror!void {
|
pub fn print(self: Self, comptime format: []const u8, args: anytype) anyerror!void {
|
||||||
return std.fmt.format(self, format, args);
|
return std.fmt.deprecatedFormat(self, format, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeByte(self: Self, byte: u8) anyerror!void {
|
pub fn writeByte(self: Self, byte: u8) anyerror!void {
|
||||||
@ -81,3 +81,29 @@ pub fn writeFile(self: Self, file: std.fs.File) anyerror!void {
|
|||||||
if (n < buf.len) return;
|
if (n < buf.len) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper for bridging to the new `Writer` API while upgrading.
|
||||||
|
pub fn adaptToNewApi(self: *const Self) Adapter {
|
||||||
|
return .{
|
||||||
|
.derp_writer = self.*,
|
||||||
|
.new_interface = .{
|
||||||
|
.buffer = &.{},
|
||||||
|
.vtable = &.{ .drain = Adapter.drain },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const Adapter = struct {
|
||||||
|
derp_writer: Self,
|
||||||
|
new_interface: std.io.Writer,
|
||||||
|
err: ?Error = null,
|
||||||
|
|
||||||
|
fn drain(w: *std.io.Writer, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {
|
||||||
|
_ = splat;
|
||||||
|
const a: *@This() = @fieldParentPtr("new_interface", w);
|
||||||
|
return a.derp_writer.write(data[0]) catch |err| {
|
||||||
|
a.err = err;
|
||||||
|
return error.WriteFailed;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@ -26,7 +26,8 @@ pub const VTable = struct {
|
|||||||
/// Returns the number of bytes written, which will be at minimum `0` and
|
/// Returns the number of bytes written, which will be at minimum `0` and
|
||||||
/// at most `limit`. The number returned, including zero, does not indicate
|
/// at most `limit`. The number returned, including zero, does not indicate
|
||||||
/// end of stream. `limit` is guaranteed to be at least as large as the
|
/// end of stream. `limit` is guaranteed to be at least as large as the
|
||||||
/// buffer capacity of `w`.
|
/// buffer capacity of `w`, a value whose minimum size is determined by the
|
||||||
|
/// stream implementation.
|
||||||
///
|
///
|
||||||
/// The reader's internal logical seek position moves forward in accordance
|
/// The reader's internal logical seek position moves forward in accordance
|
||||||
/// with the number of bytes returned from this function.
|
/// with the number of bytes returned from this function.
|
||||||
@ -1243,10 +1244,10 @@ test peekArray {
|
|||||||
|
|
||||||
test discardAll {
|
test discardAll {
|
||||||
var r: Reader = .fixed("foobar");
|
var r: Reader = .fixed("foobar");
|
||||||
try r.discard(3);
|
try r.discardAll(3);
|
||||||
try testing.expectEqualStrings("bar", try r.take(3));
|
try testing.expectEqualStrings("bar", try r.take(3));
|
||||||
try r.discard(0);
|
try r.discardAll(0);
|
||||||
try testing.expectError(error.EndOfStream, r.discard(1));
|
try testing.expectError(error.EndOfStream, r.discardAll(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
test discardRemaining {
|
test discardRemaining {
|
||||||
@ -1355,9 +1356,11 @@ test readVec {
|
|||||||
|
|
||||||
test "expected error.EndOfStream" {
|
test "expected error.EndOfStream" {
|
||||||
// Unit test inspired by https://github.com/ziglang/zig/issues/17733
|
// Unit test inspired by https://github.com/ziglang/zig/issues/17733
|
||||||
var r: std.io.Reader = .fixed("");
|
var buffer: [3]u8 = undefined;
|
||||||
try std.testing.expectError(error.EndOfStream, r.readEnum(enum(u8) { a, b }, .little));
|
var r: std.io.Reader = .fixed(&buffer);
|
||||||
try std.testing.expectError(error.EndOfStream, r.isBytes("foo"));
|
r.end = 0; // capacity 3, but empty
|
||||||
|
try std.testing.expectError(error.EndOfStream, r.takeEnum(enum(u8) { a, b }, .little));
|
||||||
|
try std.testing.expectError(error.EndOfStream, r.take(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn endingStream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
|
fn endingStream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
|
||||||
@ -1389,21 +1392,30 @@ fn failingDiscard(r: *Reader, limit: Limit) Error!usize {
|
|||||||
test "readAlloc when the backing reader provides one byte at a time" {
|
test "readAlloc when the backing reader provides one byte at a time" {
|
||||||
const OneByteReader = struct {
|
const OneByteReader = struct {
|
||||||
str: []const u8,
|
str: []const u8,
|
||||||
curr: usize,
|
i: usize,
|
||||||
|
reader: Reader,
|
||||||
|
|
||||||
fn read(self: *@This(), dest: []u8) usize {
|
fn stream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize {
|
||||||
if (self.str.len <= self.curr or dest.len == 0)
|
assert(@intFromEnum(limit) >= 1);
|
||||||
return 0;
|
const self: *@This() = @fieldParentPtr("reader", r);
|
||||||
|
if (self.str.len - self.i == 0) return error.EndOfStream;
|
||||||
dest[0] = self.str[self.curr];
|
try w.writeByte(self.str[self.i]);
|
||||||
self.curr += 1;
|
self.i += 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const str = "This is a test";
|
const str = "This is a test";
|
||||||
var one_byte_stream: OneByteReader = .init(str);
|
var one_byte_stream: OneByteReader = .{
|
||||||
const res = try one_byte_stream.reader().streamReadAlloc(std.testing.allocator, str.len + 1);
|
.str = str,
|
||||||
|
.i = 0,
|
||||||
|
.reader = .{
|
||||||
|
.buffer = &.{},
|
||||||
|
.vtable = &.{ .stream = OneByteReader.stream },
|
||||||
|
.seek = 0,
|
||||||
|
.end = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const res = try one_byte_stream.reader.allocRemaining(std.testing.allocator, .unlimited);
|
||||||
defer std.testing.allocator.free(res);
|
defer std.testing.allocator.free(res);
|
||||||
try std.testing.expectEqualStrings(str, res);
|
try std.testing.expectEqualStrings(str, res);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,6 +37,10 @@ pub const VTable = struct {
|
|||||||
/// The last element of `data` is repeated as necessary so that it is
|
/// The last element of `data` is repeated as necessary so that it is
|
||||||
/// written `splat` number of times, which may be zero.
|
/// written `splat` number of times, which may be zero.
|
||||||
///
|
///
|
||||||
|
/// This function may not be called if the data to be written could have
|
||||||
|
/// been stored in `buffer` instead, including when the amount of data to
|
||||||
|
/// be written is zero and the buffer capacity is zero.
|
||||||
|
///
|
||||||
/// Number of bytes consumed from `data` is returned, excluding bytes from
|
/// Number of bytes consumed from `data` is returned, excluding bytes from
|
||||||
/// `buffer`.
|
/// `buffer`.
|
||||||
///
|
///
|
||||||
@ -800,18 +804,13 @@ pub fn printValue(
|
|||||||
) Error!void {
|
) Error!void {
|
||||||
const T = @TypeOf(value);
|
const T = @TypeOf(value);
|
||||||
|
|
||||||
if (comptime std.mem.eql(u8, fmt, "*")) {
|
if (comptime std.mem.eql(u8, fmt, "*")) return w.printAddress(value);
|
||||||
return w.printAddress(value);
|
if (fmt.len > 0 and fmt[0] == 'f') return value.format(w, fmt[1..]);
|
||||||
}
|
|
||||||
|
|
||||||
const is_any = comptime std.mem.eql(u8, fmt, ANY);
|
const is_any = comptime std.mem.eql(u8, fmt, ANY);
|
||||||
if (!is_any and std.meta.hasMethod(T, "format")) {
|
if (!is_any and std.meta.hasMethod(T, "format") and fmt.len == 0) {
|
||||||
if (fmt.len > 0 and fmt[0] == 'f') {
|
// after 0.15.0 is tagged, delete this compile error and its condition
|
||||||
return value.format(w, fmt[1..]);
|
@compileError("ambiguous format string; specify {f} to call format method, or {any} to skip it");
|
||||||
} else if (fmt.len == 0) {
|
|
||||||
// after 0.15.0 is tagged, delete the hasMethod condition and this compile error
|
|
||||||
@compileError("ambiguous format string; specify {f} to call format method, or {any} to skip it");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (@typeInfo(T)) {
|
switch (@typeInfo(T)) {
|
||||||
@ -952,9 +951,8 @@ pub fn printValue(
|
|||||||
},
|
},
|
||||||
.pointer => |ptr_info| switch (ptr_info.size) {
|
.pointer => |ptr_info| switch (ptr_info.size) {
|
||||||
.one => switch (@typeInfo(ptr_info.child)) {
|
.one => switch (@typeInfo(ptr_info.child)) {
|
||||||
.array, .@"enum", .@"union", .@"struct" => {
|
.array => |array_info| return w.printValue(fmt, options, @as([]const array_info.child, value), max_depth),
|
||||||
return w.printValue(fmt, options, value.*, max_depth);
|
.@"enum", .@"union", .@"struct" => return w.printValue(fmt, options, value.*, max_depth),
|
||||||
},
|
|
||||||
else => {
|
else => {
|
||||||
var buffers: [2][]const u8 = .{ @typeName(ptr_info.child), "@" };
|
var buffers: [2][]const u8 = .{ @typeName(ptr_info.child), "@" };
|
||||||
try w.writeVecAll(&buffers);
|
try w.writeVecAll(&buffers);
|
||||||
@ -1120,7 +1118,12 @@ pub fn printAscii(w: *Writer, bytes: []const u8, options: std.fmt.Options) Error
|
|||||||
|
|
||||||
pub fn printUnicodeCodepoint(w: *Writer, c: u21, options: std.fmt.Options) Error!void {
|
pub fn printUnicodeCodepoint(w: *Writer, c: u21, options: std.fmt.Options) Error!void {
|
||||||
var buf: [4]u8 = undefined;
|
var buf: [4]u8 = undefined;
|
||||||
const len = try std.unicode.utf8Encode(c, &buf);
|
const len = std.unicode.utf8Encode(c, &buf) catch |err| switch (err) {
|
||||||
|
error.Utf8CannotEncodeSurrogateHalf, error.CodepointTooLarge => l: {
|
||||||
|
buf[0..3].* = std.unicode.replacement_character_utf8;
|
||||||
|
break :l 3;
|
||||||
|
},
|
||||||
|
};
|
||||||
return w.alignBufferOptions(buf[0..len], options);
|
return w.alignBufferOptions(buf[0..len], options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1553,13 +1556,7 @@ test "formatValue max_depth" {
|
|||||||
x: f32,
|
x: f32,
|
||||||
y: f32,
|
y: f32,
|
||||||
|
|
||||||
pub fn format(
|
pub fn format(self: SelfType, w: *Writer, comptime fmt: []const u8) Error!void {
|
||||||
self: SelfType,
|
|
||||||
comptime fmt: []const u8,
|
|
||||||
options: std.fmt.Options,
|
|
||||||
w: *Writer,
|
|
||||||
) Error!void {
|
|
||||||
_ = options;
|
|
||||||
if (fmt.len == 0) {
|
if (fmt.len == 0) {
|
||||||
return w.print("({d:.3},{d:.3})", .{ self.x, self.y });
|
return w.print("({d:.3},{d:.3})", .{ self.x, self.y });
|
||||||
} else {
|
} else {
|
||||||
@ -1600,131 +1597,131 @@ test "formatValue max_depth" {
|
|||||||
try w.printValue("", .{}, inst, 0);
|
try w.printValue("", .{}, inst, 0);
|
||||||
try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ ... }", w.buffered());
|
try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ ... }", w.buffered());
|
||||||
|
|
||||||
w.reset();
|
w = .fixed(&buf);
|
||||||
try w.printValue("", .{}, inst, 1);
|
try w.printValue("", .{}, inst, 1);
|
||||||
try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ ... }, .tu = io.Writer.test.printValue max_depth.TU{ ... }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", w.buffered());
|
try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ ... }, .tu = io.Writer.test.printValue max_depth.TU{ ... }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", w.buffered());
|
||||||
|
|
||||||
w.reset();
|
w = .fixed(&buf);
|
||||||
try w.printValue("", .{}, inst, 2);
|
try w.printValue("", .{}, inst, 2);
|
||||||
try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ ... }, .tu = io.Writer.test.printValue max_depth.TU{ ... }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ ... } }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", w.buffered());
|
try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ ... }, .tu = io.Writer.test.printValue max_depth.TU{ ... }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ ... } }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", w.buffered());
|
||||||
|
|
||||||
w.reset();
|
w = .fixed(&buf);
|
||||||
try w.printValue("", .{}, inst, 3);
|
try w.printValue("", .{}, inst, 3);
|
||||||
try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ ... }, .tu = io.Writer.test.printValue max_depth.TU{ ... }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ ... } }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ ... } } }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", w.buffered());
|
try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ ... }, .tu = io.Writer.test.printValue max_depth.TU{ ... }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ ... } }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ ... } } }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", w.buffered());
|
||||||
|
|
||||||
const vec: @Vector(4, i32) = .{ 1, 2, 3, 4 };
|
const vec: @Vector(4, i32) = .{ 1, 2, 3, 4 };
|
||||||
w.reset();
|
w = .fixed(&buf);
|
||||||
try w.printValue("", .{}, vec, 0);
|
try w.printValue("", .{}, vec, 0);
|
||||||
try testing.expectEqualStrings("{ ... }", w.buffered());
|
try testing.expectEqualStrings("{ ... }", w.buffered());
|
||||||
|
|
||||||
w.reset();
|
w = .fixed(&buf);
|
||||||
try w.printValue("", .{}, vec, 1);
|
try w.printValue("", .{}, vec, 1);
|
||||||
try testing.expectEqualStrings("{ 1, 2, 3, 4 }", w.buffered());
|
try testing.expectEqualStrings("{ 1, 2, 3, 4 }", w.buffered());
|
||||||
}
|
}
|
||||||
|
|
||||||
test printDuration {
|
test printDuration {
|
||||||
testDurationCase("0ns", 0);
|
try testDurationCase("0ns", 0);
|
||||||
testDurationCase("1ns", 1);
|
try testDurationCase("1ns", 1);
|
||||||
testDurationCase("999ns", std.time.ns_per_us - 1);
|
try testDurationCase("999ns", std.time.ns_per_us - 1);
|
||||||
testDurationCase("1us", std.time.ns_per_us);
|
try testDurationCase("1us", std.time.ns_per_us);
|
||||||
testDurationCase("1.45us", 1450);
|
try testDurationCase("1.45us", 1450);
|
||||||
testDurationCase("1.5us", 3 * std.time.ns_per_us / 2);
|
try testDurationCase("1.5us", 3 * std.time.ns_per_us / 2);
|
||||||
testDurationCase("14.5us", 14500);
|
try testDurationCase("14.5us", 14500);
|
||||||
testDurationCase("145us", 145000);
|
try testDurationCase("145us", 145000);
|
||||||
testDurationCase("999.999us", std.time.ns_per_ms - 1);
|
try testDurationCase("999.999us", std.time.ns_per_ms - 1);
|
||||||
testDurationCase("1ms", std.time.ns_per_ms + 1);
|
try testDurationCase("1ms", std.time.ns_per_ms + 1);
|
||||||
testDurationCase("1.5ms", 3 * std.time.ns_per_ms / 2);
|
try testDurationCase("1.5ms", 3 * std.time.ns_per_ms / 2);
|
||||||
testDurationCase("1.11ms", 1110000);
|
try testDurationCase("1.11ms", 1110000);
|
||||||
testDurationCase("1.111ms", 1111000);
|
try testDurationCase("1.111ms", 1111000);
|
||||||
testDurationCase("1.111ms", 1111100);
|
try testDurationCase("1.111ms", 1111100);
|
||||||
testDurationCase("999.999ms", std.time.ns_per_s - 1);
|
try testDurationCase("999.999ms", std.time.ns_per_s - 1);
|
||||||
testDurationCase("1s", std.time.ns_per_s);
|
try testDurationCase("1s", std.time.ns_per_s);
|
||||||
testDurationCase("59.999s", std.time.ns_per_min - 1);
|
try testDurationCase("59.999s", std.time.ns_per_min - 1);
|
||||||
testDurationCase("1m", std.time.ns_per_min);
|
try testDurationCase("1m", std.time.ns_per_min);
|
||||||
testDurationCase("1h", std.time.ns_per_hour);
|
try testDurationCase("1h", std.time.ns_per_hour);
|
||||||
testDurationCase("1d", std.time.ns_per_day);
|
try testDurationCase("1d", std.time.ns_per_day);
|
||||||
testDurationCase("1w", std.time.ns_per_week);
|
try testDurationCase("1w", std.time.ns_per_week);
|
||||||
testDurationCase("1y", 365 * std.time.ns_per_day);
|
try testDurationCase("1y", 365 * std.time.ns_per_day);
|
||||||
testDurationCase("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w1
|
try testDurationCase("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w1
|
||||||
testDurationCase("1y1h1.001s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms);
|
try testDurationCase("1y1h1.001s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms);
|
||||||
testDurationCase("1y1h1s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us);
|
try testDurationCase("1y1h1s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us);
|
||||||
testDurationCase("1y1h999.999us", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1);
|
try testDurationCase("1y1h999.999us", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1);
|
||||||
testDurationCase("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms);
|
try testDurationCase("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms);
|
||||||
testDurationCase("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1);
|
try testDurationCase("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1);
|
||||||
testDurationCase("1y1m999ns", 365 * std.time.ns_per_day + std.time.ns_per_min + 999);
|
try testDurationCase("1y1m999ns", 365 * std.time.ns_per_day + std.time.ns_per_min + 999);
|
||||||
testDurationCase("584y49w23h34m33.709s", std.math.maxInt(u64));
|
try testDurationCase("584y49w23h34m33.709s", std.math.maxInt(u64));
|
||||||
|
|
||||||
testing.expectFmt("=======0ns", "{D:=>10}", .{0});
|
try testing.expectFmt("=======0ns", "{D:=>10}", .{0});
|
||||||
testing.expectFmt("1ns=======", "{D:=<10}", .{1});
|
try testing.expectFmt("1ns=======", "{D:=<10}", .{1});
|
||||||
testing.expectFmt(" 999ns ", "{D:^10}", .{std.time.ns_per_us - 1});
|
try testing.expectFmt(" 999ns ", "{D:^10}", .{std.time.ns_per_us - 1});
|
||||||
}
|
}
|
||||||
|
|
||||||
test printDurationSigned {
|
test printDurationSigned {
|
||||||
testDurationCaseSigned("0ns", 0);
|
try testDurationCaseSigned("0ns", 0);
|
||||||
testDurationCaseSigned("1ns", 1);
|
try testDurationCaseSigned("1ns", 1);
|
||||||
testDurationCaseSigned("-1ns", -(1));
|
try testDurationCaseSigned("-1ns", -(1));
|
||||||
testDurationCaseSigned("999ns", std.time.ns_per_us - 1);
|
try testDurationCaseSigned("999ns", std.time.ns_per_us - 1);
|
||||||
testDurationCaseSigned("-999ns", -(std.time.ns_per_us - 1));
|
try testDurationCaseSigned("-999ns", -(std.time.ns_per_us - 1));
|
||||||
testDurationCaseSigned("1us", std.time.ns_per_us);
|
try testDurationCaseSigned("1us", std.time.ns_per_us);
|
||||||
testDurationCaseSigned("-1us", -(std.time.ns_per_us));
|
try testDurationCaseSigned("-1us", -(std.time.ns_per_us));
|
||||||
testDurationCaseSigned("1.45us", 1450);
|
try testDurationCaseSigned("1.45us", 1450);
|
||||||
testDurationCaseSigned("-1.45us", -(1450));
|
try testDurationCaseSigned("-1.45us", -(1450));
|
||||||
testDurationCaseSigned("1.5us", 3 * std.time.ns_per_us / 2);
|
try testDurationCaseSigned("1.5us", 3 * std.time.ns_per_us / 2);
|
||||||
testDurationCaseSigned("-1.5us", -(3 * std.time.ns_per_us / 2));
|
try testDurationCaseSigned("-1.5us", -(3 * std.time.ns_per_us / 2));
|
||||||
testDurationCaseSigned("14.5us", 14500);
|
try testDurationCaseSigned("14.5us", 14500);
|
||||||
testDurationCaseSigned("-14.5us", -(14500));
|
try testDurationCaseSigned("-14.5us", -(14500));
|
||||||
testDurationCaseSigned("145us", 145000);
|
try testDurationCaseSigned("145us", 145000);
|
||||||
testDurationCaseSigned("-145us", -(145000));
|
try testDurationCaseSigned("-145us", -(145000));
|
||||||
testDurationCaseSigned("999.999us", std.time.ns_per_ms - 1);
|
try testDurationCaseSigned("999.999us", std.time.ns_per_ms - 1);
|
||||||
testDurationCaseSigned("-999.999us", -(std.time.ns_per_ms - 1));
|
try testDurationCaseSigned("-999.999us", -(std.time.ns_per_ms - 1));
|
||||||
testDurationCaseSigned("1ms", std.time.ns_per_ms + 1);
|
try testDurationCaseSigned("1ms", std.time.ns_per_ms + 1);
|
||||||
testDurationCaseSigned("-1ms", -(std.time.ns_per_ms + 1));
|
try testDurationCaseSigned("-1ms", -(std.time.ns_per_ms + 1));
|
||||||
testDurationCaseSigned("1.5ms", 3 * std.time.ns_per_ms / 2);
|
try testDurationCaseSigned("1.5ms", 3 * std.time.ns_per_ms / 2);
|
||||||
testDurationCaseSigned("-1.5ms", -(3 * std.time.ns_per_ms / 2));
|
try testDurationCaseSigned("-1.5ms", -(3 * std.time.ns_per_ms / 2));
|
||||||
testDurationCaseSigned("1.11ms", 1110000);
|
try testDurationCaseSigned("1.11ms", 1110000);
|
||||||
testDurationCaseSigned("-1.11ms", -(1110000));
|
try testDurationCaseSigned("-1.11ms", -(1110000));
|
||||||
testDurationCaseSigned("1.111ms", 1111000);
|
try testDurationCaseSigned("1.111ms", 1111000);
|
||||||
testDurationCaseSigned("-1.111ms", -(1111000));
|
try testDurationCaseSigned("-1.111ms", -(1111000));
|
||||||
testDurationCaseSigned("1.111ms", 1111100);
|
try testDurationCaseSigned("1.111ms", 1111100);
|
||||||
testDurationCaseSigned("-1.111ms", -(1111100));
|
try testDurationCaseSigned("-1.111ms", -(1111100));
|
||||||
testDurationCaseSigned("999.999ms", std.time.ns_per_s - 1);
|
try testDurationCaseSigned("999.999ms", std.time.ns_per_s - 1);
|
||||||
testDurationCaseSigned("-999.999ms", -(std.time.ns_per_s - 1));
|
try testDurationCaseSigned("-999.999ms", -(std.time.ns_per_s - 1));
|
||||||
testDurationCaseSigned("1s", std.time.ns_per_s);
|
try testDurationCaseSigned("1s", std.time.ns_per_s);
|
||||||
testDurationCaseSigned("-1s", -(std.time.ns_per_s));
|
try testDurationCaseSigned("-1s", -(std.time.ns_per_s));
|
||||||
testDurationCaseSigned("59.999s", std.time.ns_per_min - 1);
|
try testDurationCaseSigned("59.999s", std.time.ns_per_min - 1);
|
||||||
testDurationCaseSigned("-59.999s", -(std.time.ns_per_min - 1));
|
try testDurationCaseSigned("-59.999s", -(std.time.ns_per_min - 1));
|
||||||
testDurationCaseSigned("1m", std.time.ns_per_min);
|
try testDurationCaseSigned("1m", std.time.ns_per_min);
|
||||||
testDurationCaseSigned("-1m", -(std.time.ns_per_min));
|
try testDurationCaseSigned("-1m", -(std.time.ns_per_min));
|
||||||
testDurationCaseSigned("1h", std.time.ns_per_hour);
|
try testDurationCaseSigned("1h", std.time.ns_per_hour);
|
||||||
testDurationCaseSigned("-1h", -(std.time.ns_per_hour));
|
try testDurationCaseSigned("-1h", -(std.time.ns_per_hour));
|
||||||
testDurationCaseSigned("1d", std.time.ns_per_day);
|
try testDurationCaseSigned("1d", std.time.ns_per_day);
|
||||||
testDurationCaseSigned("-1d", -(std.time.ns_per_day));
|
try testDurationCaseSigned("-1d", -(std.time.ns_per_day));
|
||||||
testDurationCaseSigned("1w", std.time.ns_per_week);
|
try testDurationCaseSigned("1w", std.time.ns_per_week);
|
||||||
testDurationCaseSigned("-1w", -(std.time.ns_per_week));
|
try testDurationCaseSigned("-1w", -(std.time.ns_per_week));
|
||||||
testDurationCaseSigned("1y", 365 * std.time.ns_per_day);
|
try testDurationCaseSigned("1y", 365 * std.time.ns_per_day);
|
||||||
testDurationCaseSigned("-1y", -(365 * std.time.ns_per_day));
|
try testDurationCaseSigned("-1y", -(365 * std.time.ns_per_day));
|
||||||
testDurationCaseSigned("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w1d
|
try testDurationCaseSigned("1y52w23h59m59.999s", 730 * std.time.ns_per_day - 1); // 365d = 52w1d
|
||||||
testDurationCaseSigned("-1y52w23h59m59.999s", -(730 * std.time.ns_per_day - 1)); // 365d = 52w1d
|
try testDurationCaseSigned("-1y52w23h59m59.999s", -(730 * std.time.ns_per_day - 1)); // 365d = 52w1d
|
||||||
testDurationCaseSigned("1y1h1.001s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms);
|
try testDurationCaseSigned("1y1h1.001s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms);
|
||||||
testDurationCaseSigned("-1y1h1.001s", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms));
|
try testDurationCaseSigned("-1y1h1.001s", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms));
|
||||||
testDurationCaseSigned("1y1h1s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us);
|
try testDurationCaseSigned("1y1h1s", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us);
|
||||||
testDurationCaseSigned("-1y1h1s", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us));
|
try testDurationCaseSigned("-1y1h1s", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us));
|
||||||
testDurationCaseSigned("1y1h999.999us", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1);
|
try testDurationCaseSigned("1y1h999.999us", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1);
|
||||||
testDurationCaseSigned("-1y1h999.999us", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1));
|
try testDurationCaseSigned("-1y1h999.999us", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1));
|
||||||
testDurationCaseSigned("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms);
|
try testDurationCaseSigned("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms);
|
||||||
testDurationCaseSigned("-1y1h1ms", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms));
|
try testDurationCaseSigned("-1y1h1ms", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms));
|
||||||
testDurationCaseSigned("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1);
|
try testDurationCaseSigned("1y1h1ms", 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1);
|
||||||
testDurationCaseSigned("-1y1h1ms", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1));
|
try testDurationCaseSigned("-1y1h1ms", -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1));
|
||||||
testDurationCaseSigned("1y1m999ns", 365 * std.time.ns_per_day + std.time.ns_per_min + 999);
|
try testDurationCaseSigned("1y1m999ns", 365 * std.time.ns_per_day + std.time.ns_per_min + 999);
|
||||||
testDurationCaseSigned("-1y1m999ns", -(365 * std.time.ns_per_day + std.time.ns_per_min + 999));
|
try testDurationCaseSigned("-1y1m999ns", -(365 * std.time.ns_per_day + std.time.ns_per_min + 999));
|
||||||
testDurationCaseSigned("292y24w3d23h47m16.854s", std.math.maxInt(i64));
|
try testDurationCaseSigned("292y24w3d23h47m16.854s", std.math.maxInt(i64));
|
||||||
testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64) + 1);
|
try testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64) + 1);
|
||||||
testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64));
|
try testDurationCaseSigned("-292y24w3d23h47m16.854s", std.math.minInt(i64));
|
||||||
|
|
||||||
testing.expectFmt("=======0ns", "{s:=>10}", .{0});
|
try testing.expectFmt("=======0ns", "{D:=>10}", .{0});
|
||||||
testing.expectFmt("1ns=======", "{s:=<10}", .{1});
|
try testing.expectFmt("1ns=======", "{D:=<10}", .{1});
|
||||||
testing.expectFmt("-1ns======", "{s:=<10}", .{-(1)});
|
try testing.expectFmt("-1ns======", "{D:=<10}", .{-(1)});
|
||||||
testing.expectFmt(" -999ns ", "{s:^10}", .{-(std.time.ns_per_us - 1)});
|
try testing.expectFmt(" -999ns ", "{D:^10}", .{-(std.time.ns_per_us - 1)});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testDurationCase(expected: []const u8, input: u64) !void {
|
fn testDurationCase(expected: []const u8, input: u64) !void {
|
||||||
@ -1762,7 +1759,7 @@ test printIntOptions {
|
|||||||
test "printInt with comptime_int" {
|
test "printInt with comptime_int" {
|
||||||
var buf: [20]u8 = undefined;
|
var buf: [20]u8 = undefined;
|
||||||
var w: Writer = .fixed(&buf);
|
var w: Writer = .fixed(&buf);
|
||||||
try w.printInt(@as(comptime_int, 123456789123456789), "", .{});
|
try w.printInt("", .{}, @as(comptime_int, 123456789123456789));
|
||||||
try std.testing.expectEqualStrings("123456789123456789", w.buffered());
|
try std.testing.expectEqualStrings("123456789123456789", w.buffered());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1777,7 +1774,7 @@ test "printFloat with comptime_float" {
|
|||||||
fn testPrintIntCase(expected: []const u8, value: anytype, base: u8, case: std.fmt.Case, options: std.fmt.Options) !void {
|
fn testPrintIntCase(expected: []const u8, value: anytype, base: u8, case: std.fmt.Case, options: std.fmt.Options) !void {
|
||||||
var buffer: [100]u8 = undefined;
|
var buffer: [100]u8 = undefined;
|
||||||
var w: Writer = .fixed(&buffer);
|
var w: Writer = .fixed(&buffer);
|
||||||
w.printIntOptions(value, base, case, options);
|
try w.printIntOptions(value, base, case, options);
|
||||||
try testing.expectEqualStrings(expected, w.buffered());
|
try testing.expectEqualStrings(expected, w.buffered());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1832,17 +1829,15 @@ test "fixed output" {
|
|||||||
try w.writeAll("world");
|
try w.writeAll("world");
|
||||||
try testing.expect(std.mem.eql(u8, w.buffered(), "Helloworld"));
|
try testing.expect(std.mem.eql(u8, w.buffered(), "Helloworld"));
|
||||||
|
|
||||||
try testing.expectError(error.WriteStreamEnd, w.writeAll("!"));
|
try testing.expectError(error.WriteFailed, w.writeAll("!"));
|
||||||
try testing.expect(std.mem.eql(u8, w.buffered(), "Helloworld"));
|
try testing.expect(std.mem.eql(u8, w.buffered(), "Helloworld"));
|
||||||
|
|
||||||
w.reset();
|
w = .fixed(&buffer);
|
||||||
|
|
||||||
try testing.expect(w.buffered().len == 0);
|
try testing.expect(w.buffered().len == 0);
|
||||||
|
|
||||||
try testing.expectError(error.WriteStreamEnd, w.writeAll("Hello world!"));
|
try testing.expectError(error.WriteFailed, w.writeAll("Hello world!"));
|
||||||
try testing.expect(std.mem.eql(u8, w.buffered(), "Hello worl"));
|
try testing.expect(std.mem.eql(u8, w.buffered(), "Hello worl"));
|
||||||
|
|
||||||
try w.seekTo((try w.getEndPos()) + 1);
|
|
||||||
try testing.expectError(error.WriteStreamEnd, w.writeAll("H"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn failingDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
|
pub fn failingDrain(w: *Writer, data: []const []const u8, splat: usize) Error!usize {
|
||||||
|
|||||||
@ -33,7 +33,7 @@ pub const BufferedAtomicFile = struct {
|
|||||||
self.atomic_file = try dir.atomicFile(dest_path, atomic_file_options);
|
self.atomic_file = try dir.atomicFile(dest_path, atomic_file_options);
|
||||||
errdefer self.atomic_file.deinit();
|
errdefer self.atomic_file.deinit();
|
||||||
|
|
||||||
self.file_writer = self.atomic_file.file.writer();
|
self.file_writer = self.atomic_file.file.deprecatedWriter();
|
||||||
self.buffered_writer = .{ .unbuffered_writer = self.file_writer };
|
self.buffered_writer = .{ .unbuffered_writer = self.file_writer };
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@ test "write a file, read it, then delete it" {
|
|||||||
var file = try tmp.dir.createFile(tmp_file_name, .{});
|
var file = try tmp.dir.createFile(tmp_file_name, .{});
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
var buf_stream = io.bufferedWriter(file.writer());
|
var buf_stream = io.bufferedWriter(file.deprecatedWriter());
|
||||||
const st = buf_stream.writer();
|
const st = buf_stream.writer();
|
||||||
try st.print("begin", .{});
|
try st.print("begin", .{});
|
||||||
try st.writeAll(data[0..]);
|
try st.writeAll(data[0..]);
|
||||||
@ -45,7 +45,7 @@ test "write a file, read it, then delete it" {
|
|||||||
const expected_file_size: u64 = "begin".len + data.len + "end".len;
|
const expected_file_size: u64 = "begin".len + data.len + "end".len;
|
||||||
try expectEqual(expected_file_size, file_size);
|
try expectEqual(expected_file_size, file_size);
|
||||||
|
|
||||||
var buf_stream = io.bufferedReader(file.reader());
|
var buf_stream = io.bufferedReader(file.deprecatedReader());
|
||||||
const st = buf_stream.reader();
|
const st = buf_stream.reader();
|
||||||
const contents = try st.readAllAlloc(std.testing.allocator, 2 * 1024);
|
const contents = try st.readAllAlloc(std.testing.allocator, 2 * 1024);
|
||||||
defer std.testing.allocator.free(contents);
|
defer std.testing.allocator.free(contents);
|
||||||
@ -66,7 +66,7 @@ test "BitStreams with File Stream" {
|
|||||||
var file = try tmp.dir.createFile(tmp_file_name, .{});
|
var file = try tmp.dir.createFile(tmp_file_name, .{});
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
var bit_stream = io.bitWriter(native_endian, file.writer());
|
var bit_stream = io.bitWriter(native_endian, file.deprecatedWriter());
|
||||||
|
|
||||||
try bit_stream.writeBits(@as(u2, 1), 1);
|
try bit_stream.writeBits(@as(u2, 1), 1);
|
||||||
try bit_stream.writeBits(@as(u5, 2), 2);
|
try bit_stream.writeBits(@as(u5, 2), 2);
|
||||||
@ -80,7 +80,7 @@ test "BitStreams with File Stream" {
|
|||||||
var file = try tmp.dir.openFile(tmp_file_name, .{});
|
var file = try tmp.dir.openFile(tmp_file_name, .{});
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
var bit_stream = io.bitReader(native_endian, file.reader());
|
var bit_stream = io.bitReader(native_endian, file.deprecatedReader());
|
||||||
|
|
||||||
var out_bits: u16 = undefined;
|
var out_bits: u16 = undefined;
|
||||||
|
|
||||||
|
|||||||
@ -56,7 +56,7 @@ pub const Value = union(enum) {
|
|||||||
std.debug.lockStdErr();
|
std.debug.lockStdErr();
|
||||||
defer std.debug.unlockStdErr();
|
defer std.debug.unlockStdErr();
|
||||||
|
|
||||||
const stderr = std.fs.File.stderr().writer();
|
const stderr = std.fs.File.stderr().deprecatedWriter();
|
||||||
stringify(self, .{}, stderr) catch return;
|
stringify(self, .{}, stderr) catch return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("../std.zig");
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
const stringify = @import("stringify.zig").stringify;
|
const stringify = @import("stringify.zig").stringify;
|
||||||
const StringifyOptions = @import("stringify.zig").StringifyOptions;
|
const StringifyOptions = @import("stringify.zig").StringifyOptions;
|
||||||
@ -14,14 +15,8 @@ pub fn Formatter(comptime T: type) type {
|
|||||||
value: T,
|
value: T,
|
||||||
options: StringifyOptions,
|
options: StringifyOptions,
|
||||||
|
|
||||||
pub fn format(
|
pub fn format(self: @This(), writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
|
||||||
self: @This(),
|
comptime assert(f.len == 0);
|
||||||
comptime fmt_spec: []const u8,
|
|
||||||
options: std.fmt.FormatOptions,
|
|
||||||
writer: anytype,
|
|
||||||
) !void {
|
|
||||||
_ = fmt_spec;
|
|
||||||
_ = options;
|
|
||||||
try stringify(self.value, self.options, writer);
|
try stringify(self.value, self.options, writer);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -689,7 +689,8 @@ fn outputUnicodeEscape(codepoint: u21, out_stream: anytype) !void {
|
|||||||
// 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 out_stream.writeAll("\\u");
|
try out_stream.writeAll("\\u");
|
||||||
try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
|
//try w.printInt("x", .{ .width = 4, .fill = '0' }, codepoint);
|
||||||
|
try std.fmt.deprecatedFormat(out_stream, "{x:0>4}", .{codepoint});
|
||||||
} else {
|
} else {
|
||||||
assert(codepoint <= 0x10FFFF);
|
assert(codepoint <= 0x10FFFF);
|
||||||
// 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,
|
||||||
@ -697,9 +698,11 @@ fn outputUnicodeEscape(codepoint: u21, out_stream: anytype) !void {
|
|||||||
const high = @as(u16, @intCast((codepoint - 0x10000) >> 10)) + 0xD800;
|
const high = @as(u16, @intCast((codepoint - 0x10000) >> 10)) + 0xD800;
|
||||||
const low = @as(u16, @intCast(codepoint & 0x3FF)) + 0xDC00;
|
const low = @as(u16, @intCast(codepoint & 0x3FF)) + 0xDC00;
|
||||||
try out_stream.writeAll("\\u");
|
try out_stream.writeAll("\\u");
|
||||||
try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
|
//try w.printInt("x", .{ .width = 4, .fill = '0' }, high);
|
||||||
|
try std.fmt.deprecatedFormat(out_stream, "{x:0>4}", .{high});
|
||||||
try out_stream.writeAll("\\u");
|
try out_stream.writeAll("\\u");
|
||||||
try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
|
//try w.printInt("x", .{ .width = 4, .fill = '0' }, low);
|
||||||
|
try std.fmt.deprecatedFormat(out_stream, "{x:0>4}", .{low});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -47,7 +47,7 @@
|
|||||||
//! // Print the message to stderr, silently ignoring any errors
|
//! // Print the message to stderr, silently ignoring any errors
|
||||||
//! std.debug.lockStdErr();
|
//! std.debug.lockStdErr();
|
||||||
//! defer std.debug.unlockStdErr();
|
//! defer std.debug.unlockStdErr();
|
||||||
//! const stderr = std.fs.File.stderr().writer();
|
//! const stderr = std.fs.File.stderr().deprecatedWriter();
|
||||||
//! nosuspend stderr.print(prefix ++ format ++ "\n", args) catch return;
|
//! nosuspend stderr.print(prefix ++ format ++ "\n", args) catch return;
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
@ -148,7 +148,7 @@ pub fn defaultLog(
|
|||||||
) void {
|
) void {
|
||||||
const level_txt = comptime message_level.asText();
|
const level_txt = comptime message_level.asText();
|
||||||
const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";
|
const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";
|
||||||
const stderr = std.fs.File.stderr().writer();
|
const stderr = std.fs.File.stderr().deprecatedWriter();
|
||||||
var bw = std.io.bufferedWriter(stderr);
|
var bw = std.io.bufferedWriter(stderr);
|
||||||
const writer = bw.writer();
|
const writer = bw.writer();
|
||||||
|
|
||||||
|
|||||||
@ -2322,13 +2322,7 @@ pub const Const = struct {
|
|||||||
/// this function will fail to print the string, printing "(BigInt)" instead of a number.
|
/// this function will fail to print the string, printing "(BigInt)" instead of a number.
|
||||||
/// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.
|
/// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.
|
||||||
/// See `toString` and `toStringAlloc` for a way to print big integers without failure.
|
/// See `toString` and `toStringAlloc` for a way to print big integers without failure.
|
||||||
pub fn format(
|
pub fn format(self: Const, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
|
||||||
self: Const,
|
|
||||||
comptime fmt: []const u8,
|
|
||||||
options: std.fmt.FormatOptions,
|
|
||||||
out_stream: anytype,
|
|
||||||
) !void {
|
|
||||||
_ = options;
|
|
||||||
comptime var base = 10;
|
comptime var base = 10;
|
||||||
comptime var case: std.fmt.Case = .lower;
|
comptime var case: std.fmt.Case = .lower;
|
||||||
|
|
||||||
@ -2350,7 +2344,7 @@ pub const Const = struct {
|
|||||||
|
|
||||||
const available_len = 64;
|
const available_len = 64;
|
||||||
if (self.limbs.len > available_len)
|
if (self.limbs.len > available_len)
|
||||||
return out_stream.writeAll("(BigInt)");
|
return w.writeAll("(BigInt)");
|
||||||
|
|
||||||
var limbs: [calcToStringLimbsBufferLen(available_len, base)]Limb = undefined;
|
var limbs: [calcToStringLimbsBufferLen(available_len, base)]Limb = undefined;
|
||||||
|
|
||||||
@ -2360,7 +2354,7 @@ pub const Const = struct {
|
|||||||
};
|
};
|
||||||
var buf: [biggest.sizeInBaseUpperBound(base)]u8 = undefined;
|
var buf: [biggest.sizeInBaseUpperBound(base)]u8 = undefined;
|
||||||
const len = self.toString(&buf, base, case, &limbs);
|
const len = self.toString(&buf, base, case, &limbs);
|
||||||
return out_stream.writeAll(buf[0..len]);
|
return w.writeAll(buf[0..len]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts self to a string in the requested base.
|
/// Converts self to a string in the requested base.
|
||||||
@ -2934,13 +2928,8 @@ pub const Managed = struct {
|
|||||||
/// this function will fail to print the string, printing "(BigInt)" instead of a number.
|
/// this function will fail to print the string, printing "(BigInt)" instead of a number.
|
||||||
/// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.
|
/// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.
|
||||||
/// See `toString` and `toStringAlloc` for a way to print big integers without failure.
|
/// See `toString` and `toStringAlloc` for a way to print big integers without failure.
|
||||||
pub fn format(
|
pub fn format(self: Managed, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
|
||||||
self: Managed,
|
return self.toConst().format(w, f);
|
||||||
comptime fmt: []const u8,
|
|
||||||
options: std.fmt.FormatOptions,
|
|
||||||
out_stream: anytype,
|
|
||||||
) !void {
|
|
||||||
return self.toConst().format(fmt, options, out_stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns math.Order.lt, math.Order.eq, math.Order.gt if |a| < |b|, |a| ==
|
/// Returns math.Order.lt, math.Order.eq, math.Order.gt if |a| < |b|, |a| ==
|
||||||
|
|||||||
@ -3813,10 +3813,10 @@ test "(BigInt) positive" {
|
|||||||
try a.pow(&a, 64 * @sizeOf(Limb) * 8);
|
try a.pow(&a, 64 * @sizeOf(Limb) * 8);
|
||||||
try b.sub(&a, &c);
|
try b.sub(&a, &c);
|
||||||
|
|
||||||
const a_fmt = try std.fmt.allocPrintZ(testing.allocator, "{d}", .{a});
|
const a_fmt = try std.fmt.allocPrintSentinel(testing.allocator, "{fd}", .{a}, 0);
|
||||||
defer testing.allocator.free(a_fmt);
|
defer testing.allocator.free(a_fmt);
|
||||||
|
|
||||||
const b_fmt = try std.fmt.allocPrintZ(testing.allocator, "{d}", .{b});
|
const b_fmt = try std.fmt.allocPrintSentinel(testing.allocator, "{fd}", .{b}, 0);
|
||||||
defer testing.allocator.free(b_fmt);
|
defer testing.allocator.free(b_fmt);
|
||||||
|
|
||||||
try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));
|
try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));
|
||||||
@ -3838,10 +3838,10 @@ test "(BigInt) negative" {
|
|||||||
a.negate();
|
a.negate();
|
||||||
try b.add(&a, &c);
|
try b.add(&a, &c);
|
||||||
|
|
||||||
const a_fmt = try std.fmt.allocPrintZ(testing.allocator, "{d}", .{a});
|
const a_fmt = try std.fmt.allocPrintSentinel(testing.allocator, "{fd}", .{a}, 0);
|
||||||
defer testing.allocator.free(a_fmt);
|
defer testing.allocator.free(a_fmt);
|
||||||
|
|
||||||
const b_fmt = try std.fmt.allocPrintZ(testing.allocator, "{d}", .{b});
|
const b_fmt = try std.fmt.allocPrintSentinel(testing.allocator, "{fd}", .{b}, 0);
|
||||||
defer testing.allocator.free(b_fmt);
|
defer testing.allocator.free(b_fmt);
|
||||||
|
|
||||||
try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));
|
try testing.expect(mem.eql(u8, a_fmt, "(BigInt)"));
|
||||||
|
|||||||
@ -991,6 +991,7 @@ test "0 sized struct" {
|
|||||||
test "struct with many fields" {
|
test "struct with many fields" {
|
||||||
const ManyFields = struct {
|
const ManyFields = struct {
|
||||||
fn Type(count: comptime_int) type {
|
fn Type(count: comptime_int) type {
|
||||||
|
@setEvalBranchQuota(50000);
|
||||||
var fields: [count]std.builtin.Type.StructField = undefined;
|
var fields: [count]std.builtin.Type.StructField = undefined;
|
||||||
for (0..count) |i| {
|
for (0..count) |i| {
|
||||||
fields[i] = .{
|
fields[i] = .{
|
||||||
|
|||||||
@ -161,22 +161,14 @@ pub const Address = extern union {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(
|
pub fn format(self: Address, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
|
||||||
self: Address,
|
comptime assert(fmt.len == 0);
|
||||||
comptime fmt: []const u8,
|
|
||||||
options: std.fmt.FormatOptions,
|
|
||||||
out_stream: anytype,
|
|
||||||
) !void {
|
|
||||||
if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
|
|
||||||
switch (self.any.family) {
|
switch (self.any.family) {
|
||||||
posix.AF.INET => try self.in.format(fmt, options, out_stream),
|
posix.AF.INET => try self.in.format(w, fmt),
|
||||||
posix.AF.INET6 => try self.in6.format(fmt, options, out_stream),
|
posix.AF.INET6 => try self.in6.format(w, fmt),
|
||||||
posix.AF.UNIX => {
|
posix.AF.UNIX => {
|
||||||
if (!has_unix_sockets) {
|
if (!has_unix_sockets) unreachable;
|
||||||
unreachable;
|
try w.writeAll(std.mem.sliceTo(&self.un.path, 0));
|
||||||
}
|
|
||||||
|
|
||||||
try std.fmt.format(out_stream, "{s}", .{std.mem.sliceTo(&self.un.path, 0)});
|
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
@ -349,22 +341,10 @@ pub const Ip4Address = extern struct {
|
|||||||
self.sa.port = mem.nativeToBig(u16, port);
|
self.sa.port = mem.nativeToBig(u16, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(
|
pub fn format(self: Ip4Address, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
|
||||||
self: Ip4Address,
|
comptime assert(fmt.len == 0);
|
||||||
comptime fmt: []const u8,
|
const bytes: *const [4]u8 = @ptrCast(&self.sa.addr);
|
||||||
options: std.fmt.FormatOptions,
|
try w.print("{d}.{d}.{d}.{d}:{d}", .{ bytes[0], bytes[1], bytes[2], bytes[3], self.getPort() });
|
||||||
out_stream: anytype,
|
|
||||||
) !void {
|
|
||||||
if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
|
|
||||||
_ = options;
|
|
||||||
const bytes = @as(*const [4]u8, @ptrCast(&self.sa.addr));
|
|
||||||
try std.fmt.format(out_stream, "{}.{}.{}.{}:{}", .{
|
|
||||||
bytes[0],
|
|
||||||
bytes[1],
|
|
||||||
bytes[2],
|
|
||||||
bytes[3],
|
|
||||||
self.getPort(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getOsSockLen(self: Ip4Address) posix.socklen_t {
|
pub fn getOsSockLen(self: Ip4Address) posix.socklen_t {
|
||||||
@ -653,17 +633,11 @@ pub const Ip6Address = extern struct {
|
|||||||
self.sa.port = mem.nativeToBig(u16, port);
|
self.sa.port = mem.nativeToBig(u16, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(
|
pub fn format(self: Ip6Address, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void {
|
||||||
self: Ip6Address,
|
comptime assert(fmt.len == 0);
|
||||||
comptime fmt: []const u8,
|
|
||||||
options: std.fmt.FormatOptions,
|
|
||||||
out_stream: anytype,
|
|
||||||
) !void {
|
|
||||||
if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
|
|
||||||
_ = options;
|
|
||||||
const port = mem.bigToNative(u16, self.sa.port);
|
const port = mem.bigToNative(u16, self.sa.port);
|
||||||
if (mem.eql(u8, self.sa.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) {
|
if (mem.eql(u8, self.sa.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) {
|
||||||
try std.fmt.format(out_stream, "[::ffff:{}.{}.{}.{}]:{}", .{
|
try w.print("[::ffff:{d}.{d}.{d}.{d}]:{d}", .{
|
||||||
self.sa.addr[12],
|
self.sa.addr[12],
|
||||||
self.sa.addr[13],
|
self.sa.addr[13],
|
||||||
self.sa.addr[14],
|
self.sa.addr[14],
|
||||||
@ -711,14 +685,14 @@ pub const Ip6Address = extern struct {
|
|||||||
longest_len = 0;
|
longest_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
try out_stream.writeAll("[");
|
try w.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 (i == longest_start) {
|
if (i == longest_start) {
|
||||||
// Emit "::" for the longest zero run
|
// Emit "::" for the longest zero run
|
||||||
if (!abbrv) {
|
if (!abbrv) {
|
||||||
try out_stream.writeAll(if (i == 0) "::" else ":");
|
try w.writeAll(if (i == 0) "::" else ":");
|
||||||
abbrv = true;
|
abbrv = true;
|
||||||
}
|
}
|
||||||
i += longest_len - 1; // Skip the compressed range
|
i += longest_len - 1; // Skip the compressed range
|
||||||
@ -727,12 +701,12 @@ pub const Ip6Address = extern struct {
|
|||||||
if (abbrv) {
|
if (abbrv) {
|
||||||
abbrv = false;
|
abbrv = false;
|
||||||
}
|
}
|
||||||
try std.fmt.format(out_stream, "{x}", .{native_endian_parts[i]});
|
try w.print("{x}", .{native_endian_parts[i]});
|
||||||
if (i != native_endian_parts.len - 1) {
|
if (i != native_endian_parts.len - 1) {
|
||||||
try out_stream.writeAll(":");
|
try w.writeAll(":");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try std.fmt.format(out_stream, "]:{}", .{port});
|
try w.print("]:{}", .{port});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getOsSockLen(self: Ip6Address) posix.socklen_t {
|
pub fn getOsSockLen(self: Ip6Address) posix.socklen_t {
|
||||||
@ -894,7 +868,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get
|
|||||||
const name_c = try allocator.dupeZ(u8, name);
|
const name_c = try allocator.dupeZ(u8, name);
|
||||||
defer allocator.free(name_c);
|
defer allocator.free(name_c);
|
||||||
|
|
||||||
const port_c = try std.fmt.allocPrintZ(allocator, "{}", .{port});
|
const port_c = try std.fmt.allocPrintSentinel(allocator, "{}", .{port}, 0);
|
||||||
defer allocator.free(port_c);
|
defer allocator.free(port_c);
|
||||||
|
|
||||||
const ws2_32 = windows.ws2_32;
|
const ws2_32 = windows.ws2_32;
|
||||||
@ -966,7 +940,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get
|
|||||||
const name_c = try allocator.dupeZ(u8, name);
|
const name_c = try allocator.dupeZ(u8, name);
|
||||||
defer allocator.free(name_c);
|
defer allocator.free(name_c);
|
||||||
|
|
||||||
const port_c = try std.fmt.allocPrintZ(allocator, "{}", .{port});
|
const port_c = try std.fmt.allocPrintSentinel(allocator, "{}", .{port}, 0);
|
||||||
defer allocator.free(port_c);
|
defer allocator.free(port_c);
|
||||||
|
|
||||||
const hints: posix.addrinfo = .{
|
const hints: posix.addrinfo = .{
|
||||||
@ -1356,7 +1330,7 @@ fn linuxLookupNameFromHosts(
|
|||||||
};
|
};
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
var buffered_reader = std.io.bufferedReader(file.reader());
|
var buffered_reader = std.io.bufferedReader(file.deprecatedReader());
|
||||||
const reader = buffered_reader.reader();
|
const reader = buffered_reader.reader();
|
||||||
var line_buf: [512]u8 = undefined;
|
var line_buf: [512]u8 = undefined;
|
||||||
while (reader.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) {
|
while (reader.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) {
|
||||||
@ -1557,7 +1531,7 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void {
|
|||||||
};
|
};
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
var buf_reader = std.io.bufferedReader(file.reader());
|
var buf_reader = std.io.bufferedReader(file.deprecatedReader());
|
||||||
const stream = buf_reader.reader();
|
const stream = buf_reader.reader();
|
||||||
var line_buf: [512]u8 = undefined;
|
var line_buf: [512]u8 = undefined;
|
||||||
while (stream.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) {
|
while (stream.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) {
|
||||||
|
|||||||
@ -7,18 +7,12 @@ const testing = std.testing;
|
|||||||
test "parse and render IP addresses at comptime" {
|
test "parse and render IP addresses at comptime" {
|
||||||
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
||||||
comptime {
|
comptime {
|
||||||
var ipAddrBuffer: [16]u8 = undefined;
|
|
||||||
// Parses IPv6 at comptime
|
|
||||||
const ipv6addr = net.Address.parseIp("::1", 0) catch unreachable;
|
const ipv6addr = net.Address.parseIp("::1", 0) catch unreachable;
|
||||||
var ipv6 = std.fmt.bufPrint(ipAddrBuffer[0..], "{}", .{ipv6addr}) catch unreachable;
|
try std.testing.expectFmt("[::1]:0", "{f}", .{ipv6addr});
|
||||||
try std.testing.expect(std.mem.eql(u8, "::1", ipv6[1 .. ipv6.len - 3]));
|
|
||||||
|
|
||||||
// Parses IPv4 at comptime
|
|
||||||
const ipv4addr = net.Address.parseIp("127.0.0.1", 0) catch unreachable;
|
const ipv4addr = net.Address.parseIp("127.0.0.1", 0) catch unreachable;
|
||||||
var ipv4 = std.fmt.bufPrint(ipAddrBuffer[0..], "{}", .{ipv4addr}) catch unreachable;
|
try std.testing.expectFmt("127.0.0.1:0", "{f}", .{ipv4addr});
|
||||||
try std.testing.expect(std.mem.eql(u8, "127.0.0.1", ipv4[0 .. ipv4.len - 2]));
|
|
||||||
|
|
||||||
// Returns error for invalid IP addresses at comptime
|
|
||||||
try testing.expectError(error.InvalidIPAddressFormat, net.Address.parseIp("::123.123.123.123", 0));
|
try testing.expectError(error.InvalidIPAddressFormat, net.Address.parseIp("::123.123.123.123", 0));
|
||||||
try testing.expectError(error.InvalidIPAddressFormat, net.Address.parseIp("127.01.0.1", 0));
|
try testing.expectError(error.InvalidIPAddressFormat, net.Address.parseIp("127.01.0.1", 0));
|
||||||
try testing.expectError(error.InvalidIPAddressFormat, net.Address.resolveIp("::123.123.123.123", 0));
|
try testing.expectError(error.InvalidIPAddressFormat, net.Address.resolveIp("::123.123.123.123", 0));
|
||||||
@ -28,13 +22,8 @@ test "parse and render IP addresses at comptime" {
|
|||||||
|
|
||||||
test "format IPv6 address with no zero runs" {
|
test "format IPv6 address with no zero runs" {
|
||||||
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
||||||
|
|
||||||
const addr = try std.net.Address.parseIp6("2001:db8:1:2:3:4:5:6", 0);
|
const addr = try std.net.Address.parseIp6("2001:db8:1:2:3:4:5:6", 0);
|
||||||
|
try std.testing.expectFmt("[2001:db8:1:2:3:4:5:6]:0", "{f}", .{addr});
|
||||||
var buffer: [50]u8 = undefined;
|
|
||||||
const result = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
|
|
||||||
|
|
||||||
try std.testing.expectEqualStrings("[2001:db8:1:2:3:4:5:6]:0", result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "parse IPv6 addresses and check compressed form" {
|
test "parse IPv6 addresses and check compressed form" {
|
||||||
@ -111,12 +100,12 @@ test "parse and render IPv6 addresses" {
|
|||||||
};
|
};
|
||||||
for (ips, 0..) |ip, i| {
|
for (ips, 0..) |ip, i| {
|
||||||
const addr = net.Address.parseIp6(ip, 0) catch unreachable;
|
const addr = net.Address.parseIp6(ip, 0) catch unreachable;
|
||||||
var newIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
|
var newIp = std.fmt.bufPrint(buffer[0..], "{f}", .{addr}) catch unreachable;
|
||||||
try std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3]));
|
try std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3]));
|
||||||
|
|
||||||
if (builtin.os.tag == .linux) {
|
if (builtin.os.tag == .linux) {
|
||||||
const addr_via_resolve = net.Address.resolveIp6(ip, 0) catch unreachable;
|
const addr_via_resolve = net.Address.resolveIp6(ip, 0) catch unreachable;
|
||||||
var newResolvedIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr_via_resolve}) catch unreachable;
|
var newResolvedIp = std.fmt.bufPrint(buffer[0..], "{f}", .{addr_via_resolve}) catch unreachable;
|
||||||
try std.testing.expect(std.mem.eql(u8, printed[i], newResolvedIp[1 .. newResolvedIp.len - 3]));
|
try std.testing.expect(std.mem.eql(u8, printed[i], newResolvedIp[1 .. newResolvedIp.len - 3]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,7 +148,7 @@ test "parse and render IPv4 addresses" {
|
|||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
}) |ip| {
|
}) |ip| {
|
||||||
const addr = net.Address.parseIp4(ip, 0) catch unreachable;
|
const addr = net.Address.parseIp4(ip, 0) catch unreachable;
|
||||||
var newIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
|
var newIp = std.fmt.bufPrint(buffer[0..], "{f}", .{addr}) catch unreachable;
|
||||||
try std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2]));
|
try std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,10 +164,8 @@ test "parse and render UNIX addresses" {
|
|||||||
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
||||||
if (!net.has_unix_sockets) return error.SkipZigTest;
|
if (!net.has_unix_sockets) return error.SkipZigTest;
|
||||||
|
|
||||||
var buffer: [14]u8 = undefined;
|
|
||||||
const addr = net.Address.initUnix("/tmp/testpath") catch unreachable;
|
const addr = net.Address.initUnix("/tmp/testpath") catch unreachable;
|
||||||
const fmt_addr = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
|
try std.testing.expectFmt("/tmp/testpath", "{f}", .{addr});
|
||||||
try std.testing.expectEqualSlices(u8, "/tmp/testpath", fmt_addr);
|
|
||||||
|
|
||||||
const too_long = [_]u8{'a'} ** 200;
|
const too_long = [_]u8{'a'} ** 200;
|
||||||
try testing.expectError(error.NameTooLong, net.Address.initUnix(too_long[0..]));
|
try testing.expectError(error.NameTooLong, net.Address.initUnix(too_long[0..]));
|
||||||
|
|||||||
@ -31,6 +31,7 @@ pub const uefi = @import("os/uefi.zig");
|
|||||||
pub const wasi = @import("os/wasi.zig");
|
pub const wasi = @import("os/wasi.zig");
|
||||||
pub const emscripten = @import("os/emscripten.zig");
|
pub const emscripten = @import("os/emscripten.zig");
|
||||||
pub const windows = @import("os/windows.zig");
|
pub const windows = @import("os/windows.zig");
|
||||||
|
pub const freebsd = @import("os/freebsd.zig");
|
||||||
|
|
||||||
test {
|
test {
|
||||||
_ = linux;
|
_ = linux;
|
||||||
|
|||||||
49
lib/std/os/freebsd.zig
Normal file
49
lib/std/os/freebsd.zig
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
const std = @import("../std.zig");
|
||||||
|
const fd_t = std.c.fd_t;
|
||||||
|
const off_t = std.c.off_t;
|
||||||
|
const unexpectedErrno = std.posix.unexpectedErrno;
|
||||||
|
const errno = std.posix.errno;
|
||||||
|
|
||||||
|
pub const CopyFileRangeError = error{
|
||||||
|
/// If infd is not open for reading or outfd is not open for writing, or
|
||||||
|
/// opened for writing with O_APPEND, or if infd and outfd refer to the
|
||||||
|
/// same file.
|
||||||
|
BadFileFlags,
|
||||||
|
/// If the copy exceeds the process's file size limit or the maximum
|
||||||
|
/// file size for the file system outfd re- sides on.
|
||||||
|
FileTooBig,
|
||||||
|
/// A signal interrupted the system call before it could be completed.
|
||||||
|
/// This may happen for files on some NFS mounts. When this happens,
|
||||||
|
/// the values pointed to by inoffp and outoffp are reset to the
|
||||||
|
/// initial values for the system call.
|
||||||
|
Interrupted,
|
||||||
|
/// One of:
|
||||||
|
/// * infd and outfd refer to the same file and the byte ranges overlap.
|
||||||
|
/// * The flags argument is not zero.
|
||||||
|
/// * Either infd or outfd refers to a file object that is not a regular file.
|
||||||
|
InvalidArguments,
|
||||||
|
/// An I/O error occurred while reading/writing the files.
|
||||||
|
InputOutput,
|
||||||
|
/// Corrupted data was detected while reading from a file system.
|
||||||
|
CorruptedData,
|
||||||
|
/// Either infd or outfd refers to a directory.
|
||||||
|
IsDir,
|
||||||
|
/// File system that stores outfd is full.
|
||||||
|
NoSpaceLeft,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_out: ?*i64, len: usize, flags: u32) CopyFileRangeError!usize {
|
||||||
|
const rc = std.c.copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
|
||||||
|
switch (errno(rc)) {
|
||||||
|
.SUCCESS => return @intCast(rc),
|
||||||
|
.BADF => return error.BadFileFlags,
|
||||||
|
.FBIG => return error.FileTooBig,
|
||||||
|
.INTR => return error.Interrupted,
|
||||||
|
.INVAL => return error.InvalidArguments,
|
||||||
|
.IO => return error.InputOutput,
|
||||||
|
.INTEGRITY => return error.CorruptedData,
|
||||||
|
.ISDIR => return error.IsDir,
|
||||||
|
.NOSPC => return error.NoSpaceLeft,
|
||||||
|
else => |err| return unexpectedErrno(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9420,4 +9420,132 @@ pub const msghdr_const = extern struct {
|
|||||||
control: ?*const anyopaque,
|
control: ?*const anyopaque,
|
||||||
controllen: usize,
|
controllen: usize,
|
||||||
flags: u32,
|
flags: u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The syscalls, but with Zig error sets, going through libc if linking libc,
|
||||||
|
/// and with some footguns eliminated.
|
||||||
|
pub const wrapped = struct {
|
||||||
|
pub const lfs64_abi = builtin.link_libc and (builtin.abi.isGnu() or builtin.abi.isAndroid());
|
||||||
|
const system = if (builtin.link_libc) std.c else std.os.linux;
|
||||||
|
|
||||||
|
pub const SendfileError = std.posix.UnexpectedError || error{
|
||||||
|
/// `out_fd` is an unconnected socket, or out_fd closed its read end.
|
||||||
|
BrokenPipe,
|
||||||
|
/// Descriptor is not valid or locked, or an mmap(2)-like operation is not available for in_fd.
|
||||||
|
UnsupportedOperation,
|
||||||
|
/// Nonblocking I/O has been selected but the write would block.
|
||||||
|
WouldBlock,
|
||||||
|
/// Unspecified error while reading from in_fd.
|
||||||
|
InputOutput,
|
||||||
|
/// Insufficient kernel memory to read from in_fd.
|
||||||
|
SystemResources,
|
||||||
|
/// `offset` is not `null` but the input file is not seekable.
|
||||||
|
Unseekable,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn sendfile(
|
||||||
|
out_fd: fd_t,
|
||||||
|
in_fd: fd_t,
|
||||||
|
in_offset: ?*off_t,
|
||||||
|
in_len: usize,
|
||||||
|
) SendfileError!usize {
|
||||||
|
const adjusted_len = @min(in_len, 0x7ffff000); // Prevents EOVERFLOW.
|
||||||
|
const sendfileSymbol = if (lfs64_abi) system.sendfile64 else system.sendfile;
|
||||||
|
const rc = sendfileSymbol(out_fd, in_fd, in_offset, adjusted_len);
|
||||||
|
switch (errno(rc)) {
|
||||||
|
.SUCCESS => return @intCast(rc),
|
||||||
|
.BADF => return invalidApiUsage(), // Always a race condition.
|
||||||
|
.FAULT => return invalidApiUsage(), // Segmentation fault.
|
||||||
|
.OVERFLOW => return unexpectedErrno(.OVERFLOW), // We avoid passing too large of a `count`.
|
||||||
|
.NOTCONN => return error.BrokenPipe, // `out_fd` is an unconnected socket
|
||||||
|
.INVAL => return error.UnsupportedOperation,
|
||||||
|
.AGAIN => return error.WouldBlock,
|
||||||
|
.IO => return error.InputOutput,
|
||||||
|
.PIPE => return error.BrokenPipe,
|
||||||
|
.NOMEM => return error.SystemResources,
|
||||||
|
.NXIO => return error.Unseekable,
|
||||||
|
.SPIPE => return error.Unseekable,
|
||||||
|
else => |err| return unexpectedErrno(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const CopyFileRangeError = std.posix.UnexpectedError || error{
|
||||||
|
/// One of:
|
||||||
|
/// * One or more file descriptors are not valid.
|
||||||
|
/// * fd_in is not open for reading; or fd_out is not open for writing.
|
||||||
|
/// * The O_APPEND flag is set for the open file description referred
|
||||||
|
/// to by the file descriptor fd_out.
|
||||||
|
BadFileFlags,
|
||||||
|
/// One of:
|
||||||
|
/// * An attempt was made to write at a position past the maximum file
|
||||||
|
/// offset the kernel supports.
|
||||||
|
/// * An attempt was made to write a range that exceeds the allowed
|
||||||
|
/// maximum file size. The maximum file size differs between
|
||||||
|
/// filesystem implementations and can be different from the maximum
|
||||||
|
/// allowed file offset.
|
||||||
|
/// * An attempt was made to write beyond the process's file size
|
||||||
|
/// resource limit. This may also result in the process receiving a
|
||||||
|
/// SIGXFSZ signal.
|
||||||
|
FileTooBig,
|
||||||
|
/// One of:
|
||||||
|
/// * either fd_in or fd_out is not a regular file
|
||||||
|
/// * flags argument is not zero
|
||||||
|
/// * fd_in and fd_out refer to the same file and the source and target ranges overlap.
|
||||||
|
InvalidArguments,
|
||||||
|
/// A low-level I/O error occurred while copying.
|
||||||
|
InputOutput,
|
||||||
|
/// Either fd_in or fd_out refers to a directory.
|
||||||
|
IsDir,
|
||||||
|
OutOfMemory,
|
||||||
|
/// There is not enough space on the target filesystem to complete the copy.
|
||||||
|
NoSpaceLeft,
|
||||||
|
/// (since Linux 5.19) the filesystem does not support this operation.
|
||||||
|
OperationNotSupported,
|
||||||
|
/// The requested source or destination range is too large to represent
|
||||||
|
/// in the specified data types.
|
||||||
|
Overflow,
|
||||||
|
/// fd_out refers to an immutable file.
|
||||||
|
PermissionDenied,
|
||||||
|
/// Either fd_in or fd_out refers to an active swap file.
|
||||||
|
SwapFile,
|
||||||
|
/// The files referred to by fd_in and fd_out are not on the same
|
||||||
|
/// filesystem, and the source and target filesystems are not of the
|
||||||
|
/// same type, or do not support cross-filesystem copy.
|
||||||
|
NotSameFileSystem,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_out: ?*i64, len: usize, flags: u32) CopyFileRangeError!usize {
|
||||||
|
const rc = system.copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
|
||||||
|
switch (errno(rc)) {
|
||||||
|
.SUCCESS => return @intCast(rc),
|
||||||
|
.BADF => return error.BadFileFlags,
|
||||||
|
.FBIG => return error.FileTooBig,
|
||||||
|
.INVAL => return error.InvalidArguments,
|
||||||
|
.IO => return error.InputOutput,
|
||||||
|
.ISDIR => return error.IsDir,
|
||||||
|
.NOMEM => return error.OutOfMemory,
|
||||||
|
.NOSPC => return error.NoSpaceLeft,
|
||||||
|
.OPNOTSUPP => return error.OperationNotSupported,
|
||||||
|
.OVERFLOW => return error.Overflow,
|
||||||
|
.PERM => return error.PermissionDenied,
|
||||||
|
.TXTBSY => return error.SwapFile,
|
||||||
|
.XDEV => return error.NotSameFileSystem,
|
||||||
|
else => |err| return unexpectedErrno(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const unexpectedErrno = std.posix.unexpectedErrno;
|
||||||
|
|
||||||
|
fn invalidApiUsage() error{Unexpected} {
|
||||||
|
if (builtin.mode == .Debug) @panic("invalid API usage");
|
||||||
|
return error.Unexpected;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn errno(rc: anytype) E {
|
||||||
|
if (builtin.link_libc) {
|
||||||
|
return if (rc == -1) @enumFromInt(std.c._errno().*) else .SUCCESS;
|
||||||
|
} else {
|
||||||
|
return errnoFromSyscall(rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
const std = @import("../std.zig");
|
const std = @import("../std.zig");
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
/// A protocol is an interface identified by a GUID.
|
/// A protocol is an interface identified by a GUID.
|
||||||
pub const protocol = @import("uefi/protocol.zig");
|
pub const protocol = @import("uefi/protocol.zig");
|
||||||
@ -59,31 +60,21 @@ pub const Guid = extern struct {
|
|||||||
node: [6]u8,
|
node: [6]u8,
|
||||||
|
|
||||||
/// Format GUID into hexadecimal lowercase xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
|
/// Format GUID into hexadecimal lowercase xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
|
||||||
pub fn format(
|
pub fn format(self: @This(), writer: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void {
|
||||||
self: @This(),
|
comptime assert(f.len == 0);
|
||||||
comptime f: []const u8,
|
|
||||||
options: std.fmt.FormatOptions,
|
|
||||||
writer: anytype,
|
|
||||||
) !void {
|
|
||||||
_ = options;
|
|
||||||
if (f.len == 0) {
|
|
||||||
const fmt = std.fmt.fmtSliceHexLower;
|
|
||||||
|
|
||||||
const time_low = @byteSwap(self.time_low);
|
const time_low = @byteSwap(self.time_low);
|
||||||
const time_mid = @byteSwap(self.time_mid);
|
const time_mid = @byteSwap(self.time_mid);
|
||||||
const time_high_and_version = @byteSwap(self.time_high_and_version);
|
const time_high_and_version = @byteSwap(self.time_high_and_version);
|
||||||
|
|
||||||
return std.fmt.format(writer, "{:0>8}-{:0>4}-{:0>4}-{:0>2}{:0>2}-{:0>12}", .{
|
return std.fmt.format(writer, "{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{
|
||||||
fmt(std.mem.asBytes(&time_low)),
|
std.mem.asBytes(&time_low),
|
||||||
fmt(std.mem.asBytes(&time_mid)),
|
std.mem.asBytes(&time_mid),
|
||||||
fmt(std.mem.asBytes(&time_high_and_version)),
|
std.mem.asBytes(&time_high_and_version),
|
||||||
fmt(std.mem.asBytes(&self.clock_seq_high_and_reserved)),
|
std.mem.asBytes(&self.clock_seq_high_and_reserved),
|
||||||
fmt(std.mem.asBytes(&self.clock_seq_low)),
|
std.mem.asBytes(&self.clock_seq_low),
|
||||||
fmt(std.mem.asBytes(&self.node)),
|
std.mem.asBytes(&self.node),
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
std.fmt.invalidFmtError(f, self);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eql(a: std.os.uefi.Guid, b: std.os.uefi.Guid) bool {
|
pub fn eql(a: std.os.uefi.Guid, b: std.os.uefi.Guid) bool {
|
||||||
|
|||||||
@ -79,30 +79,6 @@ pub const File = extern struct {
|
|||||||
VolumeFull,
|
VolumeFull,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const SeekableStream = io.SeekableStream(
|
|
||||||
*File,
|
|
||||||
SeekError,
|
|
||||||
SeekError,
|
|
||||||
setPosition,
|
|
||||||
seekBy,
|
|
||||||
getPosition,
|
|
||||||
getEndPos,
|
|
||||||
);
|
|
||||||
pub const Reader = io.GenericReader(*File, ReadError, read);
|
|
||||||
pub const Writer = io.GenericWriter(*File, WriteError, write);
|
|
||||||
|
|
||||||
pub fn seekableStream(self: *File) SeekableStream {
|
|
||||||
return .{ .context = self };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reader(self: *File) Reader {
|
|
||||||
return .{ .context = self };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn writer(self: *File) Writer {
|
|
||||||
return .{ .context = self };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn open(
|
pub fn open(
|
||||||
self: *const File,
|
self: *const File,
|
||||||
file_name: [*:0]const u16,
|
file_name: [*:0]const u16,
|
||||||
|
|||||||
@ -1690,40 +1690,6 @@ pub fn getpeername(s: ws2_32.SOCKET, name: *ws2_32.sockaddr, namelen: *ws2_32.so
|
|||||||
return ws2_32.getpeername(s, name, @as(*i32, @ptrCast(namelen)));
|
return ws2_32.getpeername(s, name, @as(*i32, @ptrCast(namelen)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sendmsg(
|
|
||||||
s: ws2_32.SOCKET,
|
|
||||||
msg: *ws2_32.WSAMSG_const,
|
|
||||||
flags: u32,
|
|
||||||
) i32 {
|
|
||||||
var bytes_send: DWORD = undefined;
|
|
||||||
if (ws2_32.WSASendMsg(s, msg, flags, &bytes_send, null, null) == ws2_32.SOCKET_ERROR) {
|
|
||||||
return ws2_32.SOCKET_ERROR;
|
|
||||||
} else {
|
|
||||||
return @as(i32, @as(u31, @intCast(bytes_send)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sendto(s: ws2_32.SOCKET, buf: [*]const u8, len: usize, flags: u32, to: ?*const ws2_32.sockaddr, to_len: ws2_32.socklen_t) i32 {
|
|
||||||
var buffer = ws2_32.WSABUF{ .len = @as(u31, @truncate(len)), .buf = @constCast(buf) };
|
|
||||||
var bytes_send: DWORD = undefined;
|
|
||||||
if (ws2_32.WSASendTo(s, @as([*]ws2_32.WSABUF, @ptrCast(&buffer)), 1, &bytes_send, flags, to, @as(i32, @intCast(to_len)), null, null) == ws2_32.SOCKET_ERROR) {
|
|
||||||
return ws2_32.SOCKET_ERROR;
|
|
||||||
} else {
|
|
||||||
return @as(i32, @as(u31, @intCast(bytes_send)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn recvfrom(s: ws2_32.SOCKET, buf: [*]u8, len: usize, flags: u32, from: ?*ws2_32.sockaddr, from_len: ?*ws2_32.socklen_t) i32 {
|
|
||||||
var buffer = ws2_32.WSABUF{ .len = @as(u31, @truncate(len)), .buf = buf };
|
|
||||||
var bytes_received: DWORD = undefined;
|
|
||||||
var flags_inout = flags;
|
|
||||||
if (ws2_32.WSARecvFrom(s, @as([*]ws2_32.WSABUF, @ptrCast(&buffer)), 1, &bytes_received, &flags_inout, from, @as(?*i32, @ptrCast(from_len)), null, null) == ws2_32.SOCKET_ERROR) {
|
|
||||||
return ws2_32.SOCKET_ERROR;
|
|
||||||
} else {
|
|
||||||
return @as(i32, @as(u31, @intCast(bytes_received)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn poll(fds: [*]ws2_32.pollfd, n: c_ulong, timeout: i32) i32 {
|
pub fn poll(fds: [*]ws2_32.pollfd, n: c_ulong, timeout: i32) i32 {
|
||||||
return ws2_32.WSAPoll(fds, n, timeout);
|
return ws2_32.WSAPoll(fds, n, timeout);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1829,7 +1829,7 @@ pub extern "ws2_32" fn sendto(
|
|||||||
buf: [*]const u8,
|
buf: [*]const u8,
|
||||||
len: i32,
|
len: i32,
|
||||||
flags: i32,
|
flags: i32,
|
||||||
to: *const sockaddr,
|
to: ?*const sockaddr,
|
||||||
tolen: i32,
|
tolen: i32,
|
||||||
) callconv(.winapi) i32;
|
) callconv(.winapi) i32;
|
||||||
|
|
||||||
@ -2116,14 +2116,6 @@ pub extern "ws2_32" fn WSASendMsg(
|
|||||||
lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
|
lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
|
||||||
) callconv(.winapi) i32;
|
) callconv(.winapi) i32;
|
||||||
|
|
||||||
pub extern "ws2_32" fn WSARecvMsg(
|
|
||||||
s: SOCKET,
|
|
||||||
lpMsg: *WSAMSG,
|
|
||||||
lpdwNumberOfBytesRecv: ?*u32,
|
|
||||||
lpOverlapped: ?*OVERLAPPED,
|
|
||||||
lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
|
|
||||||
) callconv(.winapi) i32;
|
|
||||||
|
|
||||||
pub extern "ws2_32" fn WSASendDisconnect(
|
pub extern "ws2_32" fn WSASendDisconnect(
|
||||||
s: SOCKET,
|
s: SOCKET,
|
||||||
lpOutboundDisconnectData: ?*WSABUF,
|
lpOutboundDisconnectData: ?*WSABUF,
|
||||||
|
|||||||
@ -651,7 +651,7 @@ fn getRandomBytesDevURandom(buf: []u8) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const file: fs.File = .{ .handle = fd };
|
const file: fs.File = .{ .handle = fd };
|
||||||
const stream = file.reader();
|
const stream = file.deprecatedReader();
|
||||||
stream.readNoEof(buf) catch return error.Unexpected;
|
stream.readNoEof(buf) catch return error.Unexpected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -667,7 +667,7 @@ test "mmap" {
|
|||||||
const file = try tmp.dir.createFile(test_out_file, .{});
|
const file = try tmp.dir.createFile(test_out_file, .{});
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
const stream = file.writer();
|
const stream = file.deprecatedWriter();
|
||||||
|
|
||||||
var i: u32 = 0;
|
var i: u32 = 0;
|
||||||
while (i < alloc_size / @sizeOf(u32)) : (i += 1) {
|
while (i < alloc_size / @sizeOf(u32)) : (i += 1) {
|
||||||
|
|||||||
@ -1553,7 +1553,7 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo {
|
|||||||
const file = try std.fs.openFileAbsolute("/etc/passwd", .{});
|
const file = try std.fs.openFileAbsolute("/etc/passwd", .{});
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
const reader = file.reader();
|
const reader = file.deprecatedReader();
|
||||||
|
|
||||||
const State = enum {
|
const State = enum {
|
||||||
Start,
|
Start,
|
||||||
@ -1895,7 +1895,7 @@ pub fn createEnvironFromMap(
|
|||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
|
|
||||||
if (zig_progress_action == .add) {
|
if (zig_progress_action == .add) {
|
||||||
envp_buf[i] = try std.fmt.allocPrintZ(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?});
|
envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1906,16 +1906,16 @@ pub fn createEnvironFromMap(
|
|||||||
.add => unreachable,
|
.add => unreachable,
|
||||||
.delete => continue,
|
.delete => continue,
|
||||||
.edit => {
|
.edit => {
|
||||||
envp_buf[i] = try std.fmt.allocPrintZ(arena, "{s}={d}", .{
|
envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "{s}={d}", .{
|
||||||
pair.key_ptr.*, options.zig_progress_fd.?,
|
pair.key_ptr.*, options.zig_progress_fd.?,
|
||||||
});
|
}, 0);
|
||||||
i += 1;
|
i += 1;
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
.nothing => {},
|
.nothing => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
envp_buf[i] = try std.fmt.allocPrintZ(arena, "{s}={s}", .{ pair.key_ptr.*, pair.value_ptr.* });
|
envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "{s}={s}", .{ pair.key_ptr.*, pair.value_ptr.* }, 0);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1965,7 +1965,7 @@ pub fn createEnvironFromExisting(
|
|||||||
var existing_index: usize = 0;
|
var existing_index: usize = 0;
|
||||||
|
|
||||||
if (zig_progress_action == .add) {
|
if (zig_progress_action == .add) {
|
||||||
envp_buf[i] = try std.fmt.allocPrintZ(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?});
|
envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1974,7 +1974,7 @@ pub fn createEnvironFromExisting(
|
|||||||
.add => unreachable,
|
.add => unreachable,
|
||||||
.delete => continue,
|
.delete => continue,
|
||||||
.edit => {
|
.edit => {
|
||||||
envp_buf[i] = try std.fmt.allocPrintZ(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?});
|
envp_buf[i] = try std.fmt.allocPrintSentinel(arena, "ZIG_PROGRESS={d}", .{options.zig_progress_fd.?}, 0);
|
||||||
i += 1;
|
i += 1;
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1004,12 +1004,12 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
|
|||||||
|
|
||||||
fn writeIntFd(fd: i32, value: ErrInt) !void {
|
fn writeIntFd(fd: i32, value: ErrInt) !void {
|
||||||
const file: File = .{ .handle = fd };
|
const file: File = .{ .handle = fd };
|
||||||
file.writer().writeInt(u64, @intCast(value), .little) catch return error.SystemResources;
|
file.deprecatedWriter().writeInt(u64, @intCast(value), .little) catch return error.SystemResources;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readIntFd(fd: i32) !ErrInt {
|
fn readIntFd(fd: i32) !ErrInt {
|
||||||
const file: File = .{ .handle = fd };
|
const file: File = .{ .handle = fd };
|
||||||
return @intCast(file.reader().readInt(u64, .little) catch return error.SystemResources);
|
return @intCast(file.deprecatedReader().readInt(u64, .little) catch return error.SystemResources);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8);
|
const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8);
|
||||||
|
|||||||
@ -105,7 +105,7 @@ fn expectEqualInner(comptime T: type, expected: T, actual: T) !void {
|
|||||||
.error_set,
|
.error_set,
|
||||||
=> {
|
=> {
|
||||||
if (actual != expected) {
|
if (actual != expected) {
|
||||||
print("expected {}, found {}\n", .{ expected, actual });
|
print("expected {any}, found {any}\n", .{ expected, actual });
|
||||||
return error.TestExpectedEqual;
|
return error.TestExpectedEqual;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -267,9 +267,13 @@ test "expectEqual null" {
|
|||||||
|
|
||||||
/// This function is intended to be used only in tests. When the formatted result of the template
|
/// This function is intended to be used only in tests. When the formatted result of the template
|
||||||
/// and its arguments does not equal the expected text, it prints diagnostics to stderr to show how
|
/// and its arguments does not equal the expected text, it prints diagnostics to stderr to show how
|
||||||
/// they are not equal, then returns an error. It depends on `expectEqualStrings()` for printing
|
/// they are not equal, then returns an error. It depends on `expectEqualStrings` for printing
|
||||||
/// diagnostics.
|
/// diagnostics.
|
||||||
pub fn expectFmt(expected: []const u8, comptime template: []const u8, args: anytype) !void {
|
pub fn expectFmt(expected: []const u8, comptime template: []const u8, args: anytype) !void {
|
||||||
|
if (@inComptime()) {
|
||||||
|
var buffer: [std.fmt.count(template, args)]u8 = undefined;
|
||||||
|
return expectEqualStrings(expected, try std.fmt.bufPrint(&buffer, template, args));
|
||||||
|
}
|
||||||
const actual = try std.fmt.allocPrint(allocator, template, args);
|
const actual = try std.fmt.allocPrint(allocator, template, args);
|
||||||
defer allocator.free(actual);
|
defer allocator.free(actual);
|
||||||
return expectEqualStrings(expected, actual);
|
return expectEqualStrings(expected, actual);
|
||||||
@ -415,7 +419,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
|
|||||||
print("... truncated ...\n", .{});
|
print("... truncated ...\n", .{});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
differ.write(stderr.writer()) catch {};
|
differ.write(stderr.deprecatedWriter()) catch {};
|
||||||
if (expected_truncated) {
|
if (expected_truncated) {
|
||||||
const end_offset = window_start + expected_window.len;
|
const end_offset = window_start + expected_window.len;
|
||||||
const num_missing_items = expected.len - (window_start + expected_window.len);
|
const num_missing_items = expected.len - (window_start + expected_window.len);
|
||||||
@ -437,7 +441,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
|
|||||||
print("... truncated ...\n", .{});
|
print("... truncated ...\n", .{});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
differ.write(stderr.writer()) catch {};
|
differ.write(stderr.deprecatedWriter()) catch {};
|
||||||
if (actual_truncated) {
|
if (actual_truncated) {
|
||||||
const end_offset = window_start + actual_window.len;
|
const end_offset = window_start + actual_window.len;
|
||||||
const num_missing_items = actual.len - (window_start + actual_window.len);
|
const num_missing_items = actual.len - (window_start + actual_window.len);
|
||||||
@ -637,6 +641,11 @@ pub fn tmpDir(opts: std.fs.Dir.OpenOptions) TmpDir {
|
|||||||
|
|
||||||
pub fn expectEqualStrings(expected: []const u8, actual: []const u8) !void {
|
pub fn expectEqualStrings(expected: []const u8, actual: []const u8) !void {
|
||||||
if (std.mem.indexOfDiff(u8, actual, expected)) |diff_index| {
|
if (std.mem.indexOfDiff(u8, actual, expected)) |diff_index| {
|
||||||
|
if (@inComptime()) {
|
||||||
|
@compileError(std.fmt.comptimePrint("\nexpected:\n{s}\nfound:\n{s}\ndifference starts at index {d}", .{
|
||||||
|
expected, actual, diff_index,
|
||||||
|
}));
|
||||||
|
}
|
||||||
print("\n====== expected this output: =========\n", .{});
|
print("\n====== expected this output: =========\n", .{});
|
||||||
printWithVisibleNewlines(expected);
|
printWithVisibleNewlines(expected);
|
||||||
print("\n======== instead found this: =========\n", .{});
|
print("\n======== instead found this: =========\n", .{});
|
||||||
@ -1108,7 +1117,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime
|
|||||||
const arg_i_str = comptime str: {
|
const arg_i_str = comptime str: {
|
||||||
var str_buf: [100]u8 = undefined;
|
var str_buf: [100]u8 = undefined;
|
||||||
const args_i = i + 1;
|
const args_i = i + 1;
|
||||||
const str_len = std.fmt.formatIntBuf(&str_buf, args_i, 10, .lower, .{});
|
const str_len = std.fmt.printInt(&str_buf, args_i, 10, .lower, .{});
|
||||||
break :str str_buf[0..str_len];
|
break :str str_buf[0..str_len];
|
||||||
};
|
};
|
||||||
@field(args, arg_i_str) = @field(extra_args, field.name);
|
@field(args, arg_i_str) = @field(extra_args, field.name);
|
||||||
@ -1138,7 +1147,7 @@ pub fn checkAllAllocationFailures(backing_allocator: std.mem.Allocator, comptime
|
|||||||
error.OutOfMemory => {
|
error.OutOfMemory => {
|
||||||
if (failing_allocator_inst.allocated_bytes != failing_allocator_inst.freed_bytes) {
|
if (failing_allocator_inst.allocated_bytes != failing_allocator_inst.freed_bytes) {
|
||||||
print(
|
print(
|
||||||
"\nfail_index: {d}/{d}\nallocated bytes: {d}\nfreed bytes: {d}\nallocations: {d}\ndeallocations: {d}\nallocation that was made to fail: {}",
|
"\nfail_index: {d}/{d}\nallocated bytes: {d}\nfreed bytes: {d}\nallocations: {d}\ndeallocations: {d}\nallocation that was made to fail: {f}",
|
||||||
.{
|
.{
|
||||||
fail_index,
|
fail_index,
|
||||||
needed_alloc_count,
|
needed_alloc_count,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user