aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/Build.zig8
-rw-r--r--lib/std/Build/Step/Compile.zig4
-rw-r--r--lib/std/Build/Step/RemoveDir.zig6
-rw-r--r--lib/std/Uri.zig2
-rw-r--r--lib/std/atomic/queue.zig2
-rw-r--r--lib/std/atomic/stack.zig4
-rw-r--r--lib/std/base64.zig6
-rw-r--r--lib/std/bit_set.zig4
-rw-r--r--lib/std/crypto/ff.zig158
-rw-r--r--lib/std/debug.zig2
-rw-r--r--lib/std/elf.zig24
-rw-r--r--lib/std/enums.zig2
-rw-r--r--lib/std/event/loop.zig16
-rw-r--r--lib/std/fifo.zig6
-rw-r--r--lib/std/fmt.zig4
-rw-r--r--lib/std/fs.zig2
-rw-r--r--lib/std/fs/file.zig10
-rw-r--r--lib/std/hash_map.zig17
-rw-r--r--lib/std/http.zig8
-rw-r--r--lib/std/http/Headers.zig2
-rw-r--r--lib/std/io/limited_reader.zig2
-rw-r--r--lib/std/math.zig5
-rw-r--r--lib/std/math/big/int.zig3
-rw-r--r--lib/std/math/big/rational.zig4
-rw-r--r--lib/std/os.zig6
-rw-r--r--lib/std/os/linux.zig2
-rw-r--r--lib/std/os/linux/io_uring.zig98
-rw-r--r--lib/std/rand.zig77
-rw-r--r--lib/std/rand/ziggurat.zig5
-rw-r--r--lib/std/sort/block.zig2
-rw-r--r--lib/std/target.zig6
-rw-r--r--lib/std/valgrind.zig2
-rw-r--r--lib/std/wasm.zig4
-rw-r--r--lib/std/zig/system/NativePaths.zig1
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;