diff options
Diffstat (limited to 'lib/std')
34 files changed, 333 insertions, 171 deletions
diff --git a/lib/std/Build.zig b/lib/std/Build.zig index d2d09539cb..c67f8ac0e5 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -839,7 +839,7 @@ pub fn addAssembly(b: *Build, options: AssemblyOptions) *Step.Compile { .max_rss = options.max_rss, .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir, }); - obj_step.addAssemblyLazyPath(options.source_file.dupe(b)); + obj_step.addAssemblyFile(options.source_file); return obj_step; } @@ -904,7 +904,7 @@ pub fn addRunArtifact(b: *Build, exe: *Step.Compile) *Step.Run { const run_step = Step.Run.create(b, b.fmt("run {s}", .{exe.name})); run_step.addArtifactArg(exe); - if (exe.kind == .@"test") { + if (exe.kind == .@"test" and exe.test_server_mode) { run_step.enableTestRunnerMode(); } @@ -971,9 +971,7 @@ pub fn addWriteFiles(b: *Build) *Step.WriteFile { } pub fn addRemoveDirTree(self: *Build, dir_path: []const u8) *Step.RemoveDir { - const remove_dir_step = self.allocator.create(Step.RemoveDir) catch @panic("OOM"); - remove_dir_step.* = Step.RemoveDir.init(self, dir_path); - return remove_dir_step; + return Step.RemoveDir.create(self, dir_path); } pub fn addFmt(b: *Build, options: Step.Fmt.Options) *Step.Fmt { diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 90e20c10c3..2dfa21fc10 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -73,6 +73,7 @@ exec_cmd_args: ?[]const ?[]const u8, filter: ?[]const u8, test_evented_io: bool = false, test_runner: ?[]const u8, +test_server_mode: bool, code_model: std.builtin.CodeModel = .default, wasi_exec_model: ?std.builtin.WasiExecModel = null, /// Symbols to be exported when compiling to wasm @@ -243,6 +244,8 @@ pub const RcSourceFile = struct { file: LazyPath, /// Any option that rc.exe accepts will work here, with the exception of: /// - `/fo`: The output filename is set by the build system + /// - `/p`: Only running the preprocessor is not supported in this context + /// - `/:no-preprocess` (non-standard option): Not supported in this context /// - Any MUI-related option /// https://learn.microsoft.com/en-us/windows/win32/menurc/using-rc-the-rc-command-line- /// @@ -499,6 +502,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile { .exec_cmd_args = null, .filter = options.filter, .test_runner = options.test_runner, + .test_server_mode = options.test_runner == null, .disable_stack_probing = false, .disable_sanitize_c = false, .sanitize_thread = false, diff --git a/lib/std/Build/Step/RemoveDir.zig b/lib/std/Build/Step/RemoveDir.zig index 7666dd2a7d..7a2a56771a 100644 --- a/lib/std/Build/Step/RemoveDir.zig +++ b/lib/std/Build/Step/RemoveDir.zig @@ -8,8 +8,9 @@ pub const base_id = .remove_dir; step: Step, dir_path: []const u8, -pub fn init(owner: *std.Build, dir_path: []const u8) RemoveDir { - return RemoveDir{ +pub fn create(owner: *std.Build, dir_path: []const u8) *RemoveDir { + const self = owner.allocator.create(RemoveDir) catch @panic("OOM"); + self.* = .{ .step = Step.init(.{ .id = .remove_dir, .name = owner.fmt("RemoveDir {s}", .{dir_path}), @@ -18,6 +19,7 @@ pub fn init(owner: *std.Build, dir_path: []const u8) RemoveDir { }), .dir_path = owner.dupePath(dir_path), }; + return self; } fn make(step: *Step, prog_node: *std.Progress.Node) !void { diff --git a/lib/std/Uri.zig b/lib/std/Uri.zig index 83e7da7649..6952839e71 100644 --- a/lib/std/Uri.zig +++ b/lib/std/Uri.zig @@ -129,7 +129,7 @@ pub fn unescapeString(allocator: std.mem.Allocator, input: []const u8) error{Out pub const ParseError = error{ UnexpectedCharacter, InvalidFormat, InvalidPort }; /// Parses the URI or returns an error. This function is not compliant, but is required to parse -/// some forms of URIs in the wild. Such as HTTP Location headers. +/// some forms of URIs in the wild, such as HTTP Location headers. /// The return value will contain unescaped strings pointing into the /// original `text`. Each component that is provided, will be non-`null`. pub fn parseWithoutScheme(text: []const u8) ParseError!Uri { diff --git a/lib/std/atomic/queue.zig b/lib/std/atomic/queue.zig index 7094cce964..e8d37507d3 100644 --- a/lib/std/atomic/queue.zig +++ b/lib/std/atomic/queue.zig @@ -27,7 +27,7 @@ pub fn Queue(comptime T: type) type { } /// Appends `node` to the queue. - /// The lifetime of `node` must be longer than lifetime of queue. + /// The lifetime of `node` must be longer than the lifetime of the queue. pub fn put(self: *Self, node: *Node) void { node.next = null; diff --git a/lib/std/atomic/stack.zig b/lib/std/atomic/stack.zig index 1289217652..1f19869fd6 100644 --- a/lib/std/atomic/stack.zig +++ b/lib/std/atomic/stack.zig @@ -3,8 +3,8 @@ const builtin = @import("builtin"); const assert = std.debug.assert; const expect = std.testing.expect; -/// Many reader, many writer, non-allocating, thread-safe -/// Uses a spinlock to protect push() and pop() +/// Many reader, many writer, non-allocating, thread-safe. +/// Uses a spinlock to protect `push()` and `pop()`. /// When building in single threaded mode, this is a simple linked list. pub fn Stack(comptime T: type) type { return struct { diff --git a/lib/std/base64.zig b/lib/std/base64.zig index a2f766dc26..26f1b1be61 100644 --- a/lib/std/base64.zig +++ b/lib/std/base64.zig @@ -203,8 +203,8 @@ pub const Base64Decoder = struct { } /// dest.len must be what you get from ::calcSize. - /// invalid characters result in error.InvalidCharacter. - /// invalid padding results in error.InvalidPadding. + /// Invalid characters result in `error.InvalidCharacter`. + /// Invalid padding results in `error.InvalidPadding`. pub fn decode(decoder: *const Base64Decoder, dest: []u8, source: []const u8) Error!void { if (decoder.pad_char != null and source.len % 4 != 0) return error.InvalidPadding; var dest_idx: usize = 0; @@ -291,7 +291,7 @@ pub const Base64DecoderWithIgnore = struct { return result; } - /// Return the maximum possible decoded size for a given input length - The actual length may be less if the input includes padding + /// Return the maximum possible decoded size for a given input length - The actual length may be less if the input includes padding. /// `InvalidPadding` is returned if the input length is not valid. pub fn calcSizeUpperBound(decoder_with_ignore: *const Base64DecoderWithIgnore, source_len: usize) Error!usize { var result = source_len / 4 * 3; diff --git a/lib/std/bit_set.zig b/lib/std/bit_set.zig index 9e5c707b84..430f521eb6 100644 --- a/lib/std/bit_set.zig +++ b/lib/std/bit_set.zig @@ -753,7 +753,7 @@ pub const DynamicBitSetUnmanaged = struct { self.bit_length = new_len; } - /// deinitializes the array and releases its memory. + /// Deinitializes the array and releases its memory. /// The passed allocator must be the same one used for /// init* or resize in the past. pub fn deinit(self: *Self, allocator: Allocator) void { @@ -1058,7 +1058,7 @@ pub const DynamicBitSet = struct { try self.unmanaged.resize(self.allocator, new_len, fill); } - /// deinitializes the array and releases its memory. + /// Deinitializes the array and releases its memory. /// The passed allocator must be the same one used for /// init* or resize in the past. pub fn deinit(self: *Self) void { diff --git a/lib/std/crypto/ff.zig b/lib/std/crypto/ff.zig index aec17cc7d5..287d37544f 100644 --- a/lib/std/crypto/ff.zig +++ b/lib/std/crypto/ff.zig @@ -656,6 +656,101 @@ pub fn Modulus(comptime max_bits: comptime_int) type { return d; } + // Returns x^e (mod m), with the exponent provided as a byte string. + // `public` must be set to `false` if the exponent it secret. + fn powWithEncodedExponentInternal(self: Self, x: Fe, e: []const u8, endian: builtin.Endian, comptime public: bool) NullExponentError!Fe { + var acc: u8 = 0; + for (e) |b| acc |= b; + if (acc == 0) return error.NullExponent; + + var out = self.one(); + self.toMontgomery(&out) catch unreachable; + + if (public and e.len < 3 or (e.len == 3 and e[if (endian == .Big) 0 else 2] <= 0b1111)) { + // Do not use a precomputation table for short, public exponents + var x_m = x; + if (x.montgomery == false) { + self.toMontgomery(&x_m) catch unreachable; + } + var s = switch (endian) { + .Big => 0, + .Little => e.len - 1, + }; + while (true) { + const b = e[s]; + var j: u3 = 7; + while (true) : (j -= 1) { + out = self.montgomerySq(out); + const k: u1 = @truncate(b >> j); + if (k != 0) { + const t = self.montgomeryMul(out, x_m); + @memcpy(out.v.limbs.slice(), t.v.limbs.constSlice()); + } + if (j == 0) break; + } + switch (endian) { + .Big => { + s += 1; + if (s == e.len) break; + }, + .Little => { + if (s == 0) break; + s -= 1; + }, + } + } + } else { + // Use a precomputation table for large exponents + var pc = [1]Fe{x} ++ [_]Fe{self.zero} ** 14; + if (x.montgomery == false) { + self.toMontgomery(&pc[0]) catch unreachable; + } + for (1..pc.len) |i| { + pc[i] = self.montgomeryMul(pc[i - 1], pc[0]); + } + var t0 = self.zero; + var s = switch (endian) { + .Big => 0, + .Little => e.len - 1, + }; + while (true) { + const b = e[s]; + for ([_]u3{ 4, 0 }) |j| { + for (0..4) |_| { + out = self.montgomerySq(out); + } + const k = (b >> j) & 0b1111; + if (public or std.options.side_channels_mitigations == .none) { + if (k == 0) continue; + t0 = pc[k - 1]; + } else { + for (pc, 0..) |t, i| { + t0.v.cmov(ct.eql(k, @as(u8, @truncate(i + 1))), t.v); + } + } + const t1 = self.montgomeryMul(out, t0); + if (public) { + @memcpy(out.v.limbs.slice(), t1.v.limbs.constSlice()); + } else { + out.v.cmov(!ct.eql(k, 0), t1.v); + } + } + switch (endian) { + .Big => { + s += 1; + if (s == e.len) break; + }, + .Little => { + if (s == 0) break; + s -= 1; + }, + } + } + } + self.fromMontgomery(&out) catch unreachable; + return out; + } + /// Multiplies two field elements. pub fn mul(self: Self, x: Fe, y: Fe) Fe { if (x.montgomery != y.montgomery) { @@ -698,62 +793,25 @@ pub fn Modulus(comptime max_bits: comptime_int) type { e_normalized.toBytes(buf, .Little) catch unreachable; const leading = @clz(e_normalized.v.limbs.get(e_normalized.v.limbs_count() - carry_bits)); buf = buf[0 .. buf.len - leading / 8]; - return self.powWithEncodedExponent(x, buf, .Little); + return self.powWithEncodedPublicExponent(x, buf, .Little); } - /// Returns x^e (mod m), assuming that the exponent is public, and provided as a byte string. + /// Returns x^e (mod m), with the exponent provided as a byte string. /// Exponents are usually small, so this function is faster than `powPublic` as a field element /// doesn't have to be created if a serialized representation is already available. + /// + /// If the exponent is public, `powWithEncodedPublicExponent()` can be used instead for a slight speedup. pub fn powWithEncodedExponent(self: Self, x: Fe, e: []const u8, endian: builtin.Endian) NullExponentError!Fe { - var acc: u8 = 0; - for (e) |b| acc |= b; - if (acc == 0) return error.NullExponent; + return self.powWithEncodedExponentInternal(x, e, endian, false); + } - var pc = [1]Fe{x} ++ [_]Fe{self.zero} ** 14; - if (x.montgomery == false) { - self.toMontgomery(&pc[0]) catch unreachable; - } - for (1..pc.len) |i| { - pc[i] = self.montgomeryMul(pc[i - 1], pc[0]); - } - var out = self.one(); - self.toMontgomery(&out) catch unreachable; - var t0 = self.zero; - var s = switch (endian) { - .Big => 0, - .Little => e.len - 1, - }; - while (true) { - const b = e[s]; - for ([_]u3{ 4, 0 }) |j| { - for (0..4) |_| { - out = self.montgomerySq(out); - } - const k = (b >> j) & 0b1111; - if (std.options.side_channels_mitigations == .none) { - if (k == 0) continue; - t0 = pc[k - 1]; - } else { - for (pc, 0..) |t, i| { - t0.v.cmov(ct.eql(k, @as(u8, @truncate(i + 1))), t.v); - } - } - const t1 = self.montgomeryMul(out, t0); - out.v.cmov(!ct.eql(k, 0), t1.v); - } - switch (endian) { - .Big => { - s += 1; - if (s == e.len) break; - }, - .Little => { - if (s == 0) break; - s -= 1; - }, - } - } - self.fromMontgomery(&out) catch unreachable; - return out; + /// Returns x^e (mod m), the exponent being public and provided as a byte string. + /// Exponents are usually small, so this function is faster than `powPublic` as a field element + /// doesn't have to be created if a serialized representation is already available. + /// + /// If the exponent is secret, `powWithEncodedExponent` must be used instead. + pub fn powWithEncodedPublicExponent(self: Self, x: Fe, e: []const u8, endian: builtin.Endian) NullExponentError!Fe { + return self.powWithEncodedExponentInternal(x, e, endian, true); } }; } diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 95bc8d0eaf..4af395beb4 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -2340,7 +2340,7 @@ pub fn updateSegfaultHandler(act: ?*const os.Sigaction) error{OperationNotSuppor try os.sigaction(os.SIG.FPE, act, null); } -/// Attaches a global SIGSEGV handler which calls @panic("segmentation fault"); +/// Attaches a global SIGSEGV handler which calls `@panic("segmentation fault");` pub fn attachSegfaultHandler() void { if (!have_segfault_handling_support) { @compileError("segfault handler not supported for this target"); diff --git a/lib/std/elf.zig b/lib/std/elf.zig index 4c314fadc1..4bb30b854d 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -782,10 +782,10 @@ pub const Elf32_Sym = extern struct { st_shndx: Elf32_Section, pub inline fn st_type(self: @This()) u4 { - return @as(u4, @truncate(self.st_info)); + return @truncate(self.st_info); } pub inline fn st_bind(self: @This()) u4 { - return @as(u4, @truncate(self.st_info >> 4)); + return @truncate(self.st_info >> 4); } }; pub const Elf64_Sym = extern struct { @@ -797,10 +797,10 @@ pub const Elf64_Sym = extern struct { st_size: Elf64_Xword, pub inline fn st_type(self: @This()) u4 { - return @as(u4, @truncate(self.st_info)); + return @truncate(self.st_info); } pub inline fn st_bind(self: @This()) u4 { - return @as(u4, @truncate(self.st_info >> 4)); + return @truncate(self.st_info >> 4); } }; pub const Elf32_Syminfo = extern struct { @@ -816,10 +816,10 @@ pub const Elf32_Rel = extern struct { r_info: Elf32_Word, pub inline fn r_sym(self: @This()) u24 { - return @as(u24, @truncate(self.r_info >> 8)); + return @truncate(self.r_info >> 8); } pub inline fn r_type(self: @This()) u8 { - return @as(u8, @truncate(self.r_info)); + return @truncate(self.r_info); } }; pub const Elf64_Rel = extern struct { @@ -827,10 +827,10 @@ pub const Elf64_Rel = extern struct { r_info: Elf64_Xword, pub inline fn r_sym(self: @This()) u32 { - return @as(u32, @truncate(self.r_info >> 32)); + return @truncate(self.r_info >> 32); } pub inline fn r_type(self: @This()) u32 { - return @as(u32, @truncate(self.r_info)); + return @truncate(self.r_info); } }; pub const Elf32_Rela = extern struct { @@ -839,10 +839,10 @@ pub const Elf32_Rela = extern struct { r_addend: Elf32_Sword, pub inline fn r_sym(self: @This()) u24 { - return @as(u24, @truncate(self.r_info >> 8)); + return @truncate(self.r_info >> 8); } pub inline fn r_type(self: @This()) u8 { - return @as(u8, @truncate(self.r_info)); + return @truncate(self.r_info); } }; pub const Elf64_Rela = extern struct { @@ -851,10 +851,10 @@ pub const Elf64_Rela = extern struct { r_addend: Elf64_Sxword, pub inline fn r_sym(self: @This()) u32 { - return @as(u32, @truncate(self.r_info >> 32)); + return @truncate(self.r_info >> 32); } pub inline fn r_type(self: @This()) u32 { - return @as(u32, @truncate(self.r_info)); + return @truncate(self.r_info); } }; pub const Elf32_Dyn = extern struct { diff --git a/lib/std/enums.zig b/lib/std/enums.zig index 4caf78f869..de112b8257 100644 --- a/lib/std/enums.zig +++ b/lib/std/enums.zig @@ -425,7 +425,7 @@ pub fn BoundedEnumMultiset(comptime E: type, comptime CountSize: type) type { } } - /// Deccreases the all key counts by given multiset. If + /// Decreases the all key counts by given multiset. If /// the given multiset has more key counts than this, /// then that key will have a key count of zero. pub fn removeSet(self: *Self, other: Self) void { diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index b5021a5378..883312d176 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -969,21 +969,21 @@ pub const Loop = struct { /// This argument is a socket that has been created with `socket`, bound to a local address /// with `bind`, and is listening for connections after a `listen`. sockfd: os.socket_t, - /// This argument is a pointer to a sockaddr structure. This structure is filled in with the - /// address of the peer socket, as known to the communications layer. The exact format of the - /// address returned addr is determined by the socket's address family (see `socket` and the - /// respective protocol man pages). + /// This argument is a pointer to a sockaddr structure. This structure is filled in with the + /// address of the peer socket, as known to the communications layer. The exact format of the + /// address returned addr is determined by the socket's address family (see `socket` and the + /// respective protocol man pages). addr: *os.sockaddr, - /// This argument is a value-result argument: the caller must initialize it to contain the + /// This argument is a value-result argument: the caller must initialize it to contain the /// size (in bytes) of the structure pointed to by addr; on return it will contain the actual size /// of the peer address. /// - /// The returned address is truncated if the buffer provided is too small; in this case, `addr_size` + /// The returned address is truncated if the buffer provided is too small; in this case, `addr_size` /// will return a value greater than was supplied to the call. addr_size: *os.socklen_t, /// The following values can be bitwise ORed in flags to obtain different behavior: - /// * `SOCK.CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor. See the - /// description of the `O.CLOEXEC` flag in `open` for reasons why this may be useful. + /// * `SOCK.CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor. See the + /// description of the `O.CLOEXEC` flag in `open` for reasons why this may be useful. flags: u32, ) os.AcceptError!os.socket_t { while (true) { diff --git a/lib/std/fifo.zig b/lib/std/fifo.zig index 5d798cb99d..5b19125e02 100644 --- a/lib/std/fifo.zig +++ b/lib/std/fifo.zig @@ -242,7 +242,7 @@ pub fn LinearFifo( return self.buf.len - self.count; } - /// Returns the first section of writable buffer + /// Returns the first section of writable buffer. /// Note that this may be of length 0 pub fn writableSlice(self: SliceSelfArg, offset: usize) []T { if (offset > self.buf.len) return &[_]T{}; @@ -371,8 +371,8 @@ pub fn LinearFifo( return self.buf[index]; } - /// Pump data from a reader into a writer - /// stops when reader returns 0 bytes (EOF) + /// Pump data from a reader into a writer. + /// Stops when reader returns 0 bytes (EOF). /// Buffer size must be set before calling; a buffer length of 0 is invalid. pub fn pump(self: *Self, src_reader: anytype, dest_writer: anytype) !void { assert(self.buf.len > 0); diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 8a72047652..9538d91fa3 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -1989,8 +1989,8 @@ pub const BufPrintError = error{ NoSpaceLeft, }; -/// print a Formatter string into `buf`. Actually just a thin wrapper around `format` and `fixedBufferStream`. -/// returns a slice of the bytes printed to. +/// Print a Formatter string into `buf`. Actually just a thin wrapper around `format` and `fixedBufferStream`. +/// Returns a slice of the bytes printed to. pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: anytype) BufPrintError![]u8 { var fbs = std.io.fixedBufferStream(buf); try format(fbs.writer(), fmt, args); diff --git a/lib/std/fs.zig b/lib/std/fs.zig index 43fb6ec0c8..6cda6716b7 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -204,7 +204,7 @@ pub const AtomicFile = struct { } } - /// always call deinit, even after successful finish() + /// Always call deinit, even after a successful finish(). pub fn deinit(self: *AtomicFile) void { if (self.file_open) { self.file.close(); diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index c19a19a3d3..3436aa4b33 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -453,7 +453,7 @@ pub const File = struct { } /// Sets whether write permissions are provided. - /// On Unix, this affects *all* classes. If this is undesired, use `unixSet` + /// On Unix, this affects *all* classes. If this is undesired, use `unixSet`. /// This method *DOES NOT* set permissions on the filesystem: use `File.setPermissions(permissions)` pub fn setReadOnly(self: *Self, read_only: bool) void { self.inner.setReadOnly(read_only); @@ -493,7 +493,7 @@ pub const File = struct { } /// Sets whether write permissions are provided. - /// This affects *all* classes. If this is undesired, use `unixSet` + /// This affects *all* classes. If this is undesired, use `unixSet`. /// This method *DOES NOT* set permissions on the filesystem: use `File.setPermissions(permissions)` pub fn setReadOnly(self: *Self, read_only: bool) void { if (read_only) { @@ -706,7 +706,7 @@ pub const File = struct { return @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec; } - /// Returns the time the file was created in nanoseconds since UTC 1970-01-01 + /// Returns the time the file was created in nanoseconds since UTC 1970-01-01. /// Returns null if this is not supported by the OS or filesystem pub fn created(self: Self) ?i128 { if (!@hasDecl(@TypeOf(self.stat), "birthtime")) return null; @@ -772,7 +772,7 @@ pub const File = struct { return @as(i128, self.statx.mtime.tv_sec) * std.time.ns_per_s + self.statx.mtime.tv_nsec; } - /// Returns the time the file was created in nanoseconds since UTC 1970-01-01 + /// Returns the time the file was created in nanoseconds since UTC 1970-01-01. /// Returns null if this is not supported by the filesystem, or on kernels before than version 4.11 pub fn created(self: Self) ?i128 { if (self.statx.mask & os.linux.STATX_BTIME == 0) return null; @@ -825,7 +825,7 @@ pub const File = struct { return self.modified_time; } - /// Returns the time the file was created in nanoseconds since UTC 1970-01-01 + /// Returns the time the file was created in nanoseconds since UTC 1970-01-01. /// This never returns null, only returning an optional for compatibility with other OSes pub fn created(self: Self) ?i128 { return self.creation_time; diff --git a/lib/std/hash_map.zig b/lib/std/hash_map.zig index 91d07c2eb0..40a412bf3c 100644 --- a/lib/std/hash_map.zig +++ b/lib/std/hash_map.zig @@ -92,7 +92,7 @@ pub fn hashString(s: []const u8) u64 { } pub const StringIndexContext = struct { - bytes: *std.ArrayListUnmanaged(u8), + bytes: *const std.ArrayListUnmanaged(u8), pub fn eql(self: @This(), a: u32, b: u32) bool { _ = self; @@ -106,7 +106,7 @@ pub const StringIndexContext = struct { }; pub const StringIndexAdapter = struct { - bytes: *std.ArrayListUnmanaged(u8), + bytes: *const std.ArrayListUnmanaged(u8), pub fn eql(self: @This(), a_slice: []const u8, b: u32) bool { const b_slice = mem.sliceTo(@as([*:0]const u8, @ptrCast(self.bytes.items.ptr)) + b, 0); @@ -126,6 +126,7 @@ pub const default_max_load_percentage = 80; /// member functions: /// - hash(self, PseudoKey) Hash /// - eql(self, PseudoKey, Key) bool +/// /// If you are passing a context to a *Adapted function, PseudoKey is the type /// of the key parameter. Otherwise, when creating a HashMap or HashMapUnmanaged /// type, PseudoKey = Key = K. @@ -469,7 +470,7 @@ pub fn HashMap( } /// If key exists this function cannot fail. - /// If there is an existing item with `key`, then the result + /// If there is an existing item with `key`, then the result's /// `Entry` pointers point to it, and found_existing is true. /// Otherwise, puts a new item with undefined value, and /// the `Entry` pointers point to it. Caller should then initialize @@ -479,7 +480,7 @@ pub fn HashMap( } /// If key exists this function cannot fail. - /// If there is an existing item with `key`, then the result + /// If there is an existing item with `key`, then the result's /// `Entry` pointers point to it, and found_existing is true. /// Otherwise, puts a new item with undefined key and value, and /// the `Entry` pointers point to it. Caller must then initialize @@ -488,7 +489,7 @@ pub fn HashMap( return self.unmanaged.getOrPutContextAdapted(self.allocator, key, ctx, self.ctx); } - /// If there is an existing item with `key`, then the result + /// If there is an existing item with `key`, then the result's /// `Entry` pointers point to it, and found_existing is true. /// Otherwise, puts a new item with undefined value, and /// the `Entry` pointers point to it. Caller should then initialize @@ -499,7 +500,7 @@ pub fn HashMap( return self.unmanaged.getOrPutAssumeCapacityContext(key, self.ctx); } - /// If there is an existing item with `key`, then the result + /// If there is an existing item with `key`, then the result's /// `Entry` pointers point to it, and found_existing is true. /// Otherwise, puts a new item with undefined value, and /// the `Entry` pointers point to it. Caller must then initialize @@ -565,7 +566,7 @@ pub fn HashMap( } /// Inserts a new `Entry` into the hash map, returning the previous one, if any. - /// If insertion happuns, asserts there is enough capacity without allocating. + /// If insertion happens, asserts there is enough capacity without allocating. pub fn fetchPutAssumeCapacity(self: *Self, key: K, value: V) ?KV { return self.unmanaged.fetchPutAssumeCapacityContext(key, value, self.ctx); } @@ -684,7 +685,7 @@ pub fn HashMap( } /// A HashMap based on open addressing and linear probing. -/// A lookup or modification typically occurs only 2 cache misses. +/// A lookup or modification typically incurs only 2 cache misses. /// No order is guaranteed and any modification invalidates live iterators. /// It achieves good performance with quite high load factors (by default, /// grow is triggered at 80% full) and only one byte of overhead per element. diff --git a/lib/std/http.zig b/lib/std/http.zig index 12dc4b89cd..532e5a6de8 100644 --- a/lib/std/http.zig +++ b/lib/std/http.zig @@ -14,7 +14,9 @@ pub const Version = enum { }; /// https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods +/// /// https://datatracker.ietf.org/doc/html/rfc7231#section-4 Initial definition +/// /// https://datatracker.ietf.org/doc/html/rfc5789#section-2 PATCH pub const Method = enum(u64) { // TODO: should be u192 or u256, but neither is supported by the C backend, and therefore cannot pass CI GET = parse("GET"), @@ -68,7 +70,9 @@ pub const Method = enum(u64) { // TODO: should be u192 or u256, but neither is s } /// An HTTP method is safe if it doesn't alter the state of the server. + /// /// https://developer.mozilla.org/en-US/docs/Glossary/Safe/HTTP + /// /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.1 pub fn safe(self: Method) bool { return switch (self) { @@ -79,7 +83,9 @@ pub const Method = enum(u64) { // TODO: should be u192 or u256, but neither is s } /// 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://datatracker.ietf.org/doc/html/rfc7231#section-4.2.2 pub fn idempotent(self: Method) bool { return switch (self) { @@ -90,7 +96,9 @@ pub const Method = enum(u64) { // TODO: should be u192 or u256, but neither is s } /// 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. + /// /// https://developer.mozilla.org/en-US/docs/Glossary/cacheable + /// /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.3 pub fn cacheable(self: Method) bool { return switch (self) { diff --git a/lib/std/http/Headers.zig b/lib/std/http/Headers.zig index b4c722119a..f69f7fef5f 100644 --- a/lib/std/http/Headers.zig +++ b/lib/std/http/Headers.zig @@ -249,7 +249,7 @@ pub const Headers = struct { try out_stream.writeAll("\r\n"); } - /// Frees all `HeaderIndexList`s within `index` + /// Frees all `HeaderIndexList`s within `index`. /// Frees names and values of all fields if they are owned. fn deallocateIndexListsAndFields(headers: *Headers) void { var it = headers.index.iterator(); diff --git a/lib/std/io/limited_reader.zig b/lib/std/io/limited_reader.zig index 09d76007da..d7e2503881 100644 --- a/lib/std/io/limited_reader.zig +++ b/lib/std/io/limited_reader.zig @@ -26,7 +26,7 @@ pub fn LimitedReader(comptime ReaderType: type) type { }; } -/// Returns an initialised `LimitedReader` +/// Returns an initialised `LimitedReader`. /// `bytes_left` is a `u64` to be able to take 64 bit file offsets pub fn limitedReader(inner_reader: anytype, bytes_left: u64) LimitedReader(@TypeOf(inner_reader)) { return .{ .inner_reader = inner_reader, .bytes_left = bytes_left }; diff --git a/lib/std/math.zig b/lib/std/math.zig index 336007be57..817a98f314 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -1214,7 +1214,9 @@ pub fn lossyCast(comptime T: type, value: anytype) T { } }, .Float, .ComptimeFloat => { - if (value >= maxInt(T)) { + if (isNan(value)) { + return 0; + } else if (value >= maxInt(T)) { return @as(T, maxInt(T)); } else if (value <= minInt(T)) { return @as(T, minInt(T)); @@ -1234,6 +1236,7 @@ test "lossyCast" { try testing.expect(lossyCast(u32, @as(i16, -255)) == @as(u32, 0)); try testing.expect(lossyCast(i9, @as(u32, 200)) == @as(i9, 200)); try testing.expect(lossyCast(u32, @as(f32, maxInt(u32))) == maxInt(u32)); + try testing.expect(lossyCast(u32, nan(f32)) == 0); } /// Performs linear interpolation between *a* and *b* based on *t*. diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index 93c21f0216..a761151e7b 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -452,6 +452,7 @@ pub const Mutable = struct { } /// r = a + b + /// /// r, a and b may be aliases. /// /// Asserts the result fits in `r`. An upper bound on the number of limbs needed by @@ -1869,7 +1870,7 @@ pub const Mutable = struct { } } - /// Read the value of `x` from `buffer` + /// Read the value of `x` from `buffer`. /// Asserts that `buffer` is large enough to contain a value of bit-size `bit_count`. /// /// The contents of `buffer` are interpreted as if they were the contents of diff --git a/lib/std/math/big/rational.zig b/lib/std/math/big/rational.zig index 2e52fae9d3..ee641adf50 100644 --- a/lib/std/math/big/rational.zig +++ b/lib/std/math/big/rational.zig @@ -333,8 +333,8 @@ pub const Rational = struct { r.q.swap(&other.q); } - /// Returns math.Order.lt, math.Order.eq, math.Order.gt if a < b, a == b or a - /// > b respectively. + /// Returns math.Order.lt, math.Order.eq, math.Order.gt if a < b, a == b or + /// a > b respectively. pub fn order(a: Rational, b: Rational) !math.Order { return cmpInternal(a, b, false); } diff --git a/lib/std/os.zig b/lib/std/os.zig index 90e738d775..1ae5157d8b 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -2355,7 +2355,10 @@ pub fn unlinkZ(file_path: [*:0]const u8) UnlinkError!void { /// Windows-only. Same as `unlink` except the parameter is null-terminated, WTF16 encoded. pub fn unlinkW(file_path_w: []const u16) UnlinkError!void { - return windows.DeleteFile(file_path_w, .{ .dir = std.fs.cwd().fd }); + windows.DeleteFile(file_path_w, .{ .dir = std.fs.cwd().fd }) catch |err| switch (err) { + error.DirNotEmpty => unreachable, // we're not passing .remove_dir = true + else => |e| return e, + }; } pub const UnlinkatError = UnlinkError || error{ @@ -3026,6 +3029,7 @@ pub const FchdirError = error{ } || UnexpectedError; pub fn fchdir(dirfd: fd_t) FchdirError!void { + if (dirfd == AT.FDCWD) return; while (true) { switch (errno(system.fchdir(dirfd))) { .SUCCESS => return, diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 2ecb5da231..d2a6b5f55e 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -1030,7 +1030,7 @@ pub fn clock_settime(clk_id: i32, tp: *const timespec) usize { return syscall2(.clock_settime, @as(usize, @bitCast(@as(isize, clk_id))), @intFromPtr(tp)); } -pub fn gettimeofday(tv: *timeval, tz: *timezone) usize { +pub fn gettimeofday(tv: ?*timeval, tz: ?*timezone) usize { return syscall2(.gettimeofday, @intFromPtr(tv), @intFromPtr(tz)); } diff --git a/lib/std/os/linux/io_uring.zig b/lib/std/os/linux/io_uring.zig index f87cd453b9..7f7dd21f95 100644 --- a/lib/std/os/linux/io_uring.zig +++ b/lib/std/os/linux/io_uring.zig @@ -413,6 +413,27 @@ pub const IO_Uring = struct { return sqe; } + /// Queues (but does not submit) an SQE to perform a `splice(2)` + /// Either `fd_in` or `fd_out` must be a pipe. + /// If `fd_in` refers to a pipe, `off_in` is ignored and must be set to -1. + /// If `fd_in` does not refer to a pipe and `off_in` is -1, then `len` are read + /// from `fd_in` starting from the file offset, which is incremented by the number of bytes read. + /// If `fd_in` does not refer to a pipe and `off_in` is not -1, then the starting offset of `fd_in` will be `off_in`. + /// This splice operation can be used to implement sendfile by splicing to an intermediate pipe first, + /// then splice to the final destination. In fact, the implementation of sendfile in kernel uses splice internally. + /// + /// NOTE that even if fd_in or fd_out refers to a pipe, the splice operation can still fail with EINVAL if one of the + /// fd doesn't explicitly support splice peration, e.g. reading from terminal is unsupported from kernel 5.7 to 5.11. + /// See https://github.com/axboe/liburing/issues/291 + /// + /// Returns a pointer to the SQE so that you can further modify the SQE for advanced use cases. + pub fn splice(self: *IO_Uring, user_data: u64, fd_in: os.fd_t, off_in: i64, fd_out: os.fd_t, off_out: i64, len: usize) !*linux.io_uring_sqe { + const sqe = try self.get_sqe(); + io_uring_prep_splice(sqe, fd_in, off_in, fd_out, off_out, len); + sqe.user_data = user_data; + return sqe; + } + /// Queues (but does not submit) an SQE to perform a IORING_OP_READ_FIXED. /// The `buffer` provided must be registered with the kernel by calling `register_buffers` first. /// The `buffer_index` must be the same as its index in the array provided to `register_buffers`. @@ -1244,6 +1265,12 @@ pub fn io_uring_prep_write(sqe: *linux.io_uring_sqe, fd: os.fd_t, buffer: []cons io_uring_prep_rw(.WRITE, sqe, fd, @intFromPtr(buffer.ptr), buffer.len, offset); } +pub fn io_uring_prep_splice(sqe: *linux.io_uring_sqe, fd_in: os.fd_t, off_in: i64, fd_out: os.fd_t, off_out: i64, len: usize) void { + io_uring_prep_rw(.SPLICE, sqe, fd_out, undefined, len, @bitCast(off_out)); + sqe.addr = @bitCast(off_in); + sqe.splice_fd_in = fd_in; +} + pub fn io_uring_prep_readv( sqe: *linux.io_uring_sqe, fd: os.fd_t, @@ -1828,6 +1855,77 @@ test "write/read" { try testing.expectEqualSlices(u8, buffer_write[0..], buffer_read[0..]); } +test "splice/read" { + if (builtin.os.tag != .linux) return error.SkipZigTest; + + var ring = IO_Uring.init(4, 0) catch |err| switch (err) { + error.SystemOutdated => return error.SkipZigTest, + error.PermissionDenied => return error.SkipZigTest, + else => return err, + }; + defer ring.deinit(); + + var tmp = std.testing.tmpDir(.{}); + const path_src = "test_io_uring_splice_src"; + const file_src = try tmp.dir.createFile(path_src, .{ .read = true, .truncate = true }); + defer file_src.close(); + const fd_src = file_src.handle; + + const path_dst = "test_io_uring_splice_dst"; + const file_dst = try tmp.dir.createFile(path_dst, .{ .read = true, .truncate = true }); + defer file_dst.close(); + const fd_dst = file_dst.handle; + + const buffer_write = [_]u8{97} ** 20; + var buffer_read = [_]u8{98} ** 20; + _ = try file_src.write(&buffer_write); + + var fds = try os.pipe(); + const pipe_offset: i64 = -1; + + const sqe_splice_to_pipe = try ring.splice(0x11111111, fd_src, 0, fds[1], pipe_offset, buffer_write.len); + try testing.expectEqual(linux.IORING_OP.SPLICE, sqe_splice_to_pipe.opcode); + try testing.expectEqual(@as(u64, 0), sqe_splice_to_pipe.addr); + try testing.expectEqual(@as(u64, @bitCast((pipe_offset))), sqe_splice_to_pipe.off); + sqe_splice_to_pipe.flags |= linux.IOSQE_IO_LINK; + + const sqe_splice_from_pipe = try ring.splice(0x22222222, fds[0], pipe_offset, fd_dst, 10, buffer_write.len); + try testing.expectEqual(linux.IORING_OP.SPLICE, sqe_splice_from_pipe.opcode); + try testing.expectEqual(@as(u64, @bitCast(pipe_offset)), sqe_splice_from_pipe.addr); + try testing.expectEqual(@as(u64, 10), sqe_splice_from_pipe.off); + sqe_splice_from_pipe.flags |= linux.IOSQE_IO_LINK; + + const sqe_read = try ring.read(0x33333333, fd_dst, .{ .buffer = buffer_read[0..] }, 10); + try testing.expectEqual(linux.IORING_OP.READ, sqe_read.opcode); + try testing.expectEqual(@as(u64, 10), sqe_read.off); + try testing.expectEqual(@as(u32, 3), try ring.submit()); + + const cqe_splice_to_pipe = try ring.copy_cqe(); + const cqe_splice_from_pipe = try ring.copy_cqe(); + const cqe_read = try ring.copy_cqe(); + // Prior to Linux Kernel 5.6 this is the only way to test for splice/read support: + // https://lwn.net/Articles/809820/ + if (cqe_splice_to_pipe.err() == .INVAL) return error.SkipZigTest; + if (cqe_splice_from_pipe.err() == .INVAL) return error.SkipZigTest; + if (cqe_read.err() == .INVAL) return error.SkipZigTest; + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x11111111, + .res = buffer_write.len, + .flags = 0, + }, cqe_splice_to_pipe); + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x22222222, + .res = buffer_write.len, + .flags = 0, + }, cqe_splice_from_pipe); + try testing.expectEqual(linux.io_uring_cqe{ + .user_data = 0x33333333, + .res = buffer_read.len, + .flags = 0, + }, cqe_read); + try testing.expectEqualSlices(u8, buffer_write[0..], buffer_read[0..]); +} + test "write_fixed/read_fixed" { if (builtin.os.tag != .linux) return error.SkipZigTest; diff --git a/lib/std/rand.zig b/lib/std/rand.zig index 84dc9d2daf..c573a94d61 100644 --- a/lib/std/rand.zig +++ b/lib/std/rand.zig @@ -113,22 +113,16 @@ pub const Random = struct { // TODO: endian portability is pointless if the underlying prng isn't endian portable. // TODO: document the endian portability of this library. const byte_aligned_result = mem.readIntSliceLittle(ByteAlignedT, &rand_bytes); - const unsigned_result = @as(UnsignedT, @truncate(byte_aligned_result)); - return @as(T, @bitCast(unsigned_result)); + const unsigned_result: UnsignedT = @truncate(byte_aligned_result); + return @bitCast(unsigned_result); } /// Constant-time implementation off `uintLessThan`. /// The results of this function may be biased. pub fn uintLessThanBiased(r: Random, comptime T: type, less_than: T) T { comptime assert(@typeInfo(T).Int.signedness == .unsigned); - const bits = @typeInfo(T).Int.bits; - comptime assert(bits <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation! assert(0 < less_than); - if (bits <= 32) { - return @as(T, @intCast(limitRangeBiased(u32, r.int(u32), less_than))); - } else { - return @as(T, @intCast(limitRangeBiased(u64, r.int(u64), less_than))); - } + return limitRangeBiased(T, r.int(T), less_than); } /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`. @@ -142,22 +136,16 @@ pub const Random = struct { pub fn uintLessThan(r: Random, comptime T: type, less_than: T) T { comptime assert(@typeInfo(T).Int.signedness == .unsigned); const bits = @typeInfo(T).Int.bits; - comptime assert(bits <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation! assert(0 < less_than); - // Small is typically u32 - const small_bits = @divTrunc(bits + 31, 32) * 32; - const Small = std.meta.Int(.unsigned, small_bits); - // Large is typically u64 - const Large = std.meta.Int(.unsigned, small_bits * 2); // adapted from: // http://www.pcg-random.org/posts/bounded-rands.html // "Lemire's (with an extra tweak from me)" - var x: Small = r.int(Small); - var m: Large = @as(Large, x) * @as(Large, less_than); - var l: Small = @as(Small, @truncate(m)); + var x = r.int(T); + var m = math.mulWide(T, x, less_than); + var l: T = @truncate(m); if (l < less_than) { - var t: Small = -%less_than; + var t = -%less_than; if (t >= less_than) { t -= less_than; @@ -166,12 +154,12 @@ pub const Random = struct { } } while (l < t) { - x = r.int(Small); - m = @as(Large, x) * @as(Large, less_than); - l = @as(Small, @truncate(m)); + x = r.int(T); + m = math.mulWide(T, x, less_than); + l = @truncate(m); } } - return @as(T, @intCast(m >> small_bits)); + return @intCast(m >> bits); } /// Constant-time implementation off `uintAtMost`. @@ -205,10 +193,10 @@ pub const Random = struct { if (info.signedness == .signed) { // Two's complement makes this math pretty easy. const UnsignedT = std.meta.Int(.unsigned, info.bits); - const lo = @as(UnsignedT, @bitCast(at_least)); - const hi = @as(UnsignedT, @bitCast(less_than)); + const lo: UnsignedT = @bitCast(at_least); + const hi: UnsignedT = @bitCast(less_than); const result = lo +% r.uintLessThanBiased(UnsignedT, hi -% lo); - return @as(T, @bitCast(result)); + return @bitCast(result); } else { // The signed implementation would work fine, but we can use stricter arithmetic operators here. return at_least + r.uintLessThanBiased(T, less_than - at_least); @@ -224,10 +212,10 @@ pub const Random = struct { if (info.signedness == .signed) { // Two's complement makes this math pretty easy. const UnsignedT = std.meta.Int(.unsigned, info.bits); - const lo = @as(UnsignedT, @bitCast(at_least)); - const hi = @as(UnsignedT, @bitCast(less_than)); + const lo: UnsignedT = @bitCast(at_least); + const hi: UnsignedT = @bitCast(less_than); const result = lo +% r.uintLessThan(UnsignedT, hi -% lo); - return @as(T, @bitCast(result)); + return @bitCast(result); } else { // The signed implementation would work fine, but we can use stricter arithmetic operators here. return at_least + r.uintLessThan(T, less_than - at_least); @@ -242,10 +230,10 @@ pub const Random = struct { if (info.signedness == .signed) { // Two's complement makes this math pretty easy. const UnsignedT = std.meta.Int(.unsigned, info.bits); - const lo = @as(UnsignedT, @bitCast(at_least)); - const hi = @as(UnsignedT, @bitCast(at_most)); + const lo: UnsignedT = @bitCast(at_least); + const hi: UnsignedT = @bitCast(at_most); const result = lo +% r.uintAtMostBiased(UnsignedT, hi -% lo); - return @as(T, @bitCast(result)); + return @bitCast(result); } else { // The signed implementation would work fine, but we can use stricter arithmetic operators here. return at_least + r.uintAtMostBiased(T, at_most - at_least); @@ -261,10 +249,10 @@ pub const Random = struct { if (info.signedness == .signed) { // Two's complement makes this math pretty easy. const UnsignedT = std.meta.Int(.unsigned, info.bits); - const lo = @as(UnsignedT, @bitCast(at_least)); - const hi = @as(UnsignedT, @bitCast(at_most)); + const lo: UnsignedT = @bitCast(at_least); + const hi: UnsignedT = @bitCast(at_most); const result = lo +% r.uintAtMost(UnsignedT, hi -% lo); - return @as(T, @bitCast(result)); + return @bitCast(result); } else { // The signed implementation would work fine, but we can use stricter arithmetic operators here. return at_least + r.uintAtMost(T, at_most - at_least); @@ -293,9 +281,9 @@ pub const Random = struct { rand_lz += @clz(r.int(u32) | 0x7FF); } } - const mantissa = @as(u23, @truncate(rand)); + const mantissa: u23 = @truncate(rand); const exponent = @as(u32, 126 - rand_lz) << 23; - return @as(f32, @bitCast(exponent | mantissa)); + return @bitCast(exponent | mantissa); }, f64 => { // Use 52 random bits for the mantissa, and the rest for the exponent. @@ -320,7 +308,7 @@ pub const Random = struct { } const mantissa = rand & 0xFFFFFFFFFFFFF; const exponent = (1022 - rand_lz) << 52; - return @as(f64, @bitCast(exponent | mantissa)); + return @bitCast(exponent | mantissa); }, else => @compileError("unknown floating point type"), } @@ -332,7 +320,7 @@ pub const Random = struct { pub fn floatNorm(r: Random, comptime T: type) T { const value = ziggurat.next_f64(r, ziggurat.NormDist); switch (T) { - f32 => return @as(f32, @floatCast(value)), + f32 => return @floatCast(value), f64 => return value, else => @compileError("unknown floating point type"), } @@ -344,7 +332,7 @@ pub const Random = struct { pub fn floatExp(r: Random, comptime T: type) T { const value = ziggurat.next_f64(r, ziggurat.ExpDist); switch (T) { - f32 => return @as(f32, @floatCast(value)), + f32 => return @floatCast(value), f64 => return value, else => @compileError("unknown floating point type"), } @@ -378,10 +366,10 @@ pub const Random = struct { } // `i <= j < max <= maxInt(MinInt)` - const max = @as(MinInt, @intCast(buf.len)); + const max: MinInt = @intCast(buf.len); var i: MinInt = 0; while (i < max - 1) : (i += 1) { - const j = @as(MinInt, @intCast(r.intRangeLessThan(Index, i, max))); + const j: MinInt = @intCast(r.intRangeLessThan(Index, i, max)); mem.swap(T, &buf[i], &buf[j]); } } @@ -438,13 +426,12 @@ pub const Random = struct { pub fn limitRangeBiased(comptime T: type, random_int: T, less_than: T) T { comptime assert(@typeInfo(T).Int.signedness == .unsigned); const bits = @typeInfo(T).Int.bits; - const T2 = std.meta.Int(.unsigned, bits * 2); // adapted from: // http://www.pcg-random.org/posts/bounded-rands.html // "Integer Multiplication (Biased)" - var m: T2 = @as(T2, random_int) * @as(T2, less_than); - return @as(T, @intCast(m >> bits)); + const m = math.mulWide(T, random_int, less_than); + return @intCast(m >> bits); } // Generator to extend 64-bit seed values into longer sequences. diff --git a/lib/std/rand/ziggurat.zig b/lib/std/rand/ziggurat.zig index 64417c1f3f..87045e4077 100644 --- a/lib/std/rand/ziggurat.zig +++ b/lib/std/rand/ziggurat.zig @@ -1,7 +1,6 @@ -//! Implements ZIGNOR [1]. +//! Implements [ZIGNOR][1] (Jurgen A. Doornik, 2005, Nuffield College, Oxford). //! -//! [1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to Generate Normal Random Samples*] -//! (https://www.doornik.com/research/ziggurat.pdf). Nuffield College, Oxford. +//! [1]: https://www.doornik.com/research/ziggurat.pdf //! //! rust/rand used as a reference; //! diff --git a/lib/std/sort/block.zig b/lib/std/sort/block.zig index a61ea6e326..fe6e628653 100644 --- a/lib/std/sort/block.zig +++ b/lib/std/sort/block.zig @@ -95,7 +95,7 @@ const Pull = struct { /// O(1) memory (no allocator required). /// Sorts in ascending order with respect to the given `lessThan` function. /// -/// NOTE: the algorithm only work when the comparison is less-than or greater-than +/// NOTE: The algorithm only works when the comparison is less-than or greater-than. /// (See https://github.com/ziglang/zig/issues/8289) pub fn block( comptime T: type, diff --git a/lib/std/target.zig b/lib/std/target.zig index 45681c1ac2..d0e6082ca8 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -342,10 +342,10 @@ pub const Target = struct { .linux => return .{ .linux = .{ .range = .{ - .min = .{ .major = 3, .minor = 16, .patch = 0 }, - .max = .{ .major = 5, .minor = 10, .patch = 81 }, + .min = .{ .major = 4, .minor = 19, .patch = 0 }, + .max = .{ .major = 6, .minor = 5, .patch = 7 }, }, - .glibc = .{ .major = 2, .minor = 19, .patch = 0 }, + .glibc = .{ .major = 2, .minor = 28, .patch = 0 }, }, }, diff --git a/lib/std/valgrind.zig b/lib/std/valgrind.zig index f42c56c1cc..43935fe37d 100644 --- a/lib/std/valgrind.zig +++ b/lib/std/valgrind.zig @@ -250,7 +250,7 @@ pub fn disableErrorReporting() void { doClientRequestStmt(.ChangeErrDisablement, 1, 0, 0, 0, 0); } -/// Re-enable error reporting, (see disableErrorReporting()) +/// Re-enable error reporting. (see disableErrorReporting()) pub fn enableErrorReporting() void { doClientRequestStmt(.ChangeErrDisablement, math.maxInt(usize), 0, 0, 0, 0); } diff --git a/lib/std/wasm.zig b/lib/std/wasm.zig index b02f72ed4c..84095ea9a8 100644 --- a/lib/std/wasm.zig +++ b/lib/std/wasm.zig @@ -216,7 +216,7 @@ test "Wasm - opcodes" { try testing.expectEqual(@as(u16, 0xC4), i64_extend32_s); } -/// Opcodes that require a prefix `0xFC` +/// Opcodes that require a prefix `0xFC`. /// Each opcode represents a varuint32, meaning /// they are encoded as leb128 in binary. pub const MiscOpcode = enum(u32) { @@ -793,7 +793,7 @@ pub fn section(val: Section) u8 { return @intFromEnum(val); } -/// The kind of the type when importing or exporting to/from the host environment +/// The kind of the type when importing or exporting to/from the host environment. /// https://webassembly.github.io/spec/core/syntax/modules.html pub const ExternalKind = enum(u8) { function, diff --git a/lib/std/zig/system/NativePaths.zig b/lib/std/zig/system/NativePaths.zig index af3243fc10..833d698d42 100644 --- a/lib/std/zig/system/NativePaths.zig +++ b/lib/std/zig/system/NativePaths.zig @@ -61,7 +61,6 @@ pub fn detect(arena: Allocator, native_info: NativeTargetInfo) !NativePaths { } else if (word.len > 2 and word[0] == '-' and word[1] == 'L') { const lib_path = word[2..]; try self.addLibDir(lib_path); - try self.addRPath(lib_path); } else { try self.addWarningFmt("Unrecognized C flag from NIX_LDFLAGS: {s}", .{word}); break; |
