@zigc/lib 0.16.0-test.1 → 0.17.0-dev.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +19 -0
- package/c/math.zig +148 -35
- package/c/stropts.zig +17 -0
- package/c.zig +1 -0
- package/compiler/aro/aro/Attribute/names.zig +604 -589
- package/compiler/aro/aro/Attribute.zig +202 -116
- package/compiler/aro/aro/Builtins/common.zig +874 -863
- package/compiler/aro/aro/Builtins/eval.zig +15 -7
- package/compiler/aro/aro/Builtins.zig +0 -1
- package/compiler/aro/aro/CodeGen.zig +3 -1
- package/compiler/aro/aro/Compilation.zig +120 -97
- package/compiler/aro/aro/Diagnostics.zig +21 -17
- package/compiler/aro/aro/Driver/GCCDetector.zig +635 -0
- package/compiler/aro/aro/Driver.zig +124 -50
- package/compiler/aro/aro/LangOpts.zig +12 -2
- package/compiler/aro/aro/Parser/Diagnostic.zig +79 -19
- package/compiler/aro/aro/Parser.zig +336 -142
- package/compiler/aro/aro/Preprocessor/Diagnostic.zig +21 -0
- package/compiler/aro/aro/Preprocessor.zig +127 -56
- package/compiler/aro/aro/Target.zig +17 -12
- package/compiler/aro/aro/Tokenizer.zig +31 -14
- package/compiler/aro/aro/Toolchain.zig +4 -7
- package/compiler/aro/aro/Tree.zig +178 -148
- package/compiler/aro/aro/TypeStore.zig +82 -24
- package/compiler/aro/aro/Value.zig +13 -17
- package/compiler/aro/aro/features.zig +1 -0
- package/compiler/aro/aro/pragmas/once.zig +0 -1
- package/compiler/aro/aro/record_layout.zig +3 -3
- package/compiler/aro/assembly_backend/x86_64.zig +3 -4
- package/compiler/aro/backend/Assembly.zig +1 -2
- package/compiler/aro/backend/Interner.zig +2 -2
- package/compiler/aro/backend/Ir.zig +100 -92
- package/compiler/aro/include/ptrcheck.h +49 -0
- package/compiler/aro/main.zig +26 -10
- package/compiler/build_runner.zig +1 -0
- package/compiler/objdump.zig +93 -0
- package/compiler/reduce.zig +5 -1
- package/compiler/resinator/compile.zig +2 -2
- package/compiler/resinator/main.zig +7 -1
- package/compiler/resinator/preprocess.zig +1 -3
- package/compiler/std-docs.zig +8 -1
- package/compiler/test_runner.zig +194 -62
- package/compiler/translate-c/MacroTranslator.zig +80 -11
- package/compiler/translate-c/PatternList.zig +1 -9
- package/compiler/translate-c/Scope.zig +43 -6
- package/compiler/translate-c/Translator.zig +364 -126
- package/compiler/translate-c/ast.zig +19 -11
- package/compiler/translate-c/main.zig +75 -16
- package/compiler_rt/cos.zig +141 -52
- package/compiler_rt/divmodei4.zig +40 -17
- package/compiler_rt/exp.zig +1 -4
- package/compiler_rt/exp2.zig +1 -4
- package/compiler_rt/exp_f128.zig +377 -0
- package/compiler_rt/limb64.zig +1126 -0
- package/compiler_rt/long_double.zig +37 -0
- package/compiler_rt/mulXi3.zig +1 -1
- package/compiler_rt/mulo.zig +6 -1
- package/compiler_rt/rem_pio2l.zig +173 -0
- package/compiler_rt/sin.zig +140 -55
- package/compiler_rt/sincos.zig +279 -72
- package/compiler_rt/ssp.zig +1 -1
- package/compiler_rt/tan.zig +118 -47
- package/compiler_rt/trig.zig +256 -6
- package/compiler_rt/udivmodei4.zig +28 -0
- package/compiler_rt.zig +2 -0
- package/fuzzer.zig +855 -307
- package/libc/musl/src/math/pow.c +343 -0
- package/package.json +1 -1
- package/std/Build/Fuzz.zig +6 -19
- package/std/Build/Module.zig +1 -1
- package/std/Build/Step/CheckObject.zig +3 -3
- package/std/Build/Step/Compile.zig +18 -0
- package/std/Build/Step/ConfigHeader.zig +49 -33
- package/std/Build/Step/InstallArtifact.zig +18 -0
- package/std/Build/Step/Run.zig +536 -87
- package/std/Build/Step/TranslateC.zig +0 -6
- package/std/Build/Step.zig +8 -15
- package/std/Build/WebServer.zig +29 -17
- package/std/Build/abi.zig +47 -11
- package/std/Build.zig +17 -14
- package/std/Io/Dispatch.zig +2 -0
- package/std/Io/File/Reader.zig +3 -1
- package/std/Io/File.zig +1 -0
- package/std/Io/Kqueue.zig +2 -2
- package/std/Io/Threaded.zig +181 -143
- package/std/Io/Uring.zig +2 -1
- package/std/Io/Writer.zig +41 -41
- package/std/Io.zig +970 -2
- package/std/Target.zig +3 -2
- package/std/Thread.zig +8 -3
- package/std/array_hash_map.zig +96 -555
- package/std/array_list.zig +22 -31
- package/std/bit_set.zig +22 -6
- package/std/builtin/assembly.zig +68 -0
- package/std/c.zig +17 -17
- package/std/compress/flate/Compress.zig +3 -3
- package/std/crypto/Certificate/Bundle.zig +15 -1
- package/std/crypto/codecs/asn1.zig +33 -18
- package/std/crypto/codecs/base64_hex_ct.zig +14 -4
- package/std/debug/Dwarf.zig +29 -9
- package/std/debug/Info.zig +4 -0
- package/std/debug/MachOFile.zig +46 -8
- package/std/debug/Pdb.zig +539 -36
- package/std/debug/SelfInfo/Elf.zig +19 -18
- package/std/debug/SelfInfo/MachO.zig +18 -7
- package/std/debug/SelfInfo/Windows.zig +138 -36
- package/std/debug.zig +179 -65
- package/std/enums.zig +25 -19
- package/std/heap/ArenaAllocator.zig +145 -154
- package/std/heap/debug_allocator.zig +7 -7
- package/std/http/Client.zig +10 -6
- package/std/http.zig +11 -9
- package/std/json/Stringify.zig +3 -3
- package/std/json/dynamic.zig +4 -4
- package/std/math/big/int.zig +16 -17
- package/std/mem/Allocator.zig +4 -5
- package/std/mem.zig +48 -0
- package/std/os/emscripten.zig +2 -18
- package/std/os/linux/arc.zig +144 -0
- package/std/os/linux.zig +21 -4
- package/std/os/windows.zig +2 -2
- package/std/pdb.zig +143 -4
- package/std/posix.zig +6 -12
- package/std/priority_dequeue.zig +13 -12
- package/std/priority_queue.zig +5 -4
- package/std/process/Child.zig +1 -1
- package/std/process/Environ.zig +1 -1
- package/std/start.zig +17 -4
- package/std/std.zig +19 -6
- package/std/testing/FailingAllocator.zig +4 -4
- package/std/testing/Smith.zig +37 -2
- package/std/zig/Ast/Render.zig +186 -458
- package/std/zig/Ast.zig +0 -4
- package/std/zig/AstGen.zig +44 -7
- package/std/zig/AstSmith.zig +2602 -0
- package/std/zig/Client.zig +8 -3
- package/std/zig/Parse.zig +83 -74
- package/std/zig/Server.zig +26 -0
- package/std/zig/Zir.zig +17 -0
- package/std/zig/c_translation/helpers.zig +14 -9
- package/std/zig/llvm/Builder.zig +107 -48
- package/std/zig/system.zig +20 -4
- package/std/zig/tokenizer.zig +2 -1
- package/std/zig.zig +6 -0
- package/compiler/aro/aro/Driver/Filesystem.zig +0 -241
- package/libc/mingw/complex/cabs.c +0 -48
- package/libc/mingw/complex/cabsf.c +0 -48
- package/libc/mingw/complex/cacos.c +0 -50
- package/libc/mingw/complex/cacosf.c +0 -50
- package/libc/mingw/complex/carg.c +0 -48
- package/libc/mingw/complex/cargf.c +0 -48
- package/libc/mingw/complex/casin.c +0 -50
- package/libc/mingw/complex/casinf.c +0 -50
- package/libc/mingw/complex/catan.c +0 -50
- package/libc/mingw/complex/catanf.c +0 -50
- package/libc/mingw/complex/ccos.c +0 -50
- package/libc/mingw/complex/ccosf.c +0 -50
- package/libc/mingw/complex/cexp.c +0 -48
- package/libc/mingw/complex/cexpf.c +0 -48
- package/libc/mingw/complex/cimag.c +0 -48
- package/libc/mingw/complex/cimagf.c +0 -48
- package/libc/mingw/complex/clog.c +0 -48
- package/libc/mingw/complex/clog10.c +0 -49
- package/libc/mingw/complex/clog10f.c +0 -49
- package/libc/mingw/complex/clogf.c +0 -48
- package/libc/mingw/complex/conj.c +0 -48
- package/libc/mingw/complex/conjf.c +0 -48
- package/libc/mingw/complex/cpow.c +0 -48
- package/libc/mingw/complex/cpowf.c +0 -48
- package/libc/mingw/complex/cproj.c +0 -48
- package/libc/mingw/complex/cprojf.c +0 -48
- package/libc/mingw/complex/creal.c +0 -48
- package/libc/mingw/complex/crealf.c +0 -48
- package/libc/mingw/complex/csin.c +0 -50
- package/libc/mingw/complex/csinf.c +0 -50
- package/libc/mingw/complex/csqrt.c +0 -48
- package/libc/mingw/complex/csqrtf.c +0 -48
- package/libc/mingw/complex/ctan.c +0 -50
- package/libc/mingw/complex/ctanf.c +0 -50
- package/libc/mingw/math/arm/s_rint.c +0 -86
- package/libc/mingw/math/arm/s_rintf.c +0 -51
- package/libc/mingw/math/arm/sincos.S +0 -30
- package/libc/mingw/math/arm-common/sincosl.c +0 -13
- package/libc/mingw/math/arm64/rint.c +0 -12
- package/libc/mingw/math/arm64/rintf.c +0 -12
- package/libc/mingw/math/arm64/sincos.S +0 -32
- package/libc/mingw/math/bsd_private_base.h +0 -148
- package/libc/mingw/math/fdiml.c +0 -24
- package/libc/mingw/math/frexpf.c +0 -13
- package/libc/mingw/math/frexpl.c +0 -71
- package/libc/mingw/math/x86/acosf.c +0 -29
- package/libc/mingw/math/x86/atanf.c +0 -23
- package/libc/mingw/math/x86/atanl.c +0 -18
- package/libc/mingw/math/x86/cos.def.h +0 -65
- package/libc/mingw/math/x86/cosl.c +0 -46
- package/libc/mingw/math/x86/cosl_internal.S +0 -55
- package/libc/mingw/math/x86/ldexp.c +0 -23
- package/libc/mingw/math/x86/scalbn.S +0 -41
- package/libc/mingw/math/x86/scalbnf.S +0 -40
- package/libc/mingw/math/x86/sin.def.h +0 -65
- package/libc/mingw/math/x86/sinl.c +0 -46
- package/libc/mingw/math/x86/sinl_internal.S +0 -58
- package/libc/mingw/math/x86/tanl.S +0 -62
- package/libc/mingw/misc/btowc.c +0 -28
- package/libc/mingw/misc/wcstof.c +0 -66
- package/libc/mingw/misc/wcstoimax.c +0 -132
- package/libc/mingw/misc/wcstoumax.c +0 -126
- package/libc/mingw/misc/wctob.c +0 -29
- package/libc/mingw/misc/winbs_uint64.c +0 -6
- package/libc/mingw/misc/winbs_ulong.c +0 -6
- package/libc/mingw/misc/winbs_ushort.c +0 -6
- package/libc/mingw/stdio/_Exit.c +0 -10
- package/libc/mingw/stdio/_findfirst64i32.c +0 -21
- package/libc/mingw/stdio/_findnext64i32.c +0 -21
- package/libc/mingw/stdio/_fstat64i32.c +0 -37
- package/libc/mingw/stdio/_stat64i32.c +0 -37
- package/libc/mingw/stdio/_wfindfirst64i32.c +0 -21
- package/libc/mingw/stdio/_wfindnext64i32.c +0 -21
- package/libc/mingw/stdio/_wstat64i32.c +0 -37
- package/libc/musl/src/legacy/isastream.c +0 -7
- package/libc/musl/src/legacy/valloc.c +0 -8
- package/libc/musl/src/math/__cosl.c +0 -96
- package/libc/musl/src/math/__sinl.c +0 -78
- package/libc/musl/src/math/__tanl.c +0 -143
- package/libc/musl/src/math/aarch64/lrint.c +0 -10
- package/libc/musl/src/math/aarch64/lrintf.c +0 -10
- package/libc/musl/src/math/aarch64/rintf.c +0 -7
- package/libc/musl/src/math/cosl.c +0 -39
- package/libc/musl/src/math/fdim.c +0 -10
- package/libc/musl/src/math/fdimf.c +0 -10
- package/libc/musl/src/math/fdiml.c +0 -18
- package/libc/musl/src/math/finite.c +0 -7
- package/libc/musl/src/math/finitef.c +0 -7
- package/libc/musl/src/math/frexp.c +0 -23
- package/libc/musl/src/math/frexpf.c +0 -23
- package/libc/musl/src/math/frexpl.c +0 -29
- package/libc/musl/src/math/i386/lrint.c +0 -8
- package/libc/musl/src/math/i386/lrintf.c +0 -8
- package/libc/musl/src/math/i386/rintf.c +0 -7
- package/libc/musl/src/math/lrint.c +0 -72
- package/libc/musl/src/math/lrintf.c +0 -8
- package/libc/musl/src/math/powerpc64/lrint.c +0 -16
- package/libc/musl/src/math/powerpc64/lrintf.c +0 -16
- package/libc/musl/src/math/rintf.c +0 -30
- package/libc/musl/src/math/s390x/rintf.c +0 -15
- package/libc/musl/src/math/sincosl.c +0 -60
- package/libc/musl/src/math/sinl.c +0 -41
- package/libc/musl/src/math/tanl.c +0 -29
- package/libc/musl/src/math/x32/lrint.s +0 -5
- package/libc/musl/src/math/x32/lrintf.s +0 -5
- package/libc/musl/src/math/x86_64/lrint.c +0 -8
- package/libc/musl/src/math/x86_64/lrintf.c +0 -8
- package/libc/wasi/libc-bottom-half/sources/reallocarray.c +0 -14
package/std/Io/Threaded.zig
CHANGED
|
@@ -1671,20 +1671,23 @@ pub fn init(
|
|
|
1671
1671
|
/// When initialized this way:
|
|
1672
1672
|
/// * cancel requests have no effect.
|
|
1673
1673
|
/// * `deinit` is safe, but unnecessary to call.
|
|
1674
|
-
pub const init_single_threaded: Threaded =
|
|
1675
|
-
.
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1674
|
+
pub const init_single_threaded: Threaded = init: {
|
|
1675
|
+
const env_block: process.Environ.Block = if (is_windows) .global else .empty;
|
|
1676
|
+
break :init .{
|
|
1677
|
+
.allocator = .failing,
|
|
1678
|
+
.stack_size = std.Thread.SpawnConfig.default_stack_size,
|
|
1679
|
+
.async_limit = .nothing,
|
|
1680
|
+
.cpu_count_error = null,
|
|
1681
|
+
.concurrent_limit = .nothing,
|
|
1682
|
+
.old_sig_io = undefined,
|
|
1683
|
+
.old_sig_pipe = undefined,
|
|
1684
|
+
.have_signal_handler = false,
|
|
1685
|
+
.argv0 = .empty,
|
|
1686
|
+
.environ_initialized = env_block.isEmpty(),
|
|
1687
|
+
.environ = .{ .process_environ = .{ .block = env_block } },
|
|
1688
|
+
.worker_threads = .init(null),
|
|
1689
|
+
.disable_memory_mapping = false,
|
|
1690
|
+
};
|
|
1688
1691
|
};
|
|
1689
1692
|
|
|
1690
1693
|
var global_single_threaded_instance: Threaded = .init_single_threaded;
|
|
@@ -4290,6 +4293,7 @@ fn dirCreateFilePosix(
|
|
|
4290
4293
|
.AGAIN => return error.WouldBlock,
|
|
4291
4294
|
.TXTBSY => return error.FileBusy,
|
|
4292
4295
|
.NXIO => return error.NoDevice,
|
|
4296
|
+
.ROFS => return error.ReadOnlyFileSystem,
|
|
4293
4297
|
.ILSEQ => return error.BadPathName,
|
|
4294
4298
|
else => |err| return posix.unexpectedErrno(err),
|
|
4295
4299
|
}
|
|
@@ -4871,6 +4875,7 @@ fn dirOpenFilePosix(
|
|
|
4871
4875
|
.AGAIN => return error.WouldBlock,
|
|
4872
4876
|
.TXTBSY => return error.FileBusy,
|
|
4873
4877
|
.NXIO => return error.NoDevice,
|
|
4878
|
+
.ROFS => return error.ReadOnlyFileSystem,
|
|
4874
4879
|
.ILSEQ => return error.BadPathName,
|
|
4875
4880
|
else => |err| return posix.unexpectedErrno(err),
|
|
4876
4881
|
}
|
|
@@ -6088,12 +6093,19 @@ fn dirRealPathFileWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8,
|
|
|
6088
6093
|
}
|
|
6089
6094
|
};
|
|
6090
6095
|
defer windows.CloseHandle(h_file);
|
|
6091
|
-
|
|
6096
|
+
|
|
6097
|
+
// We can re-use the path buffer for the WTF-16 representation since
|
|
6098
|
+
// we don't need the prefixed path anymore
|
|
6099
|
+
return realPathWindowsBuf(h_file, out_buffer, &path_name_w.data);
|
|
6092
6100
|
}
|
|
6093
6101
|
|
|
6094
6102
|
fn realPathWindows(h_file: windows.HANDLE, out_buffer: []u8) File.RealPathError!usize {
|
|
6095
6103
|
var wide_buf: [windows.PATH_MAX_WIDE]u16 = undefined;
|
|
6096
|
-
|
|
6104
|
+
return realPathWindowsBuf(h_file, out_buffer, &wide_buf);
|
|
6105
|
+
}
|
|
6106
|
+
|
|
6107
|
+
fn realPathWindowsBuf(h_file: windows.HANDLE, out_buffer: []u8, wtf16_buffer: []u16) File.RealPathError!usize {
|
|
6108
|
+
const wide_slice = try GetFinalPathNameByHandle(h_file, .{}, wtf16_buffer);
|
|
6097
6109
|
|
|
6098
6110
|
const len = std.unicode.calcWtf8Len(wide_slice);
|
|
6099
6111
|
if (len > out_buffer.len)
|
|
@@ -8720,13 +8732,6 @@ fn supportsAnsiEscapeCodes(file: File) Io.Cancelable!bool {
|
|
|
8720
8732
|
}
|
|
8721
8733
|
}
|
|
8722
8734
|
|
|
8723
|
-
if (native_os == .wasi) {
|
|
8724
|
-
// WASI sanitizes stdout when fd is a tty so ANSI escape codes will not
|
|
8725
|
-
// be interpreted as actual cursor commands, and stderr is always
|
|
8726
|
-
// sanitized.
|
|
8727
|
-
return false;
|
|
8728
|
-
}
|
|
8729
|
-
|
|
8730
8735
|
if (try isTty(file)) return true;
|
|
8731
8736
|
|
|
8732
8737
|
return false;
|
|
@@ -13008,6 +13013,7 @@ fn netReceiveOneWindows(
|
|
|
13008
13013
|
.CANCELLED => unreachable,
|
|
13009
13014
|
.INSUFFICIENT_RESOURCES => return error.SystemResources,
|
|
13010
13015
|
.BUFFER_OVERFLOW => return error.MessageOversize,
|
|
13016
|
+
.PORT_UNREACHABLE => return error.PortUnreachable,
|
|
13011
13017
|
else => |status| return windows.unexpectedStatus(status),
|
|
13012
13018
|
}
|
|
13013
13019
|
}
|
|
@@ -13482,21 +13488,80 @@ fn netLookupFallible(
|
|
|
13482
13488
|
const name = host_name.bytes;
|
|
13483
13489
|
assert(name.len <= HostName.max_len);
|
|
13484
13490
|
|
|
13485
|
-
|
|
13486
|
-
|
|
13487
|
-
|
|
13488
|
-
|
|
13489
|
-
|
|
13490
|
-
|
|
13491
|
-
|
|
13492
|
-
|
|
13493
|
-
|
|
13494
|
-
|
|
13495
|
-
|
|
13496
|
-
|
|
13497
|
-
|
|
13491
|
+
// On Linux, glibc provides getaddrinfo_a which is capable of supporting our semantics.
|
|
13492
|
+
// However, musl's POSIX-compliant getaddrinfo is not, so we bypass it.
|
|
13493
|
+
|
|
13494
|
+
if (builtin.target.isGnuLibC()) {
|
|
13495
|
+
// TODO use getaddrinfo_a / gai_cancel
|
|
13496
|
+
}
|
|
13497
|
+
|
|
13498
|
+
if (native_os == .linux or is_windows) {
|
|
13499
|
+
if (IpAddress.parseIp6(name, options.port)) |addr| {
|
|
13500
|
+
if (options.family == .ip4) return error.UnknownHostName;
|
|
13501
|
+
if (copyCanon(options.canonical_name_buffer, name)) |canon| {
|
|
13502
|
+
try resolved.putAll(t_io, &.{
|
|
13503
|
+
.{ .address = addr },
|
|
13504
|
+
.{ .canonical_name = canon },
|
|
13505
|
+
});
|
|
13506
|
+
} else {
|
|
13507
|
+
try resolved.putOne(t_io, .{ .address = addr });
|
|
13508
|
+
}
|
|
13509
|
+
return;
|
|
13510
|
+
} else |_| {}
|
|
13511
|
+
|
|
13512
|
+
if (IpAddress.parseIp4(name, options.port)) |addr| {
|
|
13513
|
+
if (options.family == .ip6) return error.UnknownHostName;
|
|
13514
|
+
if (copyCanon(options.canonical_name_buffer, name)) |canon| {
|
|
13515
|
+
try resolved.putAll(t_io, &.{
|
|
13516
|
+
.{ .address = addr },
|
|
13517
|
+
.{ .canonical_name = canon },
|
|
13518
|
+
});
|
|
13519
|
+
} else {
|
|
13520
|
+
try resolved.putOne(t_io, .{ .address = addr });
|
|
13521
|
+
}
|
|
13522
|
+
return;
|
|
13523
|
+
} else |_| {}
|
|
13524
|
+
|
|
13525
|
+
if (t.lookupHosts(host_name, resolved, options)) return else |err| switch (err) {
|
|
13526
|
+
error.UnknownHostName => {},
|
|
13527
|
+
else => |e| return e,
|
|
13528
|
+
}
|
|
13529
|
+
|
|
13530
|
+
// RFC 6761 Section 6.3.3
|
|
13531
|
+
// Name resolution APIs and libraries SHOULD recognize
|
|
13532
|
+
// localhost names as special and SHOULD always return the IP
|
|
13533
|
+
// loopback address for address queries and negative responses
|
|
13534
|
+
// for all other query types.
|
|
13535
|
+
|
|
13536
|
+
// Check for equal to "localhost(.)" or ends in ".localhost(.)"
|
|
13537
|
+
const localhost = if (name[name.len - 1] == '.') "localhost." else "localhost";
|
|
13538
|
+
if (std.mem.endsWith(u8, name, localhost) and
|
|
13539
|
+
(name.len == localhost.len or name[name.len - localhost.len] == '.'))
|
|
13540
|
+
{
|
|
13541
|
+
var results_buffer: [3]HostName.LookupResult = undefined;
|
|
13542
|
+
var results_index: usize = 0;
|
|
13543
|
+
if (options.family != .ip4) {
|
|
13544
|
+
results_buffer[results_index] = .{ .address = .{ .ip6 = .loopback(options.port) } };
|
|
13545
|
+
results_index += 1;
|
|
13546
|
+
}
|
|
13547
|
+
if (options.family != .ip6) {
|
|
13548
|
+
results_buffer[results_index] = .{ .address = .{ .ip4 = .loopback(options.port) } };
|
|
13549
|
+
results_index += 1;
|
|
13550
|
+
}
|
|
13551
|
+
if (options.canonical_name_buffer) |buf| {
|
|
13552
|
+
const canon_name = "localhost";
|
|
13553
|
+
const canon_name_dest = buf[0..canon_name.len];
|
|
13554
|
+
canon_name_dest.* = canon_name.*;
|
|
13555
|
+
results_buffer[results_index] = .{ .canonical_name = .{ .bytes = canon_name_dest } };
|
|
13556
|
+
results_index += 1;
|
|
13557
|
+
}
|
|
13558
|
+
try resolved.putAll(t_io, results_buffer[0..results_index]);
|
|
13559
|
+
return;
|
|
13498
13560
|
}
|
|
13499
13561
|
|
|
13562
|
+
if (native_os == .linux) return t.lookupDnsSearch(host_name, resolved, options);
|
|
13563
|
+
|
|
13564
|
+
comptime assert(is_windows);
|
|
13500
13565
|
var DnsQueryEx = t.dl.DnsQueryEx.load(.acquire);
|
|
13501
13566
|
//var DnsCancelQuery = t.dl.DnsCancelQuery.load(.acquire);
|
|
13502
13567
|
var DnsFree = t.dl.DnsFree.load(.acquire);
|
|
@@ -13540,6 +13605,7 @@ fn netLookupFallible(
|
|
|
13540
13605
|
else => |status| return windows.unexpectedStatus(status),
|
|
13541
13606
|
}
|
|
13542
13607
|
}
|
|
13608
|
+
try Thread.checkCancel();
|
|
13543
13609
|
const current_thread = Thread.current;
|
|
13544
13610
|
var lookup_dns: LookupDnsWindows = .{
|
|
13545
13611
|
.threaded = t,
|
|
@@ -13562,126 +13628,71 @@ fn netLookupFallible(
|
|
|
13562
13628
|
}
|
|
13563
13629
|
] = 0;
|
|
13564
13630
|
//var cancel_token: windows.DNS.QUERY.CANCEL = undefined;
|
|
13631
|
+
// Workaround various bugs by attempting a synchronous non-wire query first
|
|
13565
13632
|
switch (DnsQueryEx.?(&.{
|
|
13566
13633
|
.Version = 1,
|
|
13567
13634
|
.QueryName = &host_name_w,
|
|
13568
13635
|
.QueryType = if (options.family == .ip4) .A else .AAAA,
|
|
13569
13636
|
.QueryOptions = .{
|
|
13637
|
+
.NO_WIRE_QUERY = true,
|
|
13638
|
+
.NO_HOSTS_FILE = true, // handled above
|
|
13570
13639
|
.ADDRCONFIG = true,
|
|
13571
13640
|
.DUAL_ADDR = options.family == null,
|
|
13572
|
-
.MULTICAST_WAIT = true,
|
|
13573
13641
|
},
|
|
13574
|
-
|
|
13575
|
-
|
|
13576
|
-
//&cancel_token,
|
|
13577
|
-
null)) {
|
|
13642
|
+
}, &lookup_dns.results, null)) {
|
|
13643
|
+
.SUCCESS => try lookup_dns.completedFallible(),
|
|
13578
13644
|
// We must wait for the APC routine.
|
|
13579
|
-
.
|
|
13580
|
-
|
|
13581
|
-
|
|
13582
|
-
|
|
13583
|
-
|
|
13584
|
-
|
|
13585
|
-
|
|
13586
|
-
|
|
13587
|
-
|
|
13588
|
-
|
|
13589
|
-
|
|
13590
|
-
|
|
13591
|
-
|
|
13592
|
-
|
|
13593
|
-
|
|
13594
|
-
} else switch (status) {
|
|
13645
|
+
.DNS_REQUEST_PENDING => unreachable, // `pQueryCompletionCallback` was `null`
|
|
13646
|
+
.DNS_ERROR_RECORD_DOES_NOT_EXIST => switch (DnsQueryEx.?(&.{
|
|
13647
|
+
.Version = 1,
|
|
13648
|
+
.QueryName = &host_name_w,
|
|
13649
|
+
.QueryType = if (options.family == .ip4) .A else .AAAA,
|
|
13650
|
+
.QueryOptions = .{
|
|
13651
|
+
.NO_HOSTS_FILE = true, // handled above
|
|
13652
|
+
.ADDRCONFIG = true,
|
|
13653
|
+
.DUAL_ADDR = options.family == null,
|
|
13654
|
+
.MULTICAST_WAIT = true,
|
|
13655
|
+
},
|
|
13656
|
+
.pQueryCompletionCallback = if (current_thread) |_| &LookupDnsWindows.completed else null,
|
|
13657
|
+
}, &lookup_dns.results,
|
|
13658
|
+
//&cancel_token,
|
|
13659
|
+
null)) {
|
|
13595
13660
|
.SUCCESS => try lookup_dns.completedFallible(),
|
|
13596
|
-
|
|
13597
|
-
|
|
13661
|
+
// We must wait for the APC routine.
|
|
13662
|
+
.DNS_REQUEST_PENDING => {
|
|
13663
|
+
assert(current_thread != null); // `pQueryCompletionCallback` was `null`
|
|
13664
|
+
while (!@atomicLoad(bool, &lookup_dns.done, .acquire)) {
|
|
13665
|
+
// Once we get here we must not return from the function until the
|
|
13666
|
+
// operation completes, thereby releasing references to `host_name_w`,
|
|
13667
|
+
// `lookup_dns.results`, and `cancel_token`.
|
|
13668
|
+
const alertable_syscall = AlertableSyscall.start() catch |err| switch (err) {
|
|
13669
|
+
error.Canceled => |e| {
|
|
13670
|
+
//_ = DnsCancelQuery.?(&cancel_token);
|
|
13671
|
+
while (!@atomicLoad(bool, &lookup_dns.done, .acquire)) waitForApcOrAlert();
|
|
13672
|
+
return e;
|
|
13673
|
+
},
|
|
13674
|
+
};
|
|
13675
|
+
waitForApcOrAlert();
|
|
13676
|
+
alertable_syscall.finish();
|
|
13677
|
+
}
|
|
13678
|
+
},
|
|
13679
|
+
else => |status| lookup_dns.results.QueryStatus = status,
|
|
13598
13680
|
},
|
|
13599
13681
|
else => |status| lookup_dns.results.QueryStatus = status,
|
|
13600
13682
|
}
|
|
13601
13683
|
switch (lookup_dns.results.QueryStatus) {
|
|
13602
13684
|
.SUCCESS => return,
|
|
13603
13685
|
.DNS_REQUEST_PENDING => unreachable, // already handled
|
|
13604
|
-
.INVALID_NAME,
|
|
13686
|
+
.INVALID_NAME,
|
|
13687
|
+
.DNS_ERROR_RCODE_NAME_ERROR,
|
|
13688
|
+
.DNS_INFO_NO_RECORDS,
|
|
13689
|
+
.DNS_ERROR_INVALID_NAME_CHAR,
|
|
13690
|
+
.DNS_ERROR_RECORD_DOES_NOT_EXIST,
|
|
13691
|
+
=> return error.UnknownHostName,
|
|
13605
13692
|
else => |err| return windows.unexpectedError(err),
|
|
13606
13693
|
}
|
|
13607
13694
|
}
|
|
13608
13695
|
|
|
13609
|
-
// On Linux, glibc provides getaddrinfo_a which is capable of supporting our semantics.
|
|
13610
|
-
// However, musl's POSIX-compliant getaddrinfo is not, so we bypass it.
|
|
13611
|
-
|
|
13612
|
-
if (builtin.target.isGnuLibC()) {
|
|
13613
|
-
// TODO use getaddrinfo_a / gai_cancel
|
|
13614
|
-
}
|
|
13615
|
-
|
|
13616
|
-
if (native_os == .linux) {
|
|
13617
|
-
if (options.family != .ip4) {
|
|
13618
|
-
if (IpAddress.parseIp6(name, options.port)) |addr| {
|
|
13619
|
-
if (copyCanon(options.canonical_name_buffer, name)) |canon| {
|
|
13620
|
-
try resolved.putAll(t_io, &.{
|
|
13621
|
-
.{ .address = addr },
|
|
13622
|
-
.{ .canonical_name = canon },
|
|
13623
|
-
});
|
|
13624
|
-
} else {
|
|
13625
|
-
try resolved.putOne(t_io, .{ .address = addr });
|
|
13626
|
-
}
|
|
13627
|
-
return;
|
|
13628
|
-
} else |_| {}
|
|
13629
|
-
}
|
|
13630
|
-
|
|
13631
|
-
if (options.family != .ip6) {
|
|
13632
|
-
if (IpAddress.parseIp4(name, options.port)) |addr| {
|
|
13633
|
-
if (copyCanon(options.canonical_name_buffer, name)) |canon| {
|
|
13634
|
-
try resolved.putAll(t_io, &.{
|
|
13635
|
-
.{ .address = addr },
|
|
13636
|
-
.{ .canonical_name = canon },
|
|
13637
|
-
});
|
|
13638
|
-
} else {
|
|
13639
|
-
try resolved.putOne(t_io, .{ .address = addr });
|
|
13640
|
-
}
|
|
13641
|
-
return;
|
|
13642
|
-
} else |_| {}
|
|
13643
|
-
}
|
|
13644
|
-
|
|
13645
|
-
t.lookupHosts(host_name, resolved, options) catch |err| switch (err) {
|
|
13646
|
-
error.UnknownHostName => {},
|
|
13647
|
-
else => |e| return e,
|
|
13648
|
-
};
|
|
13649
|
-
|
|
13650
|
-
// RFC 6761 Section 6.3.3
|
|
13651
|
-
// Name resolution APIs and libraries SHOULD recognize
|
|
13652
|
-
// localhost names as special and SHOULD always return the IP
|
|
13653
|
-
// loopback address for address queries and negative responses
|
|
13654
|
-
// for all other query types.
|
|
13655
|
-
|
|
13656
|
-
// Check for equal to "localhost(.)" or ends in ".localhost(.)"
|
|
13657
|
-
const localhost = if (name[name.len - 1] == '.') "localhost." else "localhost";
|
|
13658
|
-
if (std.mem.endsWith(u8, name, localhost) and
|
|
13659
|
-
(name.len == localhost.len or name[name.len - localhost.len] == '.'))
|
|
13660
|
-
{
|
|
13661
|
-
var results_buffer: [3]HostName.LookupResult = undefined;
|
|
13662
|
-
var results_index: usize = 0;
|
|
13663
|
-
if (options.family != .ip4) {
|
|
13664
|
-
results_buffer[results_index] = .{ .address = .{ .ip6 = .loopback(options.port) } };
|
|
13665
|
-
results_index += 1;
|
|
13666
|
-
}
|
|
13667
|
-
if (options.family != .ip6) {
|
|
13668
|
-
results_buffer[results_index] = .{ .address = .{ .ip4 = .loopback(options.port) } };
|
|
13669
|
-
results_index += 1;
|
|
13670
|
-
}
|
|
13671
|
-
if (options.canonical_name_buffer) |buf| {
|
|
13672
|
-
const canon_name = "localhost";
|
|
13673
|
-
const canon_name_dest = buf[0..canon_name.len];
|
|
13674
|
-
canon_name_dest.* = canon_name.*;
|
|
13675
|
-
results_buffer[results_index] = .{ .canonical_name = .{ .bytes = canon_name_dest } };
|
|
13676
|
-
results_index += 1;
|
|
13677
|
-
}
|
|
13678
|
-
try resolved.putAll(t_io, results_buffer[0..results_index]);
|
|
13679
|
-
return;
|
|
13680
|
-
}
|
|
13681
|
-
|
|
13682
|
-
return t.lookupDnsSearch(host_name, resolved, options);
|
|
13683
|
-
}
|
|
13684
|
-
|
|
13685
13696
|
if (native_os == .openbsd) {
|
|
13686
13697
|
// TODO use getaddrinfo_async / asr_abort
|
|
13687
13698
|
}
|
|
@@ -14510,8 +14521,32 @@ fn lookupHosts(
|
|
|
14510
14521
|
resolved: *Io.Queue(HostName.LookupResult),
|
|
14511
14522
|
options: HostName.LookupOptions,
|
|
14512
14523
|
) !void {
|
|
14513
|
-
const
|
|
14514
|
-
|
|
14524
|
+
const path_w = if (is_windows) path_w: {
|
|
14525
|
+
var path_w_buf: [windows.PATH_MAX_WIDE:0]u16 = undefined;
|
|
14526
|
+
const system_dir = windows.getSystemDirectoryWtf16Le();
|
|
14527
|
+
const suffix = [_]u16{
|
|
14528
|
+
'\\', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\\', 'e', 't', 'c', '\\', 'h', 'o', 's', 't', 's',
|
|
14529
|
+
};
|
|
14530
|
+
@memcpy(path_w_buf[0..system_dir.len], system_dir);
|
|
14531
|
+
@memcpy(path_w_buf[system_dir.len..][0..suffix.len], &suffix);
|
|
14532
|
+
path_w_buf[system_dir.len + suffix.len] = 0;
|
|
14533
|
+
break :path_w wToPrefixedFileW(null, &path_w_buf, .{}) catch |err| switch (err) {
|
|
14534
|
+
error.FileNotFound,
|
|
14535
|
+
error.AccessDenied,
|
|
14536
|
+
=> return error.UnknownHostName,
|
|
14537
|
+
|
|
14538
|
+
error.Canceled => |e| return e,
|
|
14539
|
+
|
|
14540
|
+
else => {
|
|
14541
|
+
// Here we could add more detailed diagnostics to the results queue.
|
|
14542
|
+
return error.DetectingNetworkConfigurationFailed;
|
|
14543
|
+
},
|
|
14544
|
+
};
|
|
14545
|
+
};
|
|
14546
|
+
const file = (if (is_windows)
|
|
14547
|
+
dirOpenFileWtf16(null, path_w.span(), .{})
|
|
14548
|
+
else
|
|
14549
|
+
dirOpenFile(t, .cwd(), "/etc/hosts", .{})) catch |err| switch (err) {
|
|
14515
14550
|
error.FileNotFound,
|
|
14516
14551
|
error.NotDir,
|
|
14517
14552
|
error.AccessDenied,
|
|
@@ -14524,10 +14559,10 @@ fn lookupHosts(
|
|
|
14524
14559
|
return error.DetectingNetworkConfigurationFailed;
|
|
14525
14560
|
},
|
|
14526
14561
|
};
|
|
14527
|
-
defer file
|
|
14562
|
+
defer fileClose(t, &.{file});
|
|
14528
14563
|
|
|
14529
14564
|
var line_buf: [512]u8 = undefined;
|
|
14530
|
-
var file_reader = file.reader(
|
|
14565
|
+
var file_reader = file.reader(t.io(), &line_buf);
|
|
14531
14566
|
return t.lookupHostsReader(host_name, resolved, options, &file_reader.interface) catch |err| switch (err) {
|
|
14532
14567
|
error.ReadFailed => switch (file_reader.err.?) {
|
|
14533
14568
|
error.Canceled => |e| return e,
|
|
@@ -14567,14 +14602,17 @@ fn lookupHostsReader(
|
|
|
14567
14602
|
error.EndOfStream => break,
|
|
14568
14603
|
};
|
|
14569
14604
|
reader.toss(@min(1, reader.bufferedLen()));
|
|
14570
|
-
var split_it = std.mem.splitScalar(u8, line,
|
|
14605
|
+
var split_it = std.mem.splitScalar(u8, if (is_windows and std.mem.endsWith(u8, line, "\r"))
|
|
14606
|
+
line[0 .. line.len - 1]
|
|
14607
|
+
else
|
|
14608
|
+
line, '#');
|
|
14571
14609
|
const no_comment_line = split_it.first();
|
|
14572
14610
|
|
|
14573
14611
|
var line_it = std.mem.tokenizeAny(u8, no_comment_line, " \t");
|
|
14574
14612
|
const ip_text = line_it.next() orelse continue;
|
|
14575
14613
|
var first_name_text: ?[]const u8 = null;
|
|
14576
14614
|
while (line_it.next()) |name_text| {
|
|
14577
|
-
if (std.
|
|
14615
|
+
if (std.ascii.eqlIgnoreCase(name_text, host_name.bytes)) {
|
|
14578
14616
|
if (first_name_text == null) first_name_text = name_text;
|
|
14579
14617
|
break;
|
|
14580
14618
|
}
|
|
@@ -15239,7 +15277,7 @@ fn childWaitPosix(child: *process.Child) process.Child.WaitError!process.Child.T
|
|
|
15239
15277
|
return switch (code) {
|
|
15240
15278
|
.EXITED => .{ .exited = @truncate(status) },
|
|
15241
15279
|
.KILLED, .DUMPED => .{ .signal = @enumFromInt(status) },
|
|
15242
|
-
.TRAPPED, .STOPPED => .{ .stopped = status },
|
|
15280
|
+
.TRAPPED, .STOPPED => .{ .stopped = @enumFromInt(status) },
|
|
15243
15281
|
_, .CONTINUED => .{ .unknown = status },
|
|
15244
15282
|
};
|
|
15245
15283
|
},
|
package/std/Io/Uring.zig
CHANGED
|
@@ -4729,7 +4729,7 @@ fn childWait(userdata: ?*anyopaque, child: *process.Child) process.Child.WaitErr
|
|
|
4729
4729
|
return switch (code) {
|
|
4730
4730
|
.EXITED => .{ .exited = @truncate(status) },
|
|
4731
4731
|
.KILLED, .DUMPED => .{ .signal = @enumFromInt(status) },
|
|
4732
|
-
.TRAPPED, .STOPPED => .{ .stopped = status },
|
|
4732
|
+
.TRAPPED, .STOPPED => .{ .stopped = @enumFromInt(status) },
|
|
4733
4733
|
_, .CONTINUED => .{ .unknown = status },
|
|
4734
4734
|
};
|
|
4735
4735
|
},
|
|
@@ -5673,6 +5673,7 @@ fn openat(
|
|
|
5673
5673
|
.AGAIN => return error.WouldBlock,
|
|
5674
5674
|
.TXTBSY => return error.FileBusy,
|
|
5675
5675
|
.NXIO => return error.NoDevice,
|
|
5676
|
+
.ROFS => return error.ReadOnlyFileSystem,
|
|
5676
5677
|
.ILSEQ => return error.BadPathName,
|
|
5677
5678
|
else => |err| return unexpectedErrno(err),
|
|
5678
5679
|
}
|
package/std/Io/Writer.zig
CHANGED
|
@@ -551,64 +551,64 @@ pub fn writeAll(w: *Writer, bytes: []const u8) Error!void {
|
|
|
551
551
|
while (index < bytes.len) index += try w.write(bytes[index..]);
|
|
552
552
|
}
|
|
553
553
|
|
|
554
|
-
/// Renders fmt string with args
|
|
555
|
-
/// If `writer` returns an error, the error is returned from `format` and
|
|
556
|
-
/// `writer` is not called again.
|
|
554
|
+
/// Renders `fmt` string with `args`, calling `w` with slices of bytes.
|
|
557
555
|
///
|
|
558
|
-
/// The format string must be comptime-known and may contain placeholders
|
|
559
|
-
/// this format:
|
|
560
|
-
///
|
|
556
|
+
/// The format string must be comptime-known and may contain placeholders
|
|
557
|
+
/// following this format:
|
|
558
|
+
/// ```
|
|
559
|
+
/// {[argument][specifier]:[fill][alignment][width].[precision]}
|
|
560
|
+
/// ```
|
|
561
561
|
///
|
|
562
|
-
/// Above, each word including its surrounding [ and ] is a parameter
|
|
562
|
+
/// Above, each word including its surrounding [ and ] is a parameter to be replaced with:
|
|
563
563
|
///
|
|
564
|
-
/// -
|
|
565
|
-
/// -
|
|
566
|
-
/// brackets, e.g. {[score]...} as opposed to the numeric index form which can be written e.g. {2...}
|
|
567
|
-
/// -
|
|
568
|
-
/// -
|
|
569
|
-
/// -
|
|
564
|
+
/// - **argument** is either the numeric index or the field name of the argument that should be inserted.
|
|
565
|
+
/// - When using a field name, the field name (an identifier) must be enclosed in square
|
|
566
|
+
/// brackets, e.g. `{[score]...}` as opposed to the numeric index form which can be written e.g. `{2...}`.
|
|
567
|
+
/// - **specifier** is a type-dependent formatting option that determines how a type should formatted (see below).
|
|
568
|
+
/// - **fill** is a single byte which is used to pad formatted numbers.
|
|
569
|
+
/// - **alignment** is one of the three bytes '<', '^', or '>' to make numbers
|
|
570
570
|
/// left, center, or right-aligned, respectively.
|
|
571
571
|
/// - Not all specifiers support alignment.
|
|
572
|
-
/// - Alignment is not Unicode-aware; appropriate only when used with raw
|
|
573
|
-
///
|
|
574
|
-
/// -
|
|
572
|
+
/// - Alignment is not Unicode-aware; appropriate only when used with raw
|
|
573
|
+
/// bytes or ASCII.
|
|
574
|
+
/// - **width** is the total size of the field in bytes, only applicable to
|
|
575
|
+
/// number formatting.
|
|
576
|
+
/// - **precision** specifies how many decimals a formatted number should have.
|
|
575
577
|
///
|
|
576
|
-
///
|
|
577
|
-
///
|
|
578
|
-
/// separator are omitted.
|
|
578
|
+
/// Most of the parameters are optional and may be omitted. The separators (':'
|
|
579
|
+
/// and '.') may be omitted when all parameters afterwards are omitted.
|
|
579
580
|
///
|
|
580
|
-
///
|
|
581
|
-
/// required at the same time as
|
|
582
|
-
///
|
|
583
|
-
/// *width*, not *fill*.
|
|
581
|
+
/// The **fill** parameter is an exception. If a non-zero **fill** character is
|
|
582
|
+
/// required at the same time as **width** is specified, **alignment** is
|
|
583
|
+
/// required, otherwise the digit following ':' is interpreted as **width**.
|
|
584
584
|
///
|
|
585
|
-
///
|
|
586
|
-
/// - `x` and `X`:
|
|
585
|
+
/// **specifier** supports:
|
|
586
|
+
/// - `x` and `X`: numeric value in hexadecimal notation, or string in hexadecimal bytes
|
|
587
587
|
/// - `s`:
|
|
588
588
|
/// - for pointer-to-many and C pointers of u8, print as a C-string using zero-termination
|
|
589
589
|
/// - for slices of u8, print the entire slice as a string without zero-termination
|
|
590
590
|
/// - `t`:
|
|
591
591
|
/// - for enums and tagged unions: prints the tag name
|
|
592
592
|
/// - for error sets: prints the error name
|
|
593
|
-
/// - `b64`:
|
|
594
|
-
/// - `e`:
|
|
595
|
-
/// - `d`:
|
|
596
|
-
/// - `b`:
|
|
597
|
-
/// - `o`:
|
|
598
|
-
/// - `c`:
|
|
599
|
-
/// - `u`:
|
|
600
|
-
/// - `
|
|
601
|
-
/// - `
|
|
602
|
-
/// - `
|
|
603
|
-
/// -
|
|
604
|
-
/// -
|
|
605
|
-
/// -
|
|
606
|
-
/// - `any`: output a value of any type using its default format.
|
|
593
|
+
/// - `b64`: string as standard base64
|
|
594
|
+
/// - `e`: floating point value in scientific notation
|
|
595
|
+
/// - `d`: numeric value in decimal notation
|
|
596
|
+
/// - `b`: integer value in binary notation
|
|
597
|
+
/// - `o`: integer value in octal notation
|
|
598
|
+
/// - `c`: integer as an ASCII character. Integer type must have 8 bits at max.
|
|
599
|
+
/// - `u`: integer as an UTF-8 sequence. Integer type must have 21 bits at max.
|
|
600
|
+
/// - `B`: bytes in SI units (decimal)
|
|
601
|
+
/// - `Bi`: bytes in IEC units (binary)
|
|
602
|
+
/// - `?`: optional value as either the unwrapped value, or `null`; may be followed by a format specifier for the underlying value.
|
|
603
|
+
/// - `!`: error union value as either the unwrapped value, or the formatted error value; may be followed by a format specifier for the underlying value.
|
|
604
|
+
/// - `*`: the address of the value instead of the value itself.
|
|
605
|
+
/// - `any`: a value of any type using its default format.
|
|
607
606
|
/// - `f`: delegates to a method on the type named "format" with the signature `fn (*Writer, args: anytype) Writer.Error!void`.
|
|
608
607
|
///
|
|
609
|
-
/// A user type may be a
|
|
608
|
+
/// A user type may be a struct, vector, union or enum type.
|
|
610
609
|
///
|
|
611
|
-
///
|
|
610
|
+
/// Literal curly braces can be escaped in the format string via doubling, e.g.
|
|
611
|
+
/// `{{` or `}}`.
|
|
612
612
|
pub fn print(w: *Writer, comptime fmt: []const u8, args: anytype) Error!void {
|
|
613
613
|
const ArgsType = @TypeOf(args);
|
|
614
614
|
const args_type_info = @typeInfo(ArgsType);
|