aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/docs/wasm/markdown/Parser.zig2
-rw-r--r--lib/init/build.zig8
-rw-r--r--lib/init/build.zig.zon5
-rw-r--r--lib/std/Build.zig117
-rw-r--r--lib/std/Build/Module.zig15
-rw-r--r--lib/std/Build/Step/CheckObject.zig120
-rw-r--r--lib/std/Build/Step/Compile.zig41
-rw-r--r--lib/std/Build/Step/ConfigHeader.zig13
-rw-r--r--lib/std/Target.zig7
-rw-r--r--lib/std/Uri.zig644
-rw-r--r--lib/std/c/haiku.zig1305
-rw-r--r--lib/std/crypto/Certificate.zig2
-rw-r--r--lib/std/crypto/benchmark.zig7
-rw-r--r--lib/std/crypto/ecdsa.zig21
-rw-r--r--lib/std/crypto/keccak_p.zig25
-rw-r--r--lib/std/crypto/pcurves/p256/p256_64.zig18
-rw-r--r--lib/std/crypto/pcurves/p256/p256_scalar_64.zig18
-rw-r--r--lib/std/crypto/pcurves/p384/p384_64.zig18
-rw-r--r--lib/std/crypto/pcurves/p384/p384_scalar_64.zig18
-rw-r--r--lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig18
-rw-r--r--lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig18
-rw-r--r--lib/std/crypto/sha3.zig461
-rw-r--r--lib/std/debug.zig4
-rw-r--r--lib/std/fs/Dir.zig159
-rw-r--r--lib/std/hash/crc.zig1180
-rw-r--r--lib/std/hash/crc/catalog.zig903
-rw-r--r--lib/std/hash/crc/impl.zig241
-rw-r--r--lib/std/hash/crc/test.zig (renamed from lib/std/hash/crc/catalog_test.zig)245
-rw-r--r--lib/std/http/Client.zig239
-rw-r--r--lib/std/http/test.zig72
-rw-r--r--lib/std/io.zig2
-rw-r--r--lib/std/math/big/int.zig12
-rw-r--r--lib/std/math/big/int_test.zig13
-rw-r--r--lib/std/once.zig6
-rw-r--r--lib/std/posix/test.zig2
-rw-r--r--lib/std/tar.zig17
-rw-r--r--lib/std/zig/Zir.zig8
-rw-r--r--lib/std/zig/system.zig10
-rw-r--r--lib/std/zig/system/NativePaths.zig7
39 files changed, 3349 insertions, 2672 deletions
diff --git a/lib/docs/wasm/markdown/Parser.zig b/lib/docs/wasm/markdown/Parser.zig
index 7f463224be..fe4fc2f9b0 100644
--- a/lib/docs/wasm/markdown/Parser.zig
+++ b/lib/docs/wasm/markdown/Parser.zig
@@ -1540,7 +1540,7 @@ const InlineParser = struct {
iter.pos += 1;
return .{ .text = replacement };
};
- const is_valid = iter.pos + cp_len < iter.content.len and
+ const is_valid = iter.pos + cp_len <= iter.content.len and
std.unicode.utf8ValidateSlice(iter.content[iter.pos..][0..cp_len]);
const cp_encoded = if (is_valid)
iter.content[iter.pos..][0..cp_len]
diff --git a/lib/init/build.zig b/lib/init/build.zig
index e513acdf25..d53cbbb982 100644
--- a/lib/init/build.zig
+++ b/lib/init/build.zig
@@ -19,7 +19,7 @@ pub fn build(b: *std.Build) void {
.name = "$",
// In this case the main source file is merely a path, however, in more
// complicated build scripts, this could be a generated file.
- .root_source_file = .{ .path = "src/root.zig" },
+ .root_source_file = b.path("src/root.zig"),
.target = target,
.optimize = optimize,
});
@@ -31,7 +31,7 @@ pub fn build(b: *std.Build) void {
const exe = b.addExecutable(.{
.name = "$",
- .root_source_file = .{ .path = "src/main.zig" },
+ .root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
@@ -67,7 +67,7 @@ pub fn build(b: *std.Build) void {
// Creates a step for unit testing. This only builds the test executable
// but does not run it.
const lib_unit_tests = b.addTest(.{
- .root_source_file = .{ .path = "src/root.zig" },
+ .root_source_file = b.path("src/root.zig"),
.target = target,
.optimize = optimize,
});
@@ -75,7 +75,7 @@ pub fn build(b: *std.Build) void {
const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);
const exe_unit_tests = b.addTest(.{
- .root_source_file = .{ .path = "src/main.zig" },
+ .root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
diff --git a/lib/init/build.zig.zon b/lib/init/build.zig.zon
index dc9d138ba5..50da5587b1 100644
--- a/lib/init/build.zig.zon
+++ b/lib/init/build.zig.zon
@@ -37,6 +37,11 @@
// // build root. In this case the package's hash is irrelevant and therefore not
// // computed. This field and `url` are mutually exclusive.
// .path = "foo",
+
+ // // When this is set to `true`, a package is declared to be lazily
+ // // fetched. This makes the dependency only get fetched if it is
+ // // actually used.
+ // .lazy = false,
//},
},
diff --git a/lib/std/Build.zig b/lib/std/Build.zig
index 2c644ce4b0..a3d091858a 100644
--- a/lib/std/Build.zig
+++ b/lib/std/Build.zig
@@ -607,17 +607,17 @@ pub fn resolveInstallPrefix(self: *Build, install_prefix: ?[]const u8, dir_list:
var h_list = [_][]const u8{ self.install_path, "include" };
if (dir_list.lib_dir) |dir| {
- if (std.fs.path.isAbsolute(dir)) lib_list[0] = self.dest_dir orelse "";
+ if (fs.path.isAbsolute(dir)) lib_list[0] = self.dest_dir orelse "";
lib_list[1] = dir;
}
if (dir_list.exe_dir) |dir| {
- if (std.fs.path.isAbsolute(dir)) exe_list[0] = self.dest_dir orelse "";
+ if (fs.path.isAbsolute(dir)) exe_list[0] = self.dest_dir orelse "";
exe_list[1] = dir;
}
if (dir_list.include_dir) |dir| {
- if (std.fs.path.isAbsolute(dir)) h_list[0] = self.dest_dir orelse "";
+ if (fs.path.isAbsolute(dir)) h_list[0] = self.dest_dir orelse "";
h_list[1] = dir;
}
@@ -858,7 +858,7 @@ pub const TestOptions = struct {
/// deprecated: use `.filters = &.{filter}` instead of `.filter = filter`.
filter: ?[]const u8 = null,
filters: []const []const u8 = &.{},
- test_runner: ?[]const u8 = null,
+ test_runner: ?LazyPath = null,
link_libc: ?bool = null,
single_threaded: ?bool = null,
pic: ?bool = null,
@@ -1546,22 +1546,22 @@ pub fn addInstallArtifact(
}
///`dest_rel_path` is relative to prefix path
-pub fn installFile(self: *Build, src_path: []const u8, dest_rel_path: []const u8) void {
- self.getInstallStep().dependOn(&self.addInstallFileWithDir(.{ .path = src_path }, .prefix, dest_rel_path).step);
+pub fn installFile(b: *Build, src_path: []const u8, dest_rel_path: []const u8) void {
+ b.getInstallStep().dependOn(&b.addInstallFileWithDir(b.path(src_path), .prefix, dest_rel_path).step);
}
-pub fn installDirectory(self: *Build, options: Step.InstallDir.Options) void {
- self.getInstallStep().dependOn(&self.addInstallDirectory(options).step);
+pub fn installDirectory(b: *Build, options: Step.InstallDir.Options) void {
+ b.getInstallStep().dependOn(&b.addInstallDirectory(options).step);
}
///`dest_rel_path` is relative to bin path
-pub fn installBinFile(self: *Build, src_path: []const u8, dest_rel_path: []const u8) void {
- self.getInstallStep().dependOn(&self.addInstallFileWithDir(.{ .path = src_path }, .bin, dest_rel_path).step);
+pub fn installBinFile(b: *Build, src_path: []const u8, dest_rel_path: []const u8) void {
+ b.getInstallStep().dependOn(&b.addInstallFileWithDir(b.path(src_path), .bin, dest_rel_path).step);
}
///`dest_rel_path` is relative to lib path
-pub fn installLibFile(self: *Build, src_path: []const u8, dest_rel_path: []const u8) void {
- self.getInstallStep().dependOn(&self.addInstallFileWithDir(.{ .path = src_path }, .lib, dest_rel_path).step);
+pub fn installLibFile(b: *Build, src_path: []const u8, dest_rel_path: []const u8) void {
+ b.getInstallStep().dependOn(&b.addInstallFileWithDir(b.path(src_path), .lib, dest_rel_path).step);
}
pub fn addObjCopy(b: *Build, source: LazyPath, options: Step.ObjCopy.Options) *Step.ObjCopy {
@@ -1635,6 +1635,22 @@ pub fn truncateFile(self: *Build, dest_path: []const u8) !void {
src_file.close();
}
+/// References a file or directory relative to the source root.
+pub fn path(b: *Build, sub_path: []const u8) LazyPath {
+ if (fs.path.isAbsolute(sub_path)) {
+ std.debug.panic("sub_path is expected to be relative to the build root, but was this absolute path: '{s}'. It is best avoid absolute paths, but if you must, it is supported by LazyPath.cwd_relative", .{
+ sub_path,
+ });
+ }
+ return .{ .src_path = .{
+ .owner = b,
+ .sub_path = sub_path,
+ } };
+}
+
+/// This is low-level implementation details of the build system, not meant to
+/// be called by users' build scripts. Even in the build system itself it is a
+/// code smell to call this function.
pub fn pathFromRoot(b: *Build, p: []const u8) []u8 {
return fs.path.resolve(b.allocator, &.{ b.build_root.path orelse ".", p }) catch @panic("OOM");
}
@@ -1674,10 +1690,9 @@ pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []con
return name;
}
var it = mem.tokenizeScalar(u8, PATH, fs.path.delimiter);
- while (it.next()) |path| {
+ while (it.next()) |p| {
const full_path = self.pathJoin(&.{
- path,
- self.fmt("{s}{s}", .{ name, exe_extension }),
+ p, self.fmt("{s}{s}", .{ name, exe_extension }),
});
return fs.realpathAlloc(self.allocator, full_path) catch continue;
}
@@ -1687,10 +1702,9 @@ pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []con
if (fs.path.isAbsolute(name)) {
return name;
}
- for (paths) |path| {
+ for (paths) |p| {
const full_path = self.pathJoin(&.{
- path,
- self.fmt("{s}{s}", .{ name, exe_extension }),
+ p, self.fmt("{s}{s}", .{ name, exe_extension }),
});
return fs.realpathAlloc(self.allocator, full_path) catch continue;
}
@@ -1771,7 +1785,7 @@ pub fn getInstallPath(self: *Build, dir: InstallDir, dest_rel_path: []const u8)
.bin => self.exe_dir,
.lib => self.lib_dir,
.header => self.h_dir,
- .custom => |path| self.pathJoin(&.{ self.install_path, path }),
+ .custom => |p| self.pathJoin(&.{ self.install_path, p }),
};
return fs.path.resolve(
self.allocator,
@@ -2032,7 +2046,7 @@ fn dependencyInner(
const build_root: std.Build.Cache.Directory = .{
.path = build_root_string,
- .handle = std.fs.cwd().openDir(build_root_string, .{}) catch |err| {
+ .handle = fs.cwd().openDir(build_root_string, .{}) catch |err| {
std.debug.print("unable to open '{s}': {s}\n", .{
build_root_string, @errorName(err),
});
@@ -2093,9 +2107,9 @@ pub const GeneratedFile = struct {
// so that we can join it with another path (e.g. build root, cache root, etc.)
//
// dirname("") should still be null, because we can't go up any further.
-fn dirnameAllowEmpty(path: []const u8) ?[]const u8 {
- return fs.path.dirname(path) orelse {
- if (fs.path.isAbsolute(path) or path.len == 0) return null;
+fn dirnameAllowEmpty(full_path: []const u8) ?[]const u8 {
+ return fs.path.dirname(full_path) orelse {
+ if (fs.path.isAbsolute(full_path) or full_path.len == 0) return null;
return "";
};
@@ -2117,11 +2131,15 @@ test dirnameAllowEmpty {
/// A reference to an existing or future path.
pub const LazyPath = union(enum) {
- /// A source file path relative to build root.
- /// This should not be an absolute path, but in an older iteration of the zig build
- /// system API, it was allowed to be absolute. Absolute paths should use `cwd_relative`.
+ /// Deprecated; use the `path` function instead.
path: []const u8,
+ /// A source file path relative to build root.
+ src_path: struct {
+ owner: *std.Build,
+ sub_path: []const u8,
+ },
+
/// A file that is generated by an interface. Those files usually are
/// not available until built by a build step.
generated: *const GeneratedFile,
@@ -2150,11 +2168,10 @@ pub const LazyPath = union(enum) {
sub_path: []const u8,
},
- /// Returns a new file source that will have a relative path to the build root guaranteed.
- /// Asserts the parameter is not an absolute path.
- pub fn relative(path: []const u8) LazyPath {
- std.debug.assert(!std.fs.path.isAbsolute(path));
- return LazyPath{ .path = path };
+ /// Deprecated. Call `path` instead.
+ pub fn relative(p: []const u8) LazyPath {
+ std.log.warn("deprecated. call std.Build.path instead", .{});
+ return .{ .path = p };
}
/// Returns a lazy path referring to the directory containing this path.
@@ -2168,13 +2185,16 @@ pub const LazyPath = union(enum) {
return switch (self) {
.generated => |gen| .{ .generated_dirname = .{ .generated = gen, .up = 0 } },
.generated_dirname => |gen| .{ .generated_dirname = .{ .generated = gen.generated, .up = gen.up + 1 } },
+ .src_path => |sp| .{ .src_path = .{
+ .owner = sp.owner,
+ .sub_path = dirnameAllowEmpty(sp.sub_path) orelse {
+ dumpBadDirnameHelp(null, null, "dirname() attempted to traverse outside the build root\n", .{}) catch {};
+ @panic("misconfigured build script");
+ },
+ } },
.path => |p| .{
.path = dirnameAllowEmpty(p) orelse {
- dumpBadDirnameHelp(null, null,
- \\dirname() attempted to traverse outside the build root.
- \\This is not allowed.
- \\
- , .{}) catch {};
+ dumpBadDirnameHelp(null, null, "dirname() attempted to traverse outside the build root\n", .{}) catch {};
@panic("misconfigured build script");
},
},
@@ -2195,7 +2215,6 @@ pub const LazyPath = union(enum) {
} else {
dumpBadDirnameHelp(null, null,
\\dirname() attempted to traverse outside the current working directory.
- \\This is not allowed.
\\
, .{}) catch {};
@panic("misconfigured build script");
@@ -2207,7 +2226,6 @@ pub const LazyPath = union(enum) {
.sub_path = dirnameAllowEmpty(dep.sub_path) orelse {
dumpBadDirnameHelp(null, null,
\\dirname() attempted to traverse outside the dependency root.
- \\This is not allowed.
\\
, .{}) catch {};
@panic("misconfigured build script");
@@ -2220,7 +2238,8 @@ pub const LazyPath = union(enum) {
/// Either returns the path or `"generated"`.
pub fn getDisplayName(self: LazyPath) []const u8 {
return switch (self) {
- .path, .cwd_relative => self.path,
+ .src_path => |sp| sp.sub_path,
+ .path, .cwd_relative => |p| p,
.generated => "generated",
.generated_dirname => "generated",
.dependency => "dependency",
@@ -2230,7 +2249,7 @@ pub const LazyPath = union(enum) {
/// Adds dependencies this file source implies to the given step.
pub fn addStepDependencies(self: LazyPath, other_step: *Step) void {
switch (self) {
- .path, .cwd_relative, .dependency => {},
+ .src_path, .path, .cwd_relative, .dependency => {},
.generated => |gen| other_step.dependOn(gen.step),
.generated_dirname => |gen| other_step.dependOn(gen.generated.step),
}
@@ -2250,6 +2269,7 @@ pub const LazyPath = union(enum) {
pub fn getPath2(self: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 {
switch (self) {
.path => |p| return src_builder.pathFromRoot(p),
+ .src_path => |sp| return sp.owner.pathFromRoot(sp.sub_path),
.cwd_relative => |p| return src_builder.pathFromCwd(p),
.generated => |gen| return gen.path orelse {
std.debug.getStderrMutex().lock();
@@ -2262,13 +2282,13 @@ pub const LazyPath = union(enum) {
(src_builder.cache_root.join(src_builder.allocator, &.{"."}) catch @panic("OOM"));
const gen_step = gen.generated.step;
- var path = getPath2(LazyPath{ .generated = gen.generated }, src_builder, asking_step);
+ var p = getPath2(LazyPath{ .generated = gen.generated }, src_builder, asking_step);
var i: usize = 0;
while (i <= gen.up) : (i += 1) {
// path is absolute.
// dirname will return null only if we're at root.
// Typically, we'll stop well before that at the cache root.
- path = fs.path.dirname(path) orelse {
+ p = fs.path.dirname(p) orelse {
dumpBadDirnameHelp(gen_step, asking_step,
\\dirname() reached root.
\\No more directories left to go up.
@@ -2277,7 +2297,7 @@ pub const LazyPath = union(enum) {
@panic("misconfigured build script");
};
- if (mem.eql(u8, path, cache_root_path) and i < gen.up) {
+ if (mem.eql(u8, p, cache_root_path) and i < gen.up) {
// If we hit the cache root and there's still more to go,
// the script attempted to go too far.
dumpBadDirnameHelp(gen_step, asking_step,
@@ -2288,7 +2308,7 @@ pub const LazyPath = union(enum) {
@panic("misconfigured build script");
}
}
- return path;
+ return p;
},
.dependency => |dep| {
return dep.dependency.builder.pathJoin(&[_][]const u8{
@@ -2299,9 +2319,16 @@ pub const LazyPath = union(enum) {
}
}
- /// Duplicates the file source for a given builder.
+ /// Copies the internal strings.
+ ///
+ /// The `b` parameter is only used for its allocator. All *Build instances
+ /// share the same allocator.
pub fn dupe(self: LazyPath, b: *Build) LazyPath {
return switch (self) {
+ .src_path => |sp| .{ .src_path = .{
+ .owner = sp.owner,
+ .sub_path = sp.owner.dupePath(sp.sub_path),
+ } },
.path => |p| .{ .path = b.dupePath(p) },
.cwd_relative => |p| .{ .cwd_relative = b.dupePath(p) },
.generated => |gen| .{ .generated = gen },
diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig
index 02386de430..d19f0a781e 100644
--- a/lib/std/Build/Module.zig
+++ b/lib/std/Build/Module.zig
@@ -451,7 +451,7 @@ pub fn linkFramework(m: *Module, name: []const u8, options: LinkFrameworkOptions
pub const AddCSourceFilesOptions = struct {
/// When provided, `files` are relative to `root` rather than the
/// package that owns the `Compile` step.
- root: LazyPath = .{ .path = "" },
+ root: ?LazyPath = null,
files: []const []const u8,
flags: []const []const u8 = &.{},
};
@@ -472,7 +472,7 @@ pub fn addCSourceFiles(m: *Module, options: AddCSourceFilesOptions) void {
const c_source_files = allocator.create(CSourceFiles) catch @panic("OOM");
c_source_files.* = .{
- .root = options.root,
+ .root = options.root orelse b.path(""),
.files = b.dupeStrings(options.files),
.flags = b.dupeStrings(options.flags),
};
@@ -573,17 +573,6 @@ pub fn addLibraryPath(m: *Module, directory_path: LazyPath) void {
pub fn addRPath(m: *Module, directory_path: LazyPath) void {
const b = m.owner;
- switch (directory_path) {
- .path, .cwd_relative => |path| {
- // TODO: remove this check after people upgrade and stop expecting it to work
- if (std.mem.startsWith(u8, path, "@executable_path") or
- std.mem.startsWith(u8, path, "@loader_path"))
- {
- @panic("this function is for adding directory paths. It does not support special rpaths. use addRPathSpecial for that.");
- }
- },
- else => {},
- }
m.rpaths.append(b.allocator, .{ .lazy_path = directory_path.dupe(b) }) catch @panic("OOM");
addLazyPathDependenciesOnly(m, directory_path);
}
diff --git a/lib/std/Build/Step/CheckObject.zig b/lib/std/Build/Step/CheckObject.zig
index c39a487649..f8f0fcd584 100644
--- a/lib/std/Build/Step/CheckObject.zig
+++ b/lib/std/Build/Step/CheckObject.zig
@@ -247,15 +247,27 @@ const ComputeCompareExpected = struct {
const Check = struct {
kind: Kind,
+ payload: Payload,
+ data: std.ArrayList(u8),
actions: std.ArrayList(Action),
fn create(allocator: Allocator, kind: Kind) Check {
return .{
.kind = kind,
+ .payload = .{ .none = {} },
+ .data = std.ArrayList(u8).init(allocator),
.actions = std.ArrayList(Action).init(allocator),
};
}
+ fn dumpSection(allocator: Allocator, name: [:0]const u8) Check {
+ var check = Check.create(allocator, .dump_section);
+ const off: u32 = @intCast(check.data.items.len);
+ check.data.writer().print("{s}\x00", .{name}) catch @panic("OOM");
+ check.payload = .{ .dump_section = off };
+ return check;
+ }
+
fn extract(self: *Check, phrase: SearchPhrase) void {
self.actions.append(.{
.tag = .extract,
@@ -305,6 +317,13 @@ const Check = struct {
dyld_lazy_bind,
exports,
compute_compare,
+ dump_section,
+ };
+
+ const Payload = union {
+ none: void,
+ /// Null-delimited string in the 'data' buffer.
+ dump_section: u32,
};
};
@@ -513,6 +532,11 @@ pub fn checkInArchiveSymtab(self: *CheckObject) void {
self.checkExact(label);
}
+pub fn dumpSection(self: *CheckObject, name: [:0]const u8) void {
+ const new_check = Check.dumpSection(self.step.owner.allocator, name);
+ self.checks.append(new_check) catch @panic("OOM");
+}
+
/// Creates a new standalone, singular check which allows running simple binary operations
/// on the extracted variables. It will then compare the reduced program with the value of
/// the expected variable.
@@ -564,13 +588,44 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
}
const output = switch (self.obj_format) {
- .macho => try MachODumper.parseAndDump(step, chk.kind, contents),
- .elf => try ElfDumper.parseAndDump(step, chk.kind, contents),
+ .macho => try MachODumper.parseAndDump(step, chk, contents),
+ .elf => try ElfDumper.parseAndDump(step, chk, contents),
.coff => return step.fail("TODO coff parser", .{}),
- .wasm => try WasmDumper.parseAndDump(step, chk.kind, contents),
+ .wasm => try WasmDumper.parseAndDump(step, chk, contents),
else => unreachable,
};
+ // Depending on whether we requested dumping section verbatim or not,
+ // we either format message string with escaped codes, or not to aid debugging
+ // the failed test.
+ const fmtMessageString = struct {
+ fn fmtMessageString(kind: Check.Kind, msg: []const u8) std.fmt.Formatter(formatMessageString) {
+ return .{ .data = .{
+ .kind = kind,
+ .msg = msg,
+ } };
+ }
+
+ const Ctx = struct {
+ kind: Check.Kind,
+ msg: []const u8,
+ };
+
+ fn formatMessageString(
+ ctx: Ctx,
+ comptime unused_fmt_string: []const u8,
+ options: std.fmt.FormatOptions,
+ writer: anytype,
+ ) !void {
+ _ = unused_fmt_string;
+ _ = options;
+ switch (ctx.kind) {
+ .dump_section => try writer.print("{s}", .{std.fmt.fmtSliceEscapeLower(ctx.msg)}),
+ else => try writer.writeAll(ctx.msg),
+ }
+ }
+ }.fmtMessageString;
+
var it = mem.tokenizeAny(u8, output, "\r\n");
for (chk.actions.items) |act| {
switch (act.tag) {
@@ -585,7 +640,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
\\========= but parsed file does not contain it: =======
\\{s}
\\======================================================
- , .{ act.phrase.resolve(b, step), output });
+ , .{ fmtMessageString(chk.kind, act.phrase.resolve(b, step)), fmtMessageString(chk.kind, output) });
}
},
@@ -600,7 +655,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
\\========= but parsed file does not contain it: =======
\\{s}
\\======================================================
- , .{ act.phrase.resolve(b, step), output });
+ , .{ fmtMessageString(chk.kind, act.phrase.resolve(b, step)), fmtMessageString(chk.kind, output) });
}
},
@@ -614,7 +669,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
\\========= but parsed file does contain it: ========
\\{s}
\\===================================================
- , .{ act.phrase.resolve(b, step), output });
+ , .{ fmtMessageString(chk.kind, act.phrase.resolve(b, step)), fmtMessageString(chk.kind, output) });
}
},
@@ -629,7 +684,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
\\========= but parsed file does not contain it: =======
\\{s}
\\======================================================
- , .{ act.phrase.resolve(b, step), output });
+ , .{ act.phrase.resolve(b, step), fmtMessageString(chk.kind, output) });
}
},
@@ -660,7 +715,7 @@ const MachODumper = struct {
}
};
- fn parseAndDump(step: *Step, kind: Check.Kind, bytes: []const u8) ![]const u8 {
+ fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
const gpa = step.owner.allocator;
var stream = std.io.fixedBufferStream(bytes);
const reader = stream.reader();
@@ -731,7 +786,7 @@ const MachODumper = struct {
}
}
- switch (kind) {
+ switch (check.kind) {
.headers => {
try dumpHeader(hdr, writer);
@@ -764,7 +819,7 @@ const MachODumper = struct {
if (dyld_info_lc == null) return step.fail("no dyld info found", .{});
const lc = dyld_info_lc.?;
- switch (kind) {
+ switch (check.kind) {
.dyld_rebase => if (lc.rebase_size > 0) {
const data = bytes[lc.rebase_off..][0..lc.rebase_size];
try writer.writeAll(dyld_rebase_label ++ "\n");
@@ -805,7 +860,7 @@ const MachODumper = struct {
return step.fail("no exports data found", .{});
},
- else => return step.fail("invalid check kind for MachO file format: {s}", .{@tagName(kind)}),
+ else => return step.fail("invalid check kind for MachO file format: {s}", .{@tagName(check.kind)}),
}
return output.toOwnedSlice();
@@ -1633,14 +1688,14 @@ const ElfDumper = struct {
const dynamic_section_label = "dynamic section";
const archive_symtab_label = "archive symbol table";
- fn parseAndDump(step: *Step, kind: Check.Kind, bytes: []const u8) ![]const u8 {
- return parseAndDumpArchive(step, kind, bytes) catch |err| switch (err) {
- error.InvalidArchiveMagicNumber => try parseAndDumpObject(step, kind, bytes),
+ fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
+ return parseAndDumpArchive(step, check, bytes) catch |err| switch (err) {
+ error.InvalidArchiveMagicNumber => try parseAndDumpObject(step, check, bytes),
else => |e| return e,
};
}
- fn parseAndDumpArchive(step: *Step, kind: Check.Kind, bytes: []const u8) ![]const u8 {
+ fn parseAndDumpArchive(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
const gpa = step.owner.allocator;
var stream = std.io.fixedBufferStream(bytes);
const reader = stream.reader();
@@ -1702,13 +1757,13 @@ const ElfDumper = struct {
var output = std.ArrayList(u8).init(gpa);
const writer = output.writer();
- switch (kind) {
+ switch (check.kind) {
.archive_symtab => if (ctx.symtab.items.len > 0) {
try ctx.dumpSymtab(writer);
} else return step.fail("no archive symbol table found", .{}),
else => if (ctx.objects.items.len > 0) {
- try ctx.dumpObjects(step, kind, writer);
+ try ctx.dumpObjects(step, check, writer);
} else return step.fail("empty archive", .{}),
}
@@ -1785,10 +1840,10 @@ const ElfDumper = struct {
}
}
- fn dumpObjects(ctx: ArchiveContext, step: *Step, kind: Check.Kind, writer: anytype) !void {
+ fn dumpObjects(ctx: ArchiveContext, step: *Step, check: Check, writer: anytype) !void {
for (ctx.objects.items) |object| {
try writer.print("object {s}\n", .{object.name});
- const output = try parseAndDumpObject(step, kind, ctx.data[object.off..][0..object.len]);
+ const output = try parseAndDumpObject(step, check, ctx.data[object.off..][0..object.len]);
defer ctx.gpa.free(output);
try writer.print("{s}\n", .{output});
}
@@ -1806,7 +1861,7 @@ const ElfDumper = struct {
};
};
- fn parseAndDumpObject(step: *Step, kind: Check.Kind, bytes: []const u8) ![]const u8 {
+ fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
const gpa = step.owner.allocator;
var stream = std.io.fixedBufferStream(bytes);
const reader = stream.reader();
@@ -1859,7 +1914,7 @@ const ElfDumper = struct {
var output = std.ArrayList(u8).init(gpa);
const writer = output.writer();
- switch (kind) {
+ switch (check.kind) {
.headers => {
try ctx.dumpHeader(writer);
try ctx.dumpShdrs(writer);
@@ -1878,7 +1933,13 @@ const ElfDumper = struct {
try ctx.dumpDynamicSection(shndx, writer);
} else return step.fail("no .dynamic section found", .{}),
- else => return step.fail("invalid check kind for ELF file format: {s}", .{@tagName(kind)}),
+ .dump_section => {
+ const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(check.data.items.ptr + check.payload.dump_section)), 0);
+ const shndx = ctx.getSectionByName(name) orelse return step.fail("no '{s}' section found", .{name});
+ try ctx.dumpSection(shndx, writer);
+ },
+
+ else => return step.fail("invalid check kind for ELF file format: {s}", .{@tagName(check.kind)}),
}
return output.toOwnedSlice();
@@ -2176,6 +2237,11 @@ const ElfDumper = struct {
}
}
+ fn dumpSection(ctx: ObjectContext, shndx: usize, writer: anytype) !void {
+ const data = ctx.getSectionContents(shndx);
+ try writer.print("{s}", .{data});
+ }
+
inline fn getSectionName(ctx: ObjectContext, shndx: usize) []const u8 {
const shdr = ctx.shdrs[shndx];
return getString(ctx.shstrtab, shdr.sh_name);
@@ -2300,7 +2366,7 @@ const ElfDumper = struct {
const WasmDumper = struct {
const symtab_label = "symbols";
- fn parseAndDump(step: *Step, kind: Check.Kind, bytes: []const u8) ![]const u8 {
+ fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
const gpa = step.owner.allocator;
var fbs = std.io.fixedBufferStream(bytes);
const reader = fbs.reader();
@@ -2317,7 +2383,7 @@ const WasmDumper = struct {
errdefer output.deinit();
const writer = output.writer();
- switch (kind) {
+ switch (check.kind) {
.headers => {
while (reader.readByte()) |current_byte| {
const section = std.meta.intToEnum(std.wasm.Section, current_byte) catch {
@@ -2330,7 +2396,7 @@ const WasmDumper = struct {
} else |_| {} // reached end of stream
},
- else => return step.fail("invalid check kind for Wasm file format: {s}", .{@tagName(kind)}),
+ else => return step.fail("invalid check kind for Wasm file format: {s}", .{@tagName(check.kind)}),
}
return output.toOwnedSlice();
@@ -2364,7 +2430,7 @@ const WasmDumper = struct {
=> {
const entries = try std.leb.readULEB128(u32, reader);
try writer.print("\nentries {d}\n", .{entries});
- try dumpSection(step, section, data[fbs.pos..], entries, writer);
+ try parseSection(step, section, data[fbs.pos..], entries, writer);
},
.custom => {
const name_length = try std.leb.readULEB128(u32, reader);
@@ -2393,7 +2459,7 @@ const WasmDumper = struct {
}
}
- fn dumpSection(step: *Step, section: std.wasm.Section, data: []const u8, entries: u32, writer: anytype) !void {
+ fn parseSection(step: *Step, section: std.wasm.Section, data: []const u8, entries: u32, writer: anytype) !void {
var fbs = std.io.fixedBufferStream(data);
const reader = fbs.reader();
diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig
index 4a5364176a..c36fd8c4ca 100644
--- a/lib/std/Build/Step/Compile.zig
+++ b/lib/std/Build/Step/Compile.zig
@@ -55,7 +55,7 @@ global_base: ?u64 = null,
zig_lib_dir: ?LazyPath,
exec_cmd_args: ?[]const ?[]const u8,
filters: []const []const u8,
-test_runner: ?[]const u8,
+test_runner: ?LazyPath,
test_server_mode: bool,
wasi_exec_model: ?std.builtin.WasiExecModel = null,
@@ -236,7 +236,7 @@ pub const Options = struct {
version: ?std.SemanticVersion = null,
max_rss: usize = 0,
filters: []const []const u8 = &.{},
- test_runner: ?[]const u8 = null,
+ test_runner: ?LazyPath = null,
use_llvm: ?bool = null,
use_lld: ?bool = null,
zig_lib_dir: ?LazyPath = null,
@@ -264,20 +264,8 @@ pub const HeaderInstallation = union(enum) {
dest_rel_path: []const u8,
pub fn dupe(self: File, b: *std.Build) File {
- // 'path' lazy paths are relative to the build root of some step, inferred from the step
- // in which they are used. This means that we can't dupe such paths, because they may
- // come from dependencies with their own build roots and duping the paths as is might
- // cause the build script to search for the file relative to the wrong root.
- // As a temporary workaround, we convert build root-relative paths to absolute paths.
- // If/when the build-root relative paths are updated to encode which build root they are
- // relative to, this workaround should be removed.
- const duped_source: LazyPath = switch (self.source) {
- .path => |root_rel| .{ .cwd_relative = b.pathFromRoot(root_rel) },
- else => self.source.dupe(b),
- };
-
return .{
- .source = duped_source,
+ .source = self.source.dupe(b),
.dest_rel_path = b.dupePath(self.dest_rel_path),
};
}
@@ -305,20 +293,8 @@ pub const HeaderInstallation = union(enum) {
};
pub fn dupe(self: Directory, b: *std.Build) Directory {
- // 'path' lazy paths are relative to the build root of some step, inferred from the step
- // in which they are used. This means that we can't dupe such paths, because they may
- // come from dependencies with their own build roots and duping the paths as is might
- // cause the build script to search for the file relative to the wrong root.
- // As a temporary workaround, we convert build root-relative paths to absolute paths.
- // If/when the build-root relative paths are updated to encode which build root they are
- // relative to, this workaround should be removed.
- const duped_source: LazyPath = switch (self.source) {
- .path => |root_rel| .{ .cwd_relative = b.pathFromRoot(root_rel) },
- else => self.source.dupe(b),
- };
-
return .{
- .source = duped_source,
+ .source = self.source.dupe(b),
.dest_rel_path = b.dupePath(self.dest_rel_path),
.options = self.options.dupe(b),
};
@@ -402,7 +378,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
.zig_lib_dir = null,
.exec_cmd_args = null,
.filters = options.filters,
- .test_runner = options.test_runner,
+ .test_runner = null,
.test_server_mode = options.test_runner == null,
.rdynamic = false,
.installed_path = null,
@@ -429,6 +405,11 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
lp.addStepDependencies(&self.step);
}
+ if (options.test_runner) |lp| {
+ self.test_runner = lp.dupe(self.step.owner);
+ lp.addStepDependencies(&self.step);
+ }
+
// Only the PE/COFF format has a Resource Table which is where the manifest
// gets embedded, so for any other target the manifest file is just ignored.
if (target.ofmt == .coff) {
@@ -1402,7 +1383,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
if (self.test_runner) |test_runner| {
try zig_args.append("--test-runner");
- try zig_args.append(b.pathFromRoot(test_runner));
+ try zig_args.append(test_runner.getPath(b));
}
for (b.debug_log_scopes) |log_scope| {
diff --git a/lib/std/Build/Step/ConfigHeader.zig b/lib/std/Build/Step/ConfigHeader.zig
index 46631cac24..e547f8082e 100644
--- a/lib/std/Build/Step/ConfigHeader.zig
+++ b/lib/std/Build/Step/ConfigHeader.zig
@@ -58,6 +58,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
if (options.style.getPath()) |s| default_include_path: {
const sub_path = switch (s) {
+ .src_path => |sp| sp.sub_path,
.path => |path| path,
.generated, .generated_dirname => break :default_include_path,
.cwd_relative => |sub_path| sub_path,
@@ -192,13 +193,21 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
.autoconf => |file_source| {
try output.appendSlice(c_generated_line);
const src_path = file_source.getPath(b);
- const contents = try std.fs.cwd().readFileAlloc(arena, src_path, self.max_bytes);
+ const contents = std.fs.cwd().readFileAlloc(arena, src_path, self.max_bytes) catch |err| {
+ return step.fail("unable to read autoconf input file '{s}': {s}", .{
+ src_path, @errorName(err),
+ });
+ };
try render_autoconf(step, contents, &output, self.values, src_path);
},
.cmake => |file_source| {
try output.appendSlice(c_generated_line);
const src_path = file_source.getPath(b);
- const contents = try std.fs.cwd().readFileAlloc(arena, src_path, self.max_bytes);
+ const contents = std.fs.cwd().readFileAlloc(arena, src_path, self.max_bytes) catch |err| {
+ return step.fail("unable to read cmake input file '{s}': {s}", .{
+ src_path, @errorName(err),
+ });
+ };
try render_cmake(step, contents, &output, self.values, src_path);
},
.blank => {
diff --git a/lib/std/Target.zig b/lib/std/Target.zig
index 842442e37b..55cde46308 100644
--- a/lib/std/Target.zig
+++ b/lib/std/Target.zig
@@ -2740,6 +2740,13 @@ pub fn is_libc_lib_name(target: std.Target, name: []const u8) bool {
return true;
}
+ if (target.os.tag == .haiku) {
+ if (eqlIgnoreCase(ignore_case, name, "root"))
+ return true;
+ if (eqlIgnoreCase(ignore_case, name, "network"))
+ return true;
+ }
+
return false;
}
diff --git a/lib/std/Uri.zig b/lib/std/Uri.zig
index cbd3d42741..ee0c602125 100644
--- a/lib/std/Uri.zig
+++ b/lib/std/Uri.zig
@@ -1,156 +1,157 @@
//! Uniform Resource Identifier (URI) parsing roughly adhering to <https://tools.ietf.org/html/rfc3986>.
//! Does not do perfect grammar and character class checking, but should be robust against URIs in the wild.
-const Uri = @This();
-const std = @import("std.zig");
-const testing = std.testing;
-const Allocator = std.mem.Allocator;
-
scheme: []const u8,
-user: ?[]const u8 = null,
-password: ?[]const u8 = null,
-host: ?[]const u8 = null,
+user: ?Component = null,
+password: ?Component = null,
+host: ?Component = null,
port: ?u16 = null,
-path: []const u8,
-query: ?[]const u8 = null,
-fragment: ?[]const u8 = null,
-
-/// Applies URI encoding and replaces all reserved characters with their respective %XX code.
-pub fn escapeString(allocator: Allocator, input: []const u8) error{OutOfMemory}![]u8 {
- return escapeStringWithFn(allocator, input, isUnreserved);
-}
-
-pub fn escapePath(allocator: Allocator, input: []const u8) error{OutOfMemory}![]u8 {
- return escapeStringWithFn(allocator, input, isPathChar);
-}
-
-pub fn escapeQuery(allocator: Allocator, input: []const u8) error{OutOfMemory}![]u8 {
- return escapeStringWithFn(allocator, input, isQueryChar);
-}
-
-pub fn writeEscapedString(writer: anytype, input: []const u8) !void {
- return writeEscapedStringWithFn(writer, input, isUnreserved);
-}
-
-pub fn writeEscapedPath(writer: anytype, input: []const u8) !void {
- return writeEscapedStringWithFn(writer, input, isPathChar);
-}
-
-pub fn writeEscapedQuery(writer: anytype, input: []const u8) !void {
- return writeEscapedStringWithFn(writer, input, isQueryChar);
-}
-
-pub fn escapeStringWithFn(allocator: Allocator, input: []const u8, comptime keepUnescaped: fn (c: u8) bool) Allocator.Error![]u8 {
- var outsize: usize = 0;
- for (input) |c| {
- outsize += if (keepUnescaped(c)) @as(usize, 1) else 3;
+path: Component = Component.empty,
+query: ?Component = null,
+fragment: ?Component = null,
+
+pub const Component = union(enum) {
+ /// Invalid characters in this component must be percent encoded
+ /// before being printed as part of a URI.
+ raw: []const u8,
+ /// This component is already percent-encoded, it can be printed
+ /// directly as part of a URI.
+ percent_encoded: []const u8,
+
+ pub const empty: Component = .{ .percent_encoded = "" };
+
+ pub fn isEmpty(component: Component) bool {
+ return switch (component) {
+ .raw, .percent_encoded => |string| string.len == 0,
+ };
}
- var output = try allocator.alloc(u8, outsize);
- var outptr: usize = 0;
- for (input) |c| {
- if (keepUnescaped(c)) {
- output[outptr] = c;
- outptr += 1;
- } else {
- var buf: [2]u8 = undefined;
- _ = std.fmt.bufPrint(&buf, "{X:0>2}", .{c}) catch unreachable;
-
- output[outptr + 0] = '%';
- output[outptr + 1] = buf[0];
- output[outptr + 2] = buf[1];
- outptr += 3;
- }
+ /// Allocates the result with `arena` only if needed, so the result should not be freed.
+ pub fn toRawMaybeAlloc(
+ component: Component,
+ arena: std.mem.Allocator,
+ ) std.mem.Allocator.Error![]const u8 {
+ return switch (component) {
+ .raw => |raw| raw,
+ .percent_encoded => |percent_encoded| if (std.mem.indexOfScalar(u8, percent_encoded, '%')) |_|
+ try std.fmt.allocPrint(arena, "{raw}", .{component})
+ else
+ percent_encoded,
+ };
}
- return output;
-}
-pub fn writeEscapedStringWithFn(writer: anytype, input: []const u8, comptime keepUnescaped: fn (c: u8) bool) @TypeOf(writer).Error!void {
- for (input) |c| {
- if (keepUnescaped(c)) {
- try writer.writeByte(c);
- } else {
- try writer.print("%{X:0>2}", .{c});
- }
+ pub fn format(
+ component: Component,
+ comptime fmt_str: []const u8,
+ _: std.fmt.FormatOptions,
+ writer: anytype,
+ ) @TypeOf(writer).Error!void {
+ if (fmt_str.len == 0) {
+ try writer.print("std.Uri.Component{{ .{s} = \"{}\" }}", .{
+ @tagName(component),
+ std.zig.fmtEscapes(switch (component) {
+ .raw, .percent_encoded => |string| string,
+ }),
+ });
+ } else if (comptime std.mem.eql(u8, fmt_str, "raw")) switch (component) {
+ .raw => |raw| try writer.writeAll(raw),
+ .percent_encoded => |percent_encoded| {
+ var start: usize = 0;
+ var index: usize = 0;
+ while (std.mem.indexOfScalarPos(u8, percent_encoded, index, '%')) |percent| {
+ index = percent + 1;
+ if (percent_encoded.len - index < 2) continue;
+ const percent_encoded_char =
+ std.fmt.parseInt(u8, percent_encoded[index..][0..2], 16) catch continue;
+ try writer.print("{s}{c}", .{
+ percent_encoded[start..percent],
+ percent_encoded_char,
+ });
+ start = percent + 3;
+ index = percent + 3;
+ }
+ try writer.writeAll(percent_encoded[start..]);
+ },
+ } else if (comptime std.mem.eql(u8, fmt_str, "%")) switch (component) {
+ .raw => |raw| try percentEncode(writer, raw, isUnreserved),
+ .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
+ } else if (comptime std.mem.eql(u8, fmt_str, "user")) switch (component) {
+ .raw => |raw| try percentEncode(writer, raw, isUserChar),
+ .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
+ } else if (comptime std.mem.eql(u8, fmt_str, "password")) switch (component) {
+ .raw => |raw| try percentEncode(writer, raw, isPasswordChar),
+ .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
+ } else if (comptime std.mem.eql(u8, fmt_str, "host")) switch (component) {
+ .raw => |raw| try percentEncode(writer, raw, isHostChar),
+ .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
+ } else if (comptime std.mem.eql(u8, fmt_str, "path")) switch (component) {
+ .raw => |raw| try percentEncode(writer, raw, isPathChar),
+ .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
+ } else if (comptime std.mem.eql(u8, fmt_str, "query")) switch (component) {
+ .raw => |raw| try percentEncode(writer, raw, isQueryChar),
+ .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
+ } else if (comptime std.mem.eql(u8, fmt_str, "fragment")) switch (component) {
+ .raw => |raw| try percentEncode(writer, raw, isFragmentChar),
+ .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded),
+ } else @compileError("invalid format string '" ++ fmt_str ++ "'");
}
-}
-/// Parses a URI string and unescapes all %XX where XX is a valid hex number. Otherwise, verbatim copies
-/// them to the output.
-pub fn unescapeString(allocator: Allocator, input: []const u8) error{OutOfMemory}![]u8 {
- var outsize: usize = 0;
- var inptr: usize = 0;
- while (inptr < input.len) {
- if (input[inptr] == '%') {
- inptr += 1;
- if (inptr + 2 <= input.len) {
- _ = std.fmt.parseInt(u8, input[inptr..][0..2], 16) catch {
- outsize += 3;
- inptr += 2;
- continue;
- };
- inptr += 2;
- outsize += 1;
- } else {
- outsize += 1;
- }
- } else {
- inptr += 1;
- outsize += 1;
+ pub fn percentEncode(
+ writer: anytype,
+ raw: []const u8,
+ comptime isValidChar: fn (u8) bool,
+ ) @TypeOf(writer).Error!void {
+ var start: usize = 0;
+ for (raw, 0..) |char, index| {
+ if (isValidChar(char)) continue;
+ try writer.print("{s}%{X:0>2}", .{ raw[start..index], char });
+ start = index + 1;
}
+ try writer.writeAll(raw[start..]);
}
+};
- var output = try allocator.alloc(u8, outsize);
- var outptr: usize = 0;
- inptr = 0;
- while (inptr < input.len) {
- if (input[inptr] == '%') {
- inptr += 1;
- if (inptr + 2 <= input.len) {
- const value = std.fmt.parseInt(u8, input[inptr..][0..2], 16) catch {
- output[outptr + 0] = input[inptr + 0];
- output[outptr + 1] = input[inptr + 1];
- inptr += 2;
- outptr += 2;
+/// Percent decodes all %XX where XX is a valid hex number.
+/// `output` may alias `input` if `output.ptr <= input.ptr`.
+/// Mutates and returns a subslice of `output`.
+pub fn percentDecodeBackwards(output: []u8, input: []const u8) []u8 {
+ var input_index = input.len;
+ var output_index = output.len;
+ while (input_index > 0) {
+ if (input_index >= 3) {
+ const maybe_percent_encoded = input[input_index - 3 ..][0..3];
+ if (maybe_percent_encoded[0] == '%') {
+ if (std.fmt.parseInt(u8, maybe_percent_encoded[1..], 16)) |percent_encoded_char| {
+ input_index -= maybe_percent_encoded.len;
+ output_index -= 1;
+ output[output_index] = percent_encoded_char;
continue;
- };
-
- output[outptr] = value;
-
- inptr += 2;
- outptr += 1;
- } else {
- output[outptr] = input[inptr - 1];
- outptr += 1;
+ } else |_| {}
}
- } else {
- output[outptr] = input[inptr];
- inptr += 1;
- outptr += 1;
}
+ input_index -= 1;
+ output_index -= 1;
+ output[output_index] = input[input_index];
}
- return output;
+ return output[output_index..];
+}
+
+/// Percent decodes all %XX where XX is a valid hex number.
+/// Mutates and returns a subslice of `buffer`.
+pub fn percentDecodeInPlace(buffer: []u8) []u8 {
+ return percentDecodeBackwards(buffer, buffer);
}
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.
-/// 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 {
+/// The return value will contain strings pointing into the original `text`.
+/// Each component that is provided, will be non-`null`.
+pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri {
var reader = SliceReader{ .slice = text };
- var uri = Uri{
- .scheme = "",
- .user = null,
- .password = null,
- .host = null,
- .port = null,
- .path = "", // path is always set, but empty by default.
- .query = null,
- .fragment = null,
- };
+ var uri: Uri = .{ .scheme = scheme, .path = undefined };
if (reader.peekPrefix("//")) a: { // authority part
std.debug.assert(reader.get().? == '/');
@@ -167,12 +168,12 @@ pub fn parseWithoutScheme(text: []const u8) ParseError!Uri {
const user_info = authority[0..index];
if (std.mem.indexOf(u8, user_info, ":")) |idx| {
- uri.user = user_info[0..idx];
+ uri.user = .{ .percent_encoded = user_info[0..idx] };
if (idx < user_info.len - 1) { // empty password is also "no password"
- uri.password = user_info[idx + 1 ..];
+ uri.password = .{ .percent_encoded = user_info[idx + 1 ..] };
}
} else {
- uri.user = user_info;
+ uri.user = .{ .percent_encoded = user_info };
uri.password = null;
}
}
@@ -205,19 +206,19 @@ pub fn parseWithoutScheme(text: []const u8) ParseError!Uri {
}
if (start_of_host >= end_of_host) return error.InvalidFormat;
- uri.host = authority[start_of_host..end_of_host];
+ uri.host = .{ .percent_encoded = authority[start_of_host..end_of_host] };
}
- uri.path = reader.readUntil(isPathSeparator);
+ uri.path = .{ .percent_encoded = reader.readUntil(isPathSeparator) };
if ((reader.peek() orelse 0) == '?') { // query part
std.debug.assert(reader.get().? == '?');
- uri.query = reader.readUntil(isQuerySeparator);
+ uri.query = .{ .percent_encoded = reader.readUntil(isQuerySeparator) };
}
if ((reader.peek() orelse 0) == '#') { // fragment part
std.debug.assert(reader.get().? == '#');
- uri.fragment = reader.readUntilEof();
+ uri.fragment = .{ .percent_encoded = reader.readUntilEof() };
}
return uri;
@@ -242,8 +243,8 @@ pub const WriteToStreamOptions = struct {
/// When true, include the fragment part of the URI. Ignored when `path` is false.
fragment: bool = false,
- /// When true, do not escape any part of the URI.
- raw: bool = false,
+ /// When true, include the port part of the URI. Ignored when `port` is null.
+ port: bool = true,
};
pub fn writeToStream(
@@ -252,80 +253,53 @@ pub fn writeToStream(
writer: anytype,
) @TypeOf(writer).Error!void {
if (options.scheme) {
- try writer.writeAll(uri.scheme);
- try writer.writeAll(":");
-
+ try writer.print("{s}:", .{uri.scheme});
if (options.authority and uri.host != null) {
try writer.writeAll("//");
}
}
-
if (options.authority) {
if (options.authentication and uri.host != null) {
if (uri.user) |user| {
- try writer.writeAll(user);
+ try writer.print("{user}", .{user});
if (uri.password) |password| {
- try writer.writeAll(":");
- try writer.writeAll(password);
+ try writer.print(":{password}", .{password});
}
- try writer.writeAll("@");
+ try writer.writeByte('@');
}
}
-
if (uri.host) |host| {
- try writer.writeAll(host);
-
- if (uri.port) |port| {
- try writer.writeAll(":");
- try std.fmt.formatInt(port, 10, .lower, .{}, writer);
+ try writer.print("{host}", .{host});
+ if (options.port) {
+ if (uri.port) |port| try writer.print(":{d}", .{port});
}
}
}
-
if (options.path) {
- if (uri.path.len == 0) {
- try writer.writeAll("/");
- } else if (options.raw) {
- try writer.writeAll(uri.path);
- } else {
- try writeEscapedPath(writer, uri.path);
+ try writer.print("{path}", .{
+ if (uri.path.isEmpty()) Uri.Component{ .percent_encoded = "/" } else uri.path,
+ });
+ if (options.query) {
+ if (uri.query) |query| try writer.print("?{query}", .{query});
+ }
+ if (options.fragment) {
+ if (uri.fragment) |fragment| try writer.print("#{fragment}", .{fragment});
}
-
- if (options.query) if (uri.query) |q| {
- try writer.writeAll("?");
- if (options.raw) {
- try writer.writeAll(q);
- } else {
- try writeEscapedQuery(writer, q);
- }
- };
-
- if (options.fragment) if (uri.fragment) |f| {
- try writer.writeAll("#");
- if (options.raw) {
- try writer.writeAll(f);
- } else {
- try writeEscapedQuery(writer, f);
- }
- };
}
}
pub fn format(
uri: Uri,
- comptime fmt: []const u8,
- options: std.fmt.FormatOptions,
+ comptime fmt_str: []const u8,
+ _: std.fmt.FormatOptions,
writer: anytype,
) @TypeOf(writer).Error!void {
- _ = options;
-
- const scheme = comptime std.mem.indexOf(u8, fmt, ";") != null or fmt.len == 0;
- const authentication = comptime std.mem.indexOf(u8, fmt, "@") != null or fmt.len == 0;
- const authority = comptime std.mem.indexOf(u8, fmt, "+") != null or fmt.len == 0;
- const path = comptime std.mem.indexOf(u8, fmt, "/") != null or fmt.len == 0;
- const query = comptime std.mem.indexOf(u8, fmt, "?") != null or fmt.len == 0;
- const fragment = comptime std.mem.indexOf(u8, fmt, "#") != null or fmt.len == 0;
- const raw = comptime std.mem.indexOf(u8, fmt, "r") != null or fmt.len == 0;
+ const scheme = comptime std.mem.indexOfScalar(u8, fmt_str, ';') != null or fmt_str.len == 0;
+ const authentication = comptime std.mem.indexOfScalar(u8, fmt_str, '@') != null or fmt_str.len == 0;
+ const authority = comptime std.mem.indexOfScalar(u8, fmt_str, '+') != null or fmt_str.len == 0;
+ const path = comptime std.mem.indexOfScalar(u8, fmt_str, '/') != null or fmt_str.len == 0;
+ const query = comptime std.mem.indexOfScalar(u8, fmt_str, '?') != null or fmt_str.len == 0;
+ const fragment = comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null or fmt_str.len == 0;
return writeToStream(uri, .{
.scheme = scheme,
@@ -334,12 +308,11 @@ pub fn format(
.path = path,
.query = query,
.fragment = fragment,
- .raw = raw,
}, writer);
}
/// Parses the URI or returns an error.
-/// The return value will contain unescaped strings pointing into the
+/// The return value will contain strings pointing into the
/// original `text`. Each component that is provided, will be non-`null`.
pub fn parse(text: []const u8) ParseError!Uri {
var reader: SliceReader = .{ .slice = text };
@@ -353,42 +326,32 @@ pub fn parse(text: []const u8) ParseError!Uri {
return error.InvalidFormat;
}
- var uri = try parseWithoutScheme(reader.readUntilEof());
- uri.scheme = scheme;
-
- return uri;
+ return parseAfterScheme(scheme, reader.readUntilEof());
}
-pub const ResolveInplaceError = ParseError || error{OutOfMemory};
+pub const ResolveInPlaceError = ParseError || error{NoSpaceLeft};
/// Resolves a URI against a base URI, conforming to RFC 3986, Section 5.
-/// Copies `new` to the beginning of `aux_buf`, allowing the slices to overlap,
+/// Copies `new` to the beginning of `aux_buf.*`, allowing the slices to overlap,
/// then parses `new` as a URI, and then resolves the path in place.
/// If a merge needs to take place, the newly constructed path will be stored
-/// in `aux_buf` just after the copied `new`.
-pub fn resolve_inplace(base: Uri, new: []const u8, aux_buf: []u8) ResolveInplaceError!Uri {
- std.mem.copyForwards(u8, aux_buf, new);
+/// in `aux_buf.*` just after the copied `new`, and `aux_buf.*` will be modified
+/// to only contain the remaining unused space.
+pub fn resolve_inplace(base: Uri, new: []const u8, aux_buf: *[]u8) ResolveInPlaceError!Uri {
+ std.mem.copyForwards(u8, aux_buf.*, new);
// At this point, new is an invalid pointer.
- const new_mut = aux_buf[0..new.len];
-
- const new_parsed, const has_scheme = p: {
- break :p .{
- parse(new_mut) catch |first_err| {
- break :p .{
- parseWithoutScheme(new_mut) catch return first_err,
- false,
- };
- },
- true,
- };
- };
+ const new_mut = aux_buf.*[0..new.len];
+ aux_buf.* = aux_buf.*[new.len..];
+ const new_parsed = parse(new_mut) catch |err|
+ (parseAfterScheme("", new_mut) catch return err);
// As you can see above, `new_mut` is not a const pointer.
- const new_path: []u8 = @constCast(new_parsed.path);
+ const new_path: []u8 = @constCast(new_parsed.path.percent_encoded);
- if (has_scheme) return .{
+ if (new_parsed.scheme.len > 0) return .{
.scheme = new_parsed.scheme,
.user = new_parsed.user,
+ .password = new_parsed.password,
.host = new_parsed.host,
.port = new_parsed.port,
.path = remove_dot_segments(new_path),
@@ -399,6 +362,7 @@ pub fn resolve_inplace(base: Uri, new: []const u8, aux_buf: []u8) ResolveInplace
if (new_parsed.host) |host| return .{
.scheme = base.scheme,
.user = new_parsed.user,
+ .password = new_parsed.password,
.host = host,
.port = new_parsed.port,
.path = remove_dot_segments(new_path),
@@ -406,28 +370,21 @@ pub fn resolve_inplace(base: Uri, new: []const u8, aux_buf: []u8) ResolveInplace
.fragment = new_parsed.fragment,
};
- const path, const query = b: {
- if (new_path.len == 0)
- break :b .{
- base.path,
- new_parsed.query orelse base.query,
- };
-
- if (new_path[0] == '/')
- break :b .{
- remove_dot_segments(new_path),
- new_parsed.query,
- };
-
- break :b .{
- try merge_paths(base.path, new_path, aux_buf[new_mut.len..]),
- new_parsed.query,
- };
+ const path, const query = if (new_path.len == 0) .{
+ base.path,
+ new_parsed.query orelse base.query,
+ } else if (new_path[0] == '/') .{
+ remove_dot_segments(new_path),
+ new_parsed.query,
+ } else .{
+ try merge_paths(base.path, new_path, aux_buf),
+ new_parsed.query,
};
return .{
.scheme = base.scheme,
.user = base.user,
+ .password = base.password,
.host = base.host,
.port = base.port,
.path = path,
@@ -437,7 +394,7 @@ pub fn resolve_inplace(base: Uri, new: []const u8, aux_buf: []u8) ResolveInplace
}
/// In-place implementation of RFC 3986, Section 5.2.4.
-fn remove_dot_segments(path: []u8) []u8 {
+fn remove_dot_segments(path: []u8) Component {
var in_i: usize = 0;
var out_i: usize = 0;
while (in_i < path.len) {
@@ -476,28 +433,28 @@ fn remove_dot_segments(path: []u8) []u8 {
}
}
}
- return path[0..out_i];
+ return .{ .percent_encoded = path[0..out_i] };
}
test remove_dot_segments {
{
var buffer = "/a/b/c/./../../g".*;
- try std.testing.expectEqualStrings("/a/g", remove_dot_segments(&buffer));
+ try std.testing.expectEqualStrings("/a/g", remove_dot_segments(&buffer).percent_encoded);
}
}
/// 5.2.3. Merge Paths
-fn merge_paths(base: []const u8, new: []u8, aux: []u8) error{OutOfMemory}![]u8 {
- if (aux.len < base.len + 1 + new.len) return error.OutOfMemory;
- if (base.len == 0) {
- aux[0] = '/';
- @memcpy(aux[1..][0..new.len], new);
- return remove_dot_segments(aux[0 .. new.len + 1]);
+fn merge_paths(base: Component, new: []u8, aux_buf: *[]u8) error{NoSpaceLeft}!Component {
+ var aux = std.io.fixedBufferStream(aux_buf.*);
+ if (!base.isEmpty()) {
+ try aux.writer().print("{path}", .{base});
+ aux.pos = std.mem.lastIndexOfScalar(u8, aux.getWritten(), '/') orelse
+ return remove_dot_segments(new);
}
- const pos = std.mem.lastIndexOfScalar(u8, base, '/') orelse return remove_dot_segments(new);
- @memcpy(aux[0 .. pos + 1], base[0 .. pos + 1]);
- @memcpy(aux[pos + 1 ..][0..new.len], new);
- return remove_dot_segments(aux[0 .. pos + 1 + new.len]);
+ try aux.writer().print("/{s}", .{new});
+ const merged_path = remove_dot_segments(aux.getWritten());
+ aux_buf.* = aux_buf.*[merged_path.percent_encoded.len..];
+ return merged_path;
}
const SliceReader = struct {
@@ -561,13 +518,6 @@ fn isSchemeChar(c: u8) bool {
};
}
-fn isAuthoritySeparator(c: u8) bool {
- return switch (c) {
- '/', '?', '#' => true,
- else => false,
- };
-}
-
/// reserved = gen-delims / sub-delims
fn isReserved(c: u8) bool {
return isGenLimit(c) or isSubLimit(c);
@@ -598,19 +548,40 @@ fn isUnreserved(c: u8) bool {
};
}
-fn isPathSeparator(c: u8) bool {
- return switch (c) {
- '?', '#' => true,
- else => false,
- };
+fn isUserChar(c: u8) bool {
+ return isUnreserved(c) or isSubLimit(c);
+}
+
+fn isPasswordChar(c: u8) bool {
+ return isUserChar(c) or c == ':';
+}
+
+fn isHostChar(c: u8) bool {
+ return isPasswordChar(c) or c == '[' or c == ']';
}
fn isPathChar(c: u8) bool {
- return isUnreserved(c) or isSubLimit(c) or c == '/' or c == ':' or c == '@';
+ return isUserChar(c) or c == '/' or c == ':' or c == '@';
}
fn isQueryChar(c: u8) bool {
- return isPathChar(c) or c == '?' or c == '%';
+ return isPathChar(c) or c == '?';
+}
+
+const isFragmentChar = isQueryChar;
+
+fn isAuthoritySeparator(c: u8) bool {
+ return switch (c) {
+ '/', '?', '#' => true,
+ else => false,
+ };
+}
+
+fn isPathSeparator(c: u8) bool {
+ return switch (c) {
+ '?', '#' => true,
+ else => false,
+ };
}
fn isQuerySeparator(c: u8) bool {
@@ -623,92 +594,92 @@ fn isQuerySeparator(c: u8) bool {
test "basic" {
const parsed = try parse("https://ziglang.org/download");
try testing.expectEqualStrings("https", parsed.scheme);
- try testing.expectEqualStrings("ziglang.org", parsed.host orelse return error.UnexpectedNull);
- try testing.expectEqualStrings("/download", parsed.path);
+ try testing.expectEqualStrings("ziglang.org", parsed.host.?.percent_encoded);
+ try testing.expectEqualStrings("/download", parsed.path.percent_encoded);
try testing.expectEqual(@as(?u16, null), parsed.port);
}
test "with port" {
const parsed = try parse("http://example:1337/");
try testing.expectEqualStrings("http", parsed.scheme);
- try testing.expectEqualStrings("example", parsed.host orelse return error.UnexpectedNull);
- try testing.expectEqualStrings("/", parsed.path);
+ try testing.expectEqualStrings("example", parsed.host.?.percent_encoded);
+ try testing.expectEqualStrings("/", parsed.path.percent_encoded);
try testing.expectEqual(@as(?u16, 1337), parsed.port);
}
test "should fail gracefully" {
- try std.testing.expectEqual(@as(ParseError!Uri, error.InvalidFormat), parse("foobar://"));
+ try std.testing.expectError(error.InvalidFormat, parse("foobar://"));
}
test "file" {
const parsed = try parse("file:///");
- try std.testing.expectEqualSlices(u8, "file", parsed.scheme);
- try std.testing.expectEqual(@as(?[]const u8, null), parsed.host);
- try std.testing.expectEqualSlices(u8, "/", parsed.path);
+ try std.testing.expectEqualStrings("file", parsed.scheme);
+ try std.testing.expectEqual(@as(?Component, null), parsed.host);
+ try std.testing.expectEqualStrings("/", parsed.path.percent_encoded);
const parsed2 = try parse("file:///an/absolute/path/to/something");
- try std.testing.expectEqualSlices(u8, "file", parsed2.scheme);
- try std.testing.expectEqual(@as(?[]const u8, null), parsed2.host);
- try std.testing.expectEqualSlices(u8, "/an/absolute/path/to/something", parsed2.path);
+ try std.testing.expectEqualStrings("file", parsed2.scheme);
+ try std.testing.expectEqual(@as(?Component, null), parsed2.host);
+ try std.testing.expectEqualStrings("/an/absolute/path/to/something", parsed2.path.percent_encoded);
const parsed3 = try parse("file://localhost/an/absolute/path/to/another/thing/");
- try std.testing.expectEqualSlices(u8, "file", parsed3.scheme);
- try std.testing.expectEqualSlices(u8, "localhost", parsed3.host.?);
- try std.testing.expectEqualSlices(u8, "/an/absolute/path/to/another/thing/", parsed3.path);
+ try std.testing.expectEqualStrings("file", parsed3.scheme);
+ try std.testing.expectEqualStrings("localhost", parsed3.host.?.percent_encoded);
+ try std.testing.expectEqualStrings("/an/absolute/path/to/another/thing/", parsed3.path.percent_encoded);
}
test "scheme" {
- try std.testing.expectEqualSlices(u8, "http", (try parse("http:_")).scheme);
- try std.testing.expectEqualSlices(u8, "scheme-mee", (try parse("scheme-mee:_")).scheme);
- try std.testing.expectEqualSlices(u8, "a.b.c", (try parse("a.b.c:_")).scheme);
- try std.testing.expectEqualSlices(u8, "ab+", (try parse("ab+:_")).scheme);
- try std.testing.expectEqualSlices(u8, "X+++", (try parse("X+++:_")).scheme);
- try std.testing.expectEqualSlices(u8, "Y+-.", (try parse("Y+-.:_")).scheme);
+ try std.testing.expectEqualStrings("http", (try parse("http:_")).scheme);
+ try std.testing.expectEqualStrings("scheme-mee", (try parse("scheme-mee:_")).scheme);
+ try std.testing.expectEqualStrings("a.b.c", (try parse("a.b.c:_")).scheme);
+ try std.testing.expectEqualStrings("ab+", (try parse("ab+:_")).scheme);
+ try std.testing.expectEqualStrings("X+++", (try parse("X+++:_")).scheme);
+ try std.testing.expectEqualStrings("Y+-.", (try parse("Y+-.:_")).scheme);
}
test "authority" {
- try std.testing.expectEqualSlices(u8, "hostname", (try parse("scheme://hostname")).host.?);
+ try std.testing.expectEqualStrings("hostname", (try parse("scheme://hostname")).host.?.percent_encoded);
- try std.testing.expectEqualSlices(u8, "hostname", (try parse("scheme://userinfo@hostname")).host.?);
- try std.testing.expectEqualSlices(u8, "userinfo", (try parse("scheme://userinfo@hostname")).user.?);
- try std.testing.expectEqual(@as(?[]const u8, null), (try parse("scheme://userinfo@hostname")).password);
- try std.testing.expectEqual(@as(?[]const u8, null), (try parse("scheme://userinfo@")).host);
+ try std.testing.expectEqualStrings("hostname", (try parse("scheme://userinfo@hostname")).host.?.percent_encoded);
+ try std.testing.expectEqualStrings("userinfo", (try parse("scheme://userinfo@hostname")).user.?.percent_encoded);
+ try std.testing.expectEqual(@as(?Component, null), (try parse("scheme://userinfo@hostname")).password);
+ try std.testing.expectEqual(@as(?Component, null), (try parse("scheme://userinfo@")).host);
- try std.testing.expectEqualSlices(u8, "hostname", (try parse("scheme://user:password@hostname")).host.?);
- try std.testing.expectEqualSlices(u8, "user", (try parse("scheme://user:password@hostname")).user.?);
- try std.testing.expectEqualSlices(u8, "password", (try parse("scheme://user:password@hostname")).password.?);
+ try std.testing.expectEqualStrings("hostname", (try parse("scheme://user:password@hostname")).host.?.percent_encoded);
+ try std.testing.expectEqualStrings("user", (try parse("scheme://user:password@hostname")).user.?.percent_encoded);
+ try std.testing.expectEqualStrings("password", (try parse("scheme://user:password@hostname")).password.?.percent_encoded);
- try std.testing.expectEqualSlices(u8, "hostname", (try parse("scheme://hostname:0")).host.?);
+ try std.testing.expectEqualStrings("hostname", (try parse("scheme://hostname:0")).host.?.percent_encoded);
try std.testing.expectEqual(@as(u16, 1234), (try parse("scheme://hostname:1234")).port.?);
- try std.testing.expectEqualSlices(u8, "hostname", (try parse("scheme://userinfo@hostname:1234")).host.?);
+ try std.testing.expectEqualStrings("hostname", (try parse("scheme://userinfo@hostname:1234")).host.?.percent_encoded);
try std.testing.expectEqual(@as(u16, 1234), (try parse("scheme://userinfo@hostname:1234")).port.?);
- try std.testing.expectEqualSlices(u8, "userinfo", (try parse("scheme://userinfo@hostname:1234")).user.?);
- try std.testing.expectEqual(@as(?[]const u8, null), (try parse("scheme://userinfo@hostname:1234")).password);
+ try std.testing.expectEqualStrings("userinfo", (try parse("scheme://userinfo@hostname:1234")).user.?.percent_encoded);
+ try std.testing.expectEqual(@as(?Component, null), (try parse("scheme://userinfo@hostname:1234")).password);
- try std.testing.expectEqualSlices(u8, "hostname", (try parse("scheme://user:password@hostname:1234")).host.?);
+ try std.testing.expectEqualStrings("hostname", (try parse("scheme://user:password@hostname:1234")).host.?.percent_encoded);
try std.testing.expectEqual(@as(u16, 1234), (try parse("scheme://user:password@hostname:1234")).port.?);
- try std.testing.expectEqualSlices(u8, "user", (try parse("scheme://user:password@hostname:1234")).user.?);
- try std.testing.expectEqualSlices(u8, "password", (try parse("scheme://user:password@hostname:1234")).password.?);
+ try std.testing.expectEqualStrings("user", (try parse("scheme://user:password@hostname:1234")).user.?.percent_encoded);
+ try std.testing.expectEqualStrings("password", (try parse("scheme://user:password@hostname:1234")).password.?.percent_encoded);
}
test "authority.password" {
- try std.testing.expectEqualSlices(u8, "username", (try parse("scheme://username@a")).user.?);
- try std.testing.expectEqual(@as(?[]const u8, null), (try parse("scheme://username@a")).password);
+ try std.testing.expectEqualStrings("username", (try parse("scheme://username@a")).user.?.percent_encoded);
+ try std.testing.expectEqual(@as(?Component, null), (try parse("scheme://username@a")).password);
- try std.testing.expectEqualSlices(u8, "username", (try parse("scheme://username:@a")).user.?);
- try std.testing.expectEqual(@as(?[]const u8, null), (try parse("scheme://username:@a")).password);
+ try std.testing.expectEqualStrings("username", (try parse("scheme://username:@a")).user.?.percent_encoded);
+ try std.testing.expectEqual(@as(?Component, null), (try parse("scheme://username:@a")).password);
- try std.testing.expectEqualSlices(u8, "username", (try parse("scheme://username:password@a")).user.?);
- try std.testing.expectEqualSlices(u8, "password", (try parse("scheme://username:password@a")).password.?);
+ try std.testing.expectEqualStrings("username", (try parse("scheme://username:password@a")).user.?.percent_encoded);
+ try std.testing.expectEqualStrings("password", (try parse("scheme://username:password@a")).password.?.percent_encoded);
- try std.testing.expectEqualSlices(u8, "username", (try parse("scheme://username::@a")).user.?);
- try std.testing.expectEqualSlices(u8, ":", (try parse("scheme://username::@a")).password.?);
+ try std.testing.expectEqualStrings("username", (try parse("scheme://username::@a")).user.?.percent_encoded);
+ try std.testing.expectEqualStrings(":", (try parse("scheme://username::@a")).password.?.percent_encoded);
}
fn testAuthorityHost(comptime hostlist: anytype) !void {
inline for (hostlist) |hostname| {
- try std.testing.expectEqualSlices(u8, hostname, (try parse("scheme://" ++ hostname)).host.?);
+ try std.testing.expectEqualStrings(hostname, (try parse("scheme://" ++ hostname)).host.?.percent_encoded);
}
}
@@ -761,11 +732,11 @@ test "RFC example 1" {
.scheme = uri[0..3],
.user = null,
.password = null,
- .host = uri[6..17],
+ .host = .{ .percent_encoded = uri[6..17] },
.port = 8042,
- .path = uri[22..33],
- .query = uri[34..45],
- .fragment = uri[46..50],
+ .path = .{ .percent_encoded = uri[22..33] },
+ .query = .{ .percent_encoded = uri[34..45] },
+ .fragment = .{ .percent_encoded = uri[46..50] },
}, try parse(uri));
}
@@ -777,7 +748,7 @@ test "RFC example 2" {
.password = null,
.host = null,
.port = null,
- .path = uri[4..],
+ .path = .{ .percent_encoded = uri[4..] },
.query = null,
.fragment = null,
}, try parse(uri));
@@ -838,55 +809,60 @@ test "Special test" {
_ = try parse("https://www.youtube.com/watch?v=dQw4w9WgXcQ&feature=youtu.be&t=0");
}
-test "URI escaping" {
- const input = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad";
- const expected = "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad";
+test "URI percent encoding" {
+ try std.testing.expectFmt(
+ "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad",
+ "{%}",
+ .{Component{ .raw = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad" }},
+ );
+}
- const actual = try escapeString(std.testing.allocator, input);
- defer std.testing.allocator.free(actual);
+test "URI percent decoding" {
+ {
+ const expected = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad";
+ var input = "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad".*;
- try std.testing.expectEqualSlices(u8, expected, actual);
-}
+ try std.testing.expectFmt(expected, "{raw}", .{Component{ .percent_encoded = &input }});
+
+ var output: [expected.len]u8 = undefined;
+ try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected);
+
+ try std.testing.expectEqualStrings(expected, percentDecodeInPlace(&input));
+ }
-test "URI unescaping" {
- const input = "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad";
- const expected = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad";
+ {
+ const expected = "/abc%";
+ var input = expected.*;
- const actual = try unescapeString(std.testing.allocator, input);
- defer std.testing.allocator.free(actual);
+ try std.testing.expectFmt(expected, "{raw}", .{Component{ .percent_encoded = &input }});
- try std.testing.expectEqualSlices(u8, expected, actual);
+ var output: [expected.len]u8 = undefined;
+ try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected);
- const decoded = try unescapeString(std.testing.allocator, "/abc%");
- defer std.testing.allocator.free(decoded);
- try std.testing.expectEqualStrings("/abc%", decoded);
+ try std.testing.expectEqualStrings(expected, percentDecodeInPlace(&input));
+ }
}
-test "URI query escaping" {
+test "URI query encoding" {
const address = "https://objects.githubusercontent.com/?response-content-type=application%2Foctet-stream";
const parsed = try Uri.parse(address);
- // format the URI to escape it
- const formatted_uri = try std.fmt.allocPrint(std.testing.allocator, "{/?}", .{parsed});
- defer std.testing.allocator.free(formatted_uri);
- try std.testing.expectEqualStrings("/?response-content-type=application%2Foctet-stream", formatted_uri);
+ // format the URI to percent encode it
+ try std.testing.expectFmt("/?response-content-type=application%2Foctet-stream", "{/?}", .{parsed});
}
test "format" {
- const uri = Uri{
+ const uri: Uri = .{
.scheme = "file",
.user = null,
.password = null,
.host = null,
.port = null,
- .path = "/foo/bar/baz",
+ .path = .{ .raw = "/foo/bar/baz" },
.query = null,
.fragment = null,
};
- var buf = std.ArrayList(u8).init(std.testing.allocator);
- defer buf.deinit();
- try buf.writer().print("{;/?#}", .{uri});
- try std.testing.expectEqualSlices(u8, "file:/foo/bar/baz", buf.items);
+ try std.testing.expectFmt("file:/foo/bar/baz", "{;/?#}", .{uri});
}
test "URI malformed input" {
@@ -894,3 +870,7 @@ test "URI malformed input" {
try std.testing.expectError(error.InvalidFormat, std.Uri.parse("http://]@["));
try std.testing.expectError(error.InvalidFormat, std.Uri.parse("http://lo]s\x85hc@[/8\x10?0Q"));
}
+
+const std = @import("std.zig");
+const testing = std.testing;
+const Uri = @This();
diff --git a/lib/std/c/haiku.zig b/lib/std/c/haiku.zig
index d75dd3bf00..cd2e4bc296 100644
--- a/lib/std/c/haiku.zig
+++ b/lib/std/c/haiku.zig
@@ -5,28 +5,18 @@ const maxInt = std.math.maxInt;
const iovec = std.posix.iovec;
const iovec_const = std.posix.iovec_const;
-extern "c" fn _errnop() *c_int;
+pub extern "root" fn find_directory(which: directory_which, volume: i32, createIt: bool, path_ptr: [*]u8, length: i32) u64;
-pub const _errno = _errnop;
-
-pub extern "c" fn find_directory(which: directory_which, volume: i32, createIt: bool, path_ptr: [*]u8, length: i32) u64;
-
-pub extern "c" fn find_thread(thread_name: ?*anyopaque) i32;
+pub extern "root" fn find_thread(thread_name: ?*anyopaque) i32;
-pub extern "c" fn get_system_info(system_info: *system_info) usize;
+pub extern "root" fn get_system_info(system_info: *system_info) usize;
-pub extern "c" fn _get_team_info(team: c_int, team_info: *team_info, size: usize) i32;
+pub extern "root" fn _get_team_info(team: i32, team_info: *team_info, size: usize) i32;
-pub extern "c" fn _get_next_area_info(team: c_int, cookie: *i64, area_info: *area_info, size: usize) i32;
+pub extern "root" fn _get_next_area_info(team: i32, cookie: *i64, area_info: *area_info, size: usize) i32;
// TODO revisit if abi changes or better option becomes apparent
-pub extern "c" fn _get_next_image_info(team: c_int, cookie: *i32, image_info: *image_info, size: usize) i32;
-
-pub extern "c" fn _kern_read_dir(fd: c_int, buf_ptr: [*]u8, nbytes: usize, maxcount: u32) usize;
-
-pub extern "c" fn _kern_read_stat(fd: c_int, path_ptr: [*]u8, traverse_link: bool, st: *Stat, stat_size: i32) usize;
-
-pub extern "c" fn _kern_get_current_team() i32;
+pub extern "root" fn _get_next_image_info(team: i32, cookie: *i32, image_info: *image_info, size: usize) i32;
pub const sem_t = extern struct {
type: i32,
@@ -45,7 +35,7 @@ pub const pthread_attr_t = extern struct {
__stack_address: ?*anyopaque,
};
-pub const EAI = enum(c_int) {
+pub const EAI = enum(i32) {
/// address family for hostname not supported
ADDRFAMILY = 1,
@@ -99,11 +89,7 @@ pub const AI = struct {
pub const AI_NUMERICSERV = AI.NUMERICSERV;
-pub const fd_t = c_int;
-pub const pid_t = c_int;
-pub const uid_t = u32;
-pub const gid_t = u32;
-pub const mode_t = c_uint;
+pub const fd_t = i32;
pub const socklen_t = u32;
@@ -129,8 +115,8 @@ pub const dl_phdr_info = extern struct {
};
pub const Flock = extern struct {
- type: c_short,
- whence: c_short,
+ type: i16,
+ whence: i16,
start: off_t,
len: off_t,
pid: pid_t,
@@ -159,54 +145,6 @@ pub const msghdr = extern struct {
msg_flags: i32,
};
-pub const off_t = i64;
-pub const ino_t = u64;
-
-pub const Stat = extern struct {
- dev: i32,
- ino: u64,
- mode: u32,
- nlink: i32,
- uid: i32,
- gid: i32,
- size: i64,
- rdev: i32,
- blksize: i32,
- atim: timespec,
- mtim: timespec,
- ctim: timespec,
- crtim: timespec,
- st_type: u32,
- blocks: i64,
-
- pub fn atime(self: @This()) timespec {
- return self.atim;
- }
- pub fn mtime(self: @This()) timespec {
- return self.mtim;
- }
- pub fn ctime(self: @This()) timespec {
- return self.ctim;
- }
- pub fn birthtime(self: @This()) timespec {
- return self.crtim;
- }
-};
-
-pub const timespec = extern struct {
- tv_sec: isize,
- tv_nsec: isize,
-};
-
-pub const dirent = extern struct {
- dev: i32,
- pdev: i32,
- ino: i64,
- pino: i64,
- reclen: u16,
- name: [256]u8,
-};
-
pub const B_OS_NAME_LENGTH = 32; // OS.h
pub const area_info = extern struct {
@@ -354,17 +292,6 @@ pub const PROT = struct {
pub const NONE = 0x00;
};
-pub const CLOCK = struct {
- /// system-wide monotonic clock (aka system time)
- pub const MONOTONIC = 0;
- /// system-wide real time clock
- pub const REALTIME = -1;
- /// clock measuring the used CPU time of the current process
- pub const PROCESS_CPUTIME_ID = -2;
- /// clock measuring the used CPU time of the current thread
- pub const THREAD_CPUTIME_ID = -3;
-};
-
pub const MSF = struct {
pub const ASYNC = 1;
pub const INVALIDATE = 2;
@@ -404,159 +331,526 @@ pub const W = struct {
}
};
-// /system/develop/headers/posix/poll.h
+// access function
+pub const F_OK = 0; // test for existence of file
+pub const X_OK = 1; // test for execute or search permission
+pub const W_OK = 2; // test for write permission
+pub const R_OK = 4; // test for read permission
-pub const nfds_t = usize;
+pub const F = struct {
+ pub const DUPFD = 0x0001;
+ pub const GETFD = 0x0002;
+ pub const SETFD = 0x0004;
+ pub const GETFL = 0x0008;
+ pub const SETFL = 0x0010;
-pub const pollfd = extern struct {
- fd: i32,
- events: i16,
- revents: i16,
-};
+ pub const GETLK = 0x0020;
+ pub const SETLK = 0x0080;
+ pub const SETLKW = 0x0100;
+ pub const DUPFD_CLOEXEC = 0x0200;
-pub const POLL = struct {
- /// any readable data available
- pub const IN = 0x0001;
- /// file descriptor is writeable
- pub const OUT = 0x0002;
- pub const RDNORM = IN;
- pub const WRNORM = OUT;
- /// priority readable data
- pub const RDBAND = 0x0008;
- /// priority data can be written
- pub const WRBAND = 0x0010;
- /// high priority readable data
- pub const PRI = 0x0020;
+ pub const RDLCK = 0x0040;
+ pub const UNLCK = 0x0200;
+ pub const WRLCK = 0x0400;
+};
- /// errors pending
- pub const ERR = 0x0004;
- /// disconnected
- pub const HUP = 0x0080;
- /// invalid file descriptor
- pub const NVAL = 0x1000;
+pub const LOCK = struct {
+ pub const SH = 0x01;
+ pub const EX = 0x02;
+ pub const NB = 0x04;
+ pub const UN = 0x08;
};
-// /system/develop/headers/posix/signal.h
+pub const FD_CLOEXEC = 1;
-pub const sigset_t = u64;
-pub const empty_sigset: sigset_t = 0;
-pub const filled_sigset = ~@as(sigset_t, 0);
+pub const SEEK = struct {
+ pub const SET = 0;
+ pub const CUR = 1;
+ pub const END = 2;
+};
-pub const SIG = struct {
- pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
- pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
- pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
+pub const SOCK = struct {
+ pub const STREAM = 1;
+ pub const DGRAM = 2;
+ pub const RAW = 3;
+ pub const SEQPACKET = 5;
- pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(3);
+ /// WARNING: this flag is not supported by windows socket functions directly,
+ /// it is only supported by std.os.socket. Be sure that this value does
+ /// not share any bits with any of the `SOCK` values.
+ pub const CLOEXEC = 0x10000;
+ /// WARNING: this flag is not supported by windows socket functions directly,
+ /// it is only supported by std.os.socket. Be sure that this value does
+ /// not share any bits with any of the `SOCK` values.
+ pub const NONBLOCK = 0x20000;
+};
- pub const HUP = 1;
- pub const INT = 2;
- pub const QUIT = 3;
- pub const ILL = 4;
- pub const CHLD = 5;
- pub const ABRT = 6;
- pub const IOT = ABRT;
- pub const PIPE = 7;
- pub const FPE = 8;
- pub const KILL = 9;
- pub const STOP = 10;
- pub const SEGV = 11;
- pub const CONT = 12;
- pub const TSTP = 13;
- pub const ALRM = 14;
- pub const TERM = 15;
- pub const TTIN = 16;
- pub const TTOU = 17;
- pub const USR1 = 18;
- pub const USR2 = 19;
- pub const WINCH = 20;
- pub const KILLTHR = 21;
- pub const TRAP = 22;
- pub const POLL = 23;
- pub const PROF = 24;
- pub const SYS = 25;
- pub const URG = 26;
- pub const VTALRM = 27;
- pub const XCPU = 28;
- pub const XFSZ = 29;
- pub const BUS = 30;
- pub const RESERVED1 = 31;
- pub const RESERVED2 = 32;
+pub const SO = struct {
+ pub const ACCEPTCONN = 0x00000001;
+ pub const BROADCAST = 0x00000002;
+ pub const DEBUG = 0x00000004;
+ pub const DONTROUTE = 0x00000008;
+ pub const KEEPALIVE = 0x00000010;
+ pub const OOBINLINE = 0x00000020;
+ pub const REUSEADDR = 0x00000040;
+ pub const REUSEPORT = 0x00000080;
+ pub const USELOOPBACK = 0x00000100;
+ pub const LINGER = 0x00000200;
- pub const BLOCK = 1;
- pub const UNBLOCK = 2;
- pub const SETMASK = 3;
+ pub const SNDBUF = 0x40000001;
+ pub const SNDLOWAT = 0x40000002;
+ pub const SNDTIMEO = 0x40000003;
+ pub const RCVBUF = 0x40000004;
+ pub const RCVLOWAT = 0x40000005;
+ pub const RCVTIMEO = 0x40000006;
+ pub const ERROR = 0x40000007;
+ pub const TYPE = 0x40000008;
+ pub const NONBLOCK = 0x40000009;
+ pub const BINDTODEVICE = 0x4000000a;
+ pub const PEERCRED = 0x4000000b;
};
-pub const siginfo_t = extern struct {
- signo: c_int,
- code: c_int,
- errno: c_int,
+pub const SOL = struct {
+ pub const SOCKET = -1;
+};
- pid: pid_t,
- uid: uid_t,
- addr: *allowzero anyopaque,
+pub const PF = struct {
+ pub const UNSPEC = AF.UNSPEC;
+ pub const INET = AF.INET;
+ pub const ROUTE = AF.ROUTE;
+ pub const LINK = AF.LINK;
+ pub const INET6 = AF.INET6;
+ pub const LOCAL = AF.LOCAL;
+ pub const UNIX = AF.UNIX;
+ pub const BLUETOOTH = AF.BLUETOOTH;
};
-/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
-pub const Sigaction = extern struct {
- pub const handler_fn = *align(1) const fn (i32) callconv(.C) void;
- pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void;
+pub const AF = struct {
+ pub const UNSPEC = 0;
+ pub const INET = 1;
+ pub const APPLETALK = 2;
+ pub const ROUTE = 3;
+ pub const LINK = 4;
+ pub const INET6 = 5;
+ pub const DLI = 6;
+ pub const IPX = 7;
+ pub const NOTIFY = 8;
+ pub const LOCAL = 9;
+ pub const UNIX = LOCAL;
+ pub const BLUETOOTH = 10;
+ pub const MAX = 11;
+};
- /// signal handler
- handler: extern union {
- handler: handler_fn,
- sigaction: sigaction_fn,
- },
+pub const DT = struct {};
- /// signal mask to apply
- mask: sigset_t,
+/// add event to kq (implies enable)
+pub const EV_ADD = 0x0001;
- /// see signal options
- flags: c_int,
+/// delete event from kq
+pub const EV_DELETE = 0x0002;
- /// will be passed to the signal handler, BeOS extension
- userdata: *allowzero anyopaque = undefined,
+/// enable event
+pub const EV_ENABLE = 0x0004;
+
+/// disable event (not reported)
+pub const EV_DISABLE = 0x0008;
+
+/// only report one occurrence
+pub const EV_ONESHOT = 0x0010;
+
+/// clear event state after reporting
+pub const EV_CLEAR = 0x0020;
+
+/// force immediate event output
+/// ... with or without EV_ERROR
+/// ... use KEVENT_FLAG_ERROR_EVENTS
+/// on syscalls supporting flags
+pub const EV_RECEIPT = 0x0040;
+
+/// disable event after reporting
+pub const EV_DISPATCH = 0x0080;
+
+pub const EVFILT_READ = -1;
+pub const EVFILT_WRITE = -2;
+
+/// attached to aio requests
+pub const EVFILT_AIO = -3;
+
+/// attached to vnodes
+pub const EVFILT_VNODE = -4;
+
+/// attached to struct proc
+pub const EVFILT_PROC = -5;
+
+/// attached to struct proc
+pub const EVFILT_SIGNAL = -6;
+
+/// timers
+pub const EVFILT_TIMER = -7;
+
+/// Process descriptors
+pub const EVFILT_PROCDESC = -8;
+
+/// Filesystem events
+pub const EVFILT_FS = -9;
+
+pub const EVFILT_LIO = -10;
+
+/// User events
+pub const EVFILT_USER = -11;
+
+/// Sendfile events
+pub const EVFILT_SENDFILE = -12;
+
+pub const EVFILT_EMPTY = -13;
+
+pub const T = struct {
+ pub const CGETA = 0x8000;
+ pub const CSETA = 0x8001;
+ pub const CSETAF = 0x8002;
+ pub const CSETAW = 0x8003;
+ pub const CWAITEVENT = 0x8004;
+ pub const CSBRK = 0x8005;
+ pub const CFLSH = 0x8006;
+ pub const CXONC = 0x8007;
+ pub const CQUERYCONNECTED = 0x8008;
+ pub const CGETBITS = 0x8009;
+ pub const CSETDTR = 0x8010;
+ pub const CSETRTS = 0x8011;
+ pub const IOCGWINSZ = 0x8012;
+ pub const IOCSWINSZ = 0x8013;
+ pub const CVTIME = 0x8014;
+ pub const IOCGPGRP = 0x8015;
+ pub const IOCSPGRP = 0x8016;
+ pub const IOCSCTTY = 0x8017;
+ pub const IOCMGET = 0x8018;
+ pub const IOCMSET = 0x8019;
+ pub const IOCSBRK = 0x8020;
+ pub const IOCCBRK = 0x8021;
+ pub const IOCMBIS = 0x8022;
+ pub const IOCMBIC = 0x8023;
+ pub const IOCGSID = 0x8024;
+
+ pub const FIONREAD = 0xbe000001;
+ pub const FIONBIO = 0xbe000000;
};
-pub const SA = struct {
- pub const NOCLDSTOP = 0x01;
- pub const NOCLDWAIT = 0x02;
- pub const RESETHAND = 0x04;
- pub const NODEFER = 0x08;
- pub const RESTART = 0x10;
- pub const ONSTACK = 0x20;
- pub const SIGINFO = 0x40;
- pub const NOMASK = NODEFER;
- pub const STACK = ONSTACK;
- pub const ONESHOT = RESETHAND;
+pub const winsize = extern struct {
+ ws_row: u16,
+ ws_col: u16,
+ ws_xpixel: u16,
+ ws_ypixel: u16,
};
-pub const SS = struct {
- pub const ONSTACK = 0x1;
- pub const DISABLE = 0x2;
+pub const S = struct {
+ pub const IFMT = 0o170000;
+ pub const IFSOCK = 0o140000;
+ pub const IFLNK = 0o120000;
+ pub const IFREG = 0o100000;
+ pub const IFBLK = 0o060000;
+ pub const IFDIR = 0o040000;
+ pub const IFCHR = 0o020000;
+ pub const IFIFO = 0o010000;
+ pub const INDEX_DIR = 0o4000000000;
+
+ pub const IUMSK = 0o7777;
+ pub const ISUID = 0o4000;
+ pub const ISGID = 0o2000;
+ pub const ISVTX = 0o1000;
+ pub const IRWXU = 0o700;
+ pub const IRUSR = 0o400;
+ pub const IWUSR = 0o200;
+ pub const IXUSR = 0o100;
+ pub const IRWXG = 0o070;
+ pub const IRGRP = 0o040;
+ pub const IWGRP = 0o020;
+ pub const IXGRP = 0o010;
+ pub const IRWXO = 0o007;
+ pub const IROTH = 0o004;
+ pub const IWOTH = 0o002;
+ pub const IXOTH = 0o001;
+
+ pub fn ISREG(m: u32) bool {
+ return m & IFMT == IFREG;
+ }
+
+ pub fn ISLNK(m: u32) bool {
+ return m & IFMT == IFLNK;
+ }
+
+ pub fn ISBLK(m: u32) bool {
+ return m & IFMT == IFBLK;
+ }
+
+ pub fn ISDIR(m: u32) bool {
+ return m & IFMT == IFDIR;
+ }
+
+ pub fn ISCHR(m: u32) bool {
+ return m & IFMT == IFCHR;
+ }
+
+ pub fn ISFIFO(m: u32) bool {
+ return m & IFMT == IFIFO;
+ }
+
+ pub fn ISSOCK(m: u32) bool {
+ return m & IFMT == IFSOCK;
+ }
+
+ pub fn ISINDEX(m: u32) bool {
+ return m & INDEX_DIR == INDEX_DIR;
+ }
};
-pub const MINSIGSTKSZ = 8192;
-pub const SIGSTKSZ = 16384;
+pub const HOST_NAME_MAX = 255;
-pub const stack_t = extern struct {
- sp: [*]u8,
- size: isize,
+pub const addrinfo = extern struct {
flags: i32,
+ family: i32,
+ socktype: i32,
+ protocol: i32,
+ addrlen: socklen_t,
+ canonname: ?[*:0]u8,
+ addr: ?*sockaddr,
+ next: ?*addrinfo,
};
-pub const NSIG = 65;
+pub const IPPROTO = struct {
+ pub const IP = 0;
+ pub const HOPOPTS = 0;
+ pub const ICMP = 1;
+ pub const IGMP = 2;
+ pub const TCP = 6;
+ pub const UDP = 17;
+ pub const IPV6 = 41;
+ pub const ROUTING = 43;
+ pub const FRAGMENT = 44;
+ pub const ESP = 50;
+ pub const AH = 51;
+ pub const ICMPV6 = 58;
+ pub const NONE = 59;
+ pub const DSTOPTS = 60;
+ pub const ETHERIP = 97;
+ pub const RAW = 255;
+ pub const MAX = 256;
+};
-pub const mcontext_t = vregs;
+pub const rlimit_resource = enum(i32) {
+ CORE = 0,
+ CPU = 1,
+ DATA = 2,
+ FSIZE = 3,
+ NOFILE = 4,
+ STACK = 5,
+ AS = 6,
+ NOVMON = 7,
+ _,
+};
-pub const ucontext_t = extern struct {
- link: ?*ucontext_t,
- sigmask: sigset_t,
- stack: stack_t,
- mcontext: mcontext_t,
+pub const rlim_t = i64;
+
+pub const RLIM = struct {
+ /// No limit
+ pub const INFINITY: rlim_t = (1 << 63) - 1;
+
+ pub const SAVED_MAX = INFINITY;
+ pub const SAVED_CUR = INFINITY;
+};
+
+pub const rlimit = extern struct {
+ /// Soft limit
+ cur: rlim_t,
+ /// Hard limit
+ max: rlim_t,
+};
+
+pub const SHUT = struct {
+ pub const RD = 0;
+ pub const WR = 1;
+ pub const RDWR = 2;
+};
+
+// TODO fill out if needed
+pub const directory_which = enum(i32) {
+ B_USER_SETTINGS_DIRECTORY = 0xbbe,
+
+ _,
+};
+
+pub const MSG_NOSIGNAL = 0x0800;
+
+// /system/develop/headers/os/kernel/OS.h
+
+pub const area_id = i32;
+pub const port_id = i32;
+pub const sem_id = i32;
+pub const team_id = i32;
+pub const thread_id = i32;
+
+// /system/develop/headers/os/support/Errors.h
+
+pub const E = enum(i32) {
+ pub const B_GENERAL_ERROR_BASE: i32 = std.math.minInt(i32);
+ pub const B_OS_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x1000;
+ pub const B_APP_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x2000;
+ pub const B_INTERFACE_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x3000;
+ pub const B_MEDIA_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x4000;
+ pub const B_TRANSLATION_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x4800;
+ pub const B_MIDI_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x5000;
+ pub const B_STORAGE_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x6000;
+ pub const B_POSIX_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x7000;
+ pub const B_MAIL_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x8000;
+ pub const B_PRINT_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x9000;
+ pub const B_DEVICE_ERROR_BASE = B_GENERAL_ERROR_BASE + 0xa000;
+
+ pub const B_ERRORS_END = B_GENERAL_ERROR_BASE + 0xffff;
+
+ pub const B_NO_MEMORY = B_GENERAL_ERROR_BASE + 0;
+ pub const B_IO_ERROR = B_GENERAL_ERROR_BASE + 1;
+ pub const B_PERMISSION_DENIED = B_GENERAL_ERROR_BASE + 2;
+ pub const B_BAD_INDEX = B_GENERAL_ERROR_BASE + 3;
+ pub const B_BAD_TYPE = B_GENERAL_ERROR_BASE + 4;
+ pub const B_BAD_VALUE = B_GENERAL_ERROR_BASE + 5;
+ pub const B_MISMATCHED_VALUES = B_GENERAL_ERROR_BASE + 6;
+ pub const B_NAME_NOT_FOUND = B_GENERAL_ERROR_BASE + 7;
+ pub const B_NAME_IN_USE = B_GENERAL_ERROR_BASE + 8;
+ pub const B_TIMED_OUT = B_GENERAL_ERROR_BASE + 9;
+ pub const B_INTERRUPTED = B_GENERAL_ERROR_BASE + 10;
+ pub const B_WOULD_BLOCK = B_GENERAL_ERROR_BASE + 11;
+ pub const B_CANCELED = B_GENERAL_ERROR_BASE + 12;
+ pub const B_NO_INIT = B_GENERAL_ERROR_BASE + 13;
+ pub const B_NOT_INITIALIZED = B_GENERAL_ERROR_BASE + 13;
+ pub const B_BUSY = B_GENERAL_ERROR_BASE + 14;
+ pub const B_NOT_ALLOWED = B_GENERAL_ERROR_BASE + 15;
+ pub const B_BAD_DATA = B_GENERAL_ERROR_BASE + 16;
+ pub const B_DONT_DO_THAT = B_GENERAL_ERROR_BASE + 17;
+
+ pub const B_BAD_IMAGE_ID = B_OS_ERROR_BASE + 0x300;
+ pub const B_BAD_ADDRESS = B_OS_ERROR_BASE + 0x301;
+ pub const B_NOT_AN_EXECUTABLE = B_OS_ERROR_BASE + 0x302;
+ pub const B_MISSING_LIBRARY = B_OS_ERROR_BASE + 0x303;
+ pub const B_MISSING_SYMBOL = B_OS_ERROR_BASE + 0x304;
+ pub const B_UNKNOWN_EXECUTABLE = B_OS_ERROR_BASE + 0x305;
+ pub const B_LEGACY_EXECUTABLE = B_OS_ERROR_BASE + 0x306;
+
+ pub const B_FILE_ERROR = B_STORAGE_ERROR_BASE + 0;
+ pub const B_FILE_EXISTS = B_STORAGE_ERROR_BASE + 2;
+ pub const B_ENTRY_NOT_FOUND = B_STORAGE_ERROR_BASE + 3;
+ pub const B_NAME_TOO_LONG = B_STORAGE_ERROR_BASE + 4;
+ pub const B_NOT_A_DIRECTORY = B_STORAGE_ERROR_BASE + 5;
+ pub const B_DIRECTORY_NOT_EMPTY = B_STORAGE_ERROR_BASE + 6;
+ pub const B_DEVICE_FULL = B_STORAGE_ERROR_BASE + 7;
+ pub const B_READ_ONLY_DEVICE = B_STORAGE_ERROR_BASE + 8;
+ pub const B_IS_A_DIRECTORY = B_STORAGE_ERROR_BASE + 9;
+ pub const B_NO_MORE_FDS = B_STORAGE_ERROR_BASE + 10;
+ pub const B_CROSS_DEVICE_LINK = B_STORAGE_ERROR_BASE + 11;
+ pub const B_LINK_LIMIT = B_STORAGE_ERROR_BASE + 12;
+ pub const B_BUSTED_PIPE = B_STORAGE_ERROR_BASE + 13;
+ pub const B_UNSUPPORTED = B_STORAGE_ERROR_BASE + 14;
+ pub const B_PARTITION_TOO_SMALL = B_STORAGE_ERROR_BASE + 15;
+ pub const B_PARTIAL_READ = B_STORAGE_ERROR_BASE + 16;
+ pub const B_PARTIAL_WRITE = B_STORAGE_ERROR_BASE + 17;
+
+ SUCCESS = 0,
+
+ @"2BIG" = B_POSIX_ERROR_BASE + 1,
+ CHILD = B_POSIX_ERROR_BASE + 2,
+ DEADLK = B_POSIX_ERROR_BASE + 3,
+ FBIG = B_POSIX_ERROR_BASE + 4,
+ MLINK = B_POSIX_ERROR_BASE + 5,
+ NFILE = B_POSIX_ERROR_BASE + 6,
+ NODEV = B_POSIX_ERROR_BASE + 7,
+ NOLCK = B_POSIX_ERROR_BASE + 8,
+ NOSYS = B_POSIX_ERROR_BASE + 9,
+ NOTTY = B_POSIX_ERROR_BASE + 10,
+ NXIO = B_POSIX_ERROR_BASE + 11,
+ SPIPE = B_POSIX_ERROR_BASE + 12,
+ SRCH = B_POSIX_ERROR_BASE + 13,
+ FPOS = B_POSIX_ERROR_BASE + 14,
+ SIGPARM = B_POSIX_ERROR_BASE + 15,
+ DOM = B_POSIX_ERROR_BASE + 16,
+ RANGE = B_POSIX_ERROR_BASE + 17,
+ PROTOTYPE = B_POSIX_ERROR_BASE + 18,
+ PROTONOSUPPORT = B_POSIX_ERROR_BASE + 19,
+ PFNOSUPPORT = B_POSIX_ERROR_BASE + 20,
+ AFNOSUPPORT = B_POSIX_ERROR_BASE + 21,
+ ADDRINUSE = B_POSIX_ERROR_BASE + 22,
+ ADDRNOTAVAIL = B_POSIX_ERROR_BASE + 23,
+ NETDOWN = B_POSIX_ERROR_BASE + 24,
+ NETUNREACH = B_POSIX_ERROR_BASE + 25,
+ NETRESET = B_POSIX_ERROR_BASE + 26,
+ CONNABORTED = B_POSIX_ERROR_BASE + 27,
+ CONNRESET = B_POSIX_ERROR_BASE + 28,
+ ISCONN = B_POSIX_ERROR_BASE + 29,
+ NOTCONN = B_POSIX_ERROR_BASE + 30,
+ SHUTDOWN = B_POSIX_ERROR_BASE + 31,
+ CONNREFUSED = B_POSIX_ERROR_BASE + 32,
+ HOSTUNREACH = B_POSIX_ERROR_BASE + 33,
+ NOPROTOOPT = B_POSIX_ERROR_BASE + 34,
+ NOBUFS = B_POSIX_ERROR_BASE + 35,
+ INPROGRESS = B_POSIX_ERROR_BASE + 36,
+ ALREADY = B_POSIX_ERROR_BASE + 37,
+ ILSEQ = B_POSIX_ERROR_BASE + 38,
+ NOMSG = B_POSIX_ERROR_BASE + 39,
+ STALE = B_POSIX_ERROR_BASE + 40,
+ OVERFLOW = B_POSIX_ERROR_BASE + 41,
+ MSGSIZE = B_POSIX_ERROR_BASE + 42,
+ OPNOTSUPP = B_POSIX_ERROR_BASE + 43,
+ NOTSOCK = B_POSIX_ERROR_BASE + 44,
+ HOSTDOWN = B_POSIX_ERROR_BASE + 45,
+ BADMSG = B_POSIX_ERROR_BASE + 46,
+ CANCELED = B_POSIX_ERROR_BASE + 47,
+ DESTADDRREQ = B_POSIX_ERROR_BASE + 48,
+ DQUOT = B_POSIX_ERROR_BASE + 49,
+ IDRM = B_POSIX_ERROR_BASE + 50,
+ MULTIHOP = B_POSIX_ERROR_BASE + 51,
+ NODATA = B_POSIX_ERROR_BASE + 52,
+ NOLINK = B_POSIX_ERROR_BASE + 53,
+ NOSR = B_POSIX_ERROR_BASE + 54,
+ NOSTR = B_POSIX_ERROR_BASE + 55,
+ NOTSUP = B_POSIX_ERROR_BASE + 56,
+ PROTO = B_POSIX_ERROR_BASE + 57,
+ TIME = B_POSIX_ERROR_BASE + 58,
+ TXTBSY = B_POSIX_ERROR_BASE + 59,
+ NOATTR = B_POSIX_ERROR_BASE + 60,
+ NOTRECOVERABLE = B_POSIX_ERROR_BASE + 61,
+ OWNERDEAD = B_POSIX_ERROR_BASE + 62,
+
+ NOMEM = B_NO_MEMORY,
+
+ ACCES = B_PERMISSION_DENIED,
+ INTR = B_INTERRUPTED,
+ IO = B_IO_ERROR,
+ BUSY = B_BUSY,
+ FAULT = B_BAD_ADDRESS,
+ TIMEDOUT = B_TIMED_OUT,
+ /// Also used for WOULDBLOCK
+ AGAIN = B_WOULD_BLOCK,
+ BADF = B_FILE_ERROR,
+ EXIST = B_FILE_EXISTS,
+ INVAL = B_BAD_VALUE,
+ NAMETOOLONG = B_NAME_TOO_LONG,
+ NOENT = B_ENTRY_NOT_FOUND,
+ PERM = B_NOT_ALLOWED,
+ NOTDIR = B_NOT_A_DIRECTORY,
+ ISDIR = B_IS_A_DIRECTORY,
+ NOTEMPTY = B_DIRECTORY_NOT_EMPTY,
+ NOSPC = B_DEVICE_FULL,
+ ROFS = B_READ_ONLY_DEVICE,
+ MFILE = B_NO_MORE_FDS,
+ XDEV = B_CROSS_DEVICE_LINK,
+ LOOP = B_LINK_LIMIT,
+ NOEXEC = B_NOT_AN_EXECUTABLE,
+ PIPE = B_BUSTED_PIPE,
+
+ _,
};
+// /system/develop/headers/os/support/SupportDefs.h
+
+pub const status_t = i32;
+
// /system/develop/headers/posix/arch/*/signal.h
pub const vregs = switch (builtin.cpu.arch) {
@@ -822,445 +1116,278 @@ pub const vregs = switch (builtin.cpu.arch) {
else => void,
};
-// access function
-pub const F_OK = 0; // test for existence of file
-pub const X_OK = 1; // test for execute or search permission
-pub const W_OK = 2; // test for write permission
-pub const R_OK = 4; // test for read permission
-
-pub const F = struct {
- pub const DUPFD = 0x0001;
- pub const GETFD = 0x0002;
- pub const SETFD = 0x0004;
- pub const GETFL = 0x0008;
- pub const SETFL = 0x0010;
-
- pub const GETLK = 0x0020;
- pub const SETLK = 0x0080;
- pub const SETLKW = 0x0100;
- pub const DUPFD_CLOEXEC = 0x0200;
-
- pub const RDLCK = 0x0040;
- pub const UNLCK = 0x0200;
- pub const WRLCK = 0x0400;
-};
-
-pub const LOCK = struct {
- pub const SH = 0x01;
- pub const EX = 0x02;
- pub const NB = 0x04;
- pub const UN = 0x08;
-};
-
-pub const FD_CLOEXEC = 1;
-
-pub const SEEK = struct {
- pub const SET = 0;
- pub const CUR = 1;
- pub const END = 2;
+// /system/develop/headers/posix/dirent.h
+
+pub const DirEnt = extern struct {
+ /// device
+ dev: dev_t,
+ /// parent device (only for queries)
+ pdev: dev_t,
+ /// inode number
+ ino: ino_t,
+ /// parent inode (only for queries)
+ pino: ino_t,
+ /// length of this record, not the name
+ reclen: u16,
+ /// name of the entry (null byte terminated)
+ name: [0]u8,
+ pub fn getName(dirent: *const DirEnt) [*:0]const u8 {
+ return @ptrCast(&dirent.name);
+ }
};
-pub const SOCK = struct {
- pub const STREAM = 1;
- pub const DGRAM = 2;
- pub const RAW = 3;
- pub const SEQPACKET = 5;
+// /system/develop/headers/posix/errno.h
- /// WARNING: this flag is not supported by windows socket functions directly,
- /// it is only supported by std.os.socket. Be sure that this value does
- /// not share any bits with any of the `SOCK` values.
- pub const CLOEXEC = 0x10000;
- /// WARNING: this flag is not supported by windows socket functions directly,
- /// it is only supported by std.os.socket. Be sure that this value does
- /// not share any bits with any of the `SOCK` values.
- pub const NONBLOCK = 0x20000;
-};
+extern "root" fn _errnop() *i32;
+pub const _errno = _errnop;
-pub const SO = struct {
- pub const ACCEPTCONN = 0x00000001;
- pub const BROADCAST = 0x00000002;
- pub const DEBUG = 0x00000004;
- pub const DONTROUTE = 0x00000008;
- pub const KEEPALIVE = 0x00000010;
- pub const OOBINLINE = 0x00000020;
- pub const REUSEADDR = 0x00000040;
- pub const REUSEPORT = 0x00000080;
- pub const USELOOPBACK = 0x00000100;
- pub const LINGER = 0x00000200;
+// /system/develop/headers/posix/poll.h
- pub const SNDBUF = 0x40000001;
- pub const SNDLOWAT = 0x40000002;
- pub const SNDTIMEO = 0x40000003;
- pub const RCVBUF = 0x40000004;
- pub const RCVLOWAT = 0x40000005;
- pub const RCVTIMEO = 0x40000006;
- pub const ERROR = 0x40000007;
- pub const TYPE = 0x40000008;
- pub const NONBLOCK = 0x40000009;
- pub const BINDTODEVICE = 0x4000000a;
- pub const PEERCRED = 0x4000000b;
-};
+pub const nfds_t = usize;
-pub const SOL = struct {
- pub const SOCKET = -1;
+pub const pollfd = extern struct {
+ fd: i32,
+ events: i16,
+ revents: i16,
};
-pub const PF = struct {
- pub const UNSPEC = AF.UNSPEC;
- pub const INET = AF.INET;
- pub const ROUTE = AF.ROUTE;
- pub const LINK = AF.LINK;
- pub const INET6 = AF.INET6;
- pub const LOCAL = AF.LOCAL;
- pub const UNIX = AF.UNIX;
- pub const BLUETOOTH = AF.BLUETOOTH;
-};
+pub const POLL = struct {
+ /// any readable data available
+ pub const IN = 0x0001;
+ /// file descriptor is writeable
+ pub const OUT = 0x0002;
+ pub const RDNORM = IN;
+ pub const WRNORM = OUT;
+ /// priority readable data
+ pub const RDBAND = 0x0008;
+ /// priority data can be written
+ pub const WRBAND = 0x0010;
+ /// high priority readable data
+ pub const PRI = 0x0020;
-pub const AF = struct {
- pub const UNSPEC = 0;
- pub const INET = 1;
- pub const APPLETALK = 2;
- pub const ROUTE = 3;
- pub const LINK = 4;
- pub const INET6 = 5;
- pub const DLI = 6;
- pub const IPX = 7;
- pub const NOTIFY = 8;
- pub const LOCAL = 9;
- pub const UNIX = LOCAL;
- pub const BLUETOOTH = 10;
- pub const MAX = 11;
+ /// errors pending
+ pub const ERR = 0x0004;
+ /// disconnected
+ pub const HUP = 0x0080;
+ /// invalid file descriptor
+ pub const NVAL = 0x1000;
};
-pub const DT = struct {};
-
-/// add event to kq (implies enable)
-pub const EV_ADD = 0x0001;
-
-/// delete event from kq
-pub const EV_DELETE = 0x0002;
-
-/// enable event
-pub const EV_ENABLE = 0x0004;
-
-/// disable event (not reported)
-pub const EV_DISABLE = 0x0008;
-
-/// only report one occurrence
-pub const EV_ONESHOT = 0x0010;
-
-/// clear event state after reporting
-pub const EV_CLEAR = 0x0020;
-
-/// force immediate event output
-/// ... with or without EV_ERROR
-/// ... use KEVENT_FLAG_ERROR_EVENTS
-/// on syscalls supporting flags
-pub const EV_RECEIPT = 0x0040;
-
-/// disable event after reporting
-pub const EV_DISPATCH = 0x0080;
-
-pub const EVFILT_READ = -1;
-pub const EVFILT_WRITE = -2;
-
-/// attached to aio requests
-pub const EVFILT_AIO = -3;
+// /system/develop/headers/posix/signal.h
-/// attached to vnodes
-pub const EVFILT_VNODE = -4;
+pub const sigset_t = u64;
+pub const empty_sigset: sigset_t = 0;
+pub const filled_sigset = ~@as(sigset_t, 0);
-/// attached to struct proc
-pub const EVFILT_PROC = -5;
+pub const SIG = struct {
+ pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
+ pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
+ pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
-/// attached to struct proc
-pub const EVFILT_SIGNAL = -6;
+ pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(3);
-/// timers
-pub const EVFILT_TIMER = -7;
+ pub const HUP = 1;
+ pub const INT = 2;
+ pub const QUIT = 3;
+ pub const ILL = 4;
+ pub const CHLD = 5;
+ pub const ABRT = 6;
+ pub const IOT = ABRT;
+ pub const PIPE = 7;
+ pub const FPE = 8;
+ pub const KILL = 9;
+ pub const STOP = 10;
+ pub const SEGV = 11;
+ pub const CONT = 12;
+ pub const TSTP = 13;
+ pub const ALRM = 14;
+ pub const TERM = 15;
+ pub const TTIN = 16;
+ pub const TTOU = 17;
+ pub const USR1 = 18;
+ pub const USR2 = 19;
+ pub const WINCH = 20;
+ pub const KILLTHR = 21;
+ pub const TRAP = 22;
+ pub const POLL = 23;
+ pub const PROF = 24;
+ pub const SYS = 25;
+ pub const URG = 26;
+ pub const VTALRM = 27;
+ pub const XCPU = 28;
+ pub const XFSZ = 29;
+ pub const BUS = 30;
+ pub const RESERVED1 = 31;
+ pub const RESERVED2 = 32;
-/// Process descriptors
-pub const EVFILT_PROCDESC = -8;
+ pub const BLOCK = 1;
+ pub const UNBLOCK = 2;
+ pub const SETMASK = 3;
+};
-/// Filesystem events
-pub const EVFILT_FS = -9;
+pub const siginfo_t = extern struct {
+ signo: i32,
+ code: i32,
+ errno: i32,
-pub const EVFILT_LIO = -10;
+ pid: pid_t,
+ uid: uid_t,
+ addr: *allowzero anyopaque,
+};
-/// User events
-pub const EVFILT_USER = -11;
+/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
+pub const Sigaction = extern struct {
+ pub const handler_fn = *align(1) const fn (i32) callconv(.C) void;
+ pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void;
-/// Sendfile events
-pub const EVFILT_SENDFILE = -12;
+ /// signal handler
+ handler: extern union {
+ handler: handler_fn,
+ sigaction: sigaction_fn,
+ },
-pub const EVFILT_EMPTY = -13;
+ /// signal mask to apply
+ mask: sigset_t,
-pub const T = struct {
- pub const CGETA = 0x8000;
- pub const CSETA = 0x8001;
- pub const CSETAF = 0x8002;
- pub const CSETAW = 0x8003;
- pub const CWAITEVENT = 0x8004;
- pub const CSBRK = 0x8005;
- pub const CFLSH = 0x8006;
- pub const CXONC = 0x8007;
- pub const CQUERYCONNECTED = 0x8008;
- pub const CGETBITS = 0x8009;
- pub const CSETDTR = 0x8010;
- pub const CSETRTS = 0x8011;
- pub const IOCGWINSZ = 0x8012;
- pub const IOCSWINSZ = 0x8013;
- pub const CVTIME = 0x8014;
- pub const IOCGPGRP = 0x8015;
- pub const IOCSPGRP = 0x8016;
- pub const IOCSCTTY = 0x8017;
- pub const IOCMGET = 0x8018;
- pub const IOCMSET = 0x8019;
- pub const IOCSBRK = 0x8020;
- pub const IOCCBRK = 0x8021;
- pub const IOCMBIS = 0x8022;
- pub const IOCMBIC = 0x8023;
- pub const IOCGSID = 0x8024;
+ /// see signal options
+ flags: i32,
- pub const FIONREAD = 0xbe000001;
- pub const FIONBIO = 0xbe000000;
+ /// will be passed to the signal handler, BeOS extension
+ userdata: *allowzero anyopaque = undefined,
};
-pub const winsize = extern struct {
- ws_row: u16,
- ws_col: u16,
- ws_xpixel: u16,
- ws_ypixel: u16,
+pub const SA = struct {
+ pub const NOCLDSTOP = 0x01;
+ pub const NOCLDWAIT = 0x02;
+ pub const RESETHAND = 0x04;
+ pub const NODEFER = 0x08;
+ pub const RESTART = 0x10;
+ pub const ONSTACK = 0x20;
+ pub const SIGINFO = 0x40;
+ pub const NOMASK = NODEFER;
+ pub const STACK = ONSTACK;
+ pub const ONESHOT = RESETHAND;
};
-const B_POSIX_ERROR_BASE = -2147454976;
+pub const SS = struct {
+ pub const ONSTACK = 0x1;
+ pub const DISABLE = 0x2;
+};
-pub const E = enum(i32) {
- @"2BIG" = B_POSIX_ERROR_BASE + 1,
- CHILD = B_POSIX_ERROR_BASE + 2,
- DEADLK = B_POSIX_ERROR_BASE + 3,
- FBIG = B_POSIX_ERROR_BASE + 4,
- MLINK = B_POSIX_ERROR_BASE + 5,
- NFILE = B_POSIX_ERROR_BASE + 6,
- NODEV = B_POSIX_ERROR_BASE + 7,
- NOLCK = B_POSIX_ERROR_BASE + 8,
- NOSYS = B_POSIX_ERROR_BASE + 9,
- NOTTY = B_POSIX_ERROR_BASE + 10,
- NXIO = B_POSIX_ERROR_BASE + 11,
- SPIPE = B_POSIX_ERROR_BASE + 12,
- SRCH = B_POSIX_ERROR_BASE + 13,
- FPOS = B_POSIX_ERROR_BASE + 14,
- SIGPARM = B_POSIX_ERROR_BASE + 15,
- DOM = B_POSIX_ERROR_BASE + 16,
- RANGE = B_POSIX_ERROR_BASE + 17,
- PROTOTYPE = B_POSIX_ERROR_BASE + 18,
- PROTONOSUPPORT = B_POSIX_ERROR_BASE + 19,
- PFNOSUPPORT = B_POSIX_ERROR_BASE + 20,
- AFNOSUPPORT = B_POSIX_ERROR_BASE + 21,
- ADDRINUSE = B_POSIX_ERROR_BASE + 22,
- ADDRNOTAVAIL = B_POSIX_ERROR_BASE + 23,
- NETDOWN = B_POSIX_ERROR_BASE + 24,
- NETUNREACH = B_POSIX_ERROR_BASE + 25,
- NETRESET = B_POSIX_ERROR_BASE + 26,
- CONNABORTED = B_POSIX_ERROR_BASE + 27,
- CONNRESET = B_POSIX_ERROR_BASE + 28,
- ISCONN = B_POSIX_ERROR_BASE + 29,
- NOTCONN = B_POSIX_ERROR_BASE + 30,
- SHUTDOWN = B_POSIX_ERROR_BASE + 31,
- CONNREFUSED = B_POSIX_ERROR_BASE + 32,
- HOSTUNREACH = B_POSIX_ERROR_BASE + 33,
- NOPROTOOPT = B_POSIX_ERROR_BASE + 34,
- NOBUFS = B_POSIX_ERROR_BASE + 35,
- INPROGRESS = B_POSIX_ERROR_BASE + 36,
- ALREADY = B_POSIX_ERROR_BASE + 37,
- ILSEQ = B_POSIX_ERROR_BASE + 38,
- NOMSG = B_POSIX_ERROR_BASE + 39,
- STALE = B_POSIX_ERROR_BASE + 40,
- OVERFLOW = B_POSIX_ERROR_BASE + 41,
- MSGSIZE = B_POSIX_ERROR_BASE + 42,
- OPNOTSUPP = B_POSIX_ERROR_BASE + 43,
- NOTSOCK = B_POSIX_ERROR_BASE + 44,
- HOSTDOWN = B_POSIX_ERROR_BASE + 45,
- BADMSG = B_POSIX_ERROR_BASE + 46,
- CANCELED = B_POSIX_ERROR_BASE + 47,
- DESTADDRREQ = B_POSIX_ERROR_BASE + 48,
- DQUOT = B_POSIX_ERROR_BASE + 49,
- IDRM = B_POSIX_ERROR_BASE + 50,
- MULTIHOP = B_POSIX_ERROR_BASE + 51,
- NODATA = B_POSIX_ERROR_BASE + 52,
- NOLINK = B_POSIX_ERROR_BASE + 53,
- NOSR = B_POSIX_ERROR_BASE + 54,
- NOSTR = B_POSIX_ERROR_BASE + 55,
- NOTSUP = B_POSIX_ERROR_BASE + 56,
- PROTO = B_POSIX_ERROR_BASE + 57,
- TIME = B_POSIX_ERROR_BASE + 58,
- TXTBSY = B_POSIX_ERROR_BASE + 59,
- NOATTR = B_POSIX_ERROR_BASE + 60,
- NOTRECOVERABLE = B_POSIX_ERROR_BASE + 61,
- OWNERDEAD = B_POSIX_ERROR_BASE + 62,
+pub const MINSIGSTKSZ = 8192;
+pub const SIGSTKSZ = 16384;
- ACCES = -0x7ffffffe, // Permission denied
- INTR = -0x7ffffff6, // Interrupted system call
- IO = -0x7fffffff, // Input/output error
- BUSY = -0x7ffffff2, // Device busy
- FAULT = -0x7fffecff, // Bad address
- TIMEDOUT = -2147483639, // Operation timed out
- AGAIN = -0x7ffffff5,
- BADF = -0x7fffa000, // Bad file descriptor
- EXIST = -0x7fff9ffe, // File exists
- INVAL = -0x7ffffffb, // Invalid argument
- NAMETOOLONG = -2147459068, // File name too long
- NOENT = -0x7fff9ffd, // No such file or directory
- PERM = -0x7ffffff1, // Operation not permitted
- NOTDIR = -0x7fff9ffb, // Not a directory
- ISDIR = -0x7fff9ff7, // Is a directory
- NOTEMPTY = -2147459066, // Directory not empty
- NOSPC = -0x7fff9ff9, // No space left on device
- ROFS = -0x7fff9ff8, // Read-only filesystem
- MFILE = -0x7fff9ff6, // Too many open files
- XDEV = -0x7fff9ff5, // Cross-device link
- NOEXEC = -0x7fffecfe, // Exec format error
- PIPE = -0x7fff9ff3, // Broken pipe
- NOMEM = -0x80000000, // Cannot allocate memory
- LOOP = -2147459060, // Too many levels of symbolic links
- SUCCESS = 0,
- _,
+pub const stack_t = extern struct {
+ sp: [*]u8,
+ size: isize,
+ flags: i32,
};
-pub const S = struct {
- pub const IFMT = 0o170000;
- pub const IFSOCK = 0o140000;
- pub const IFLNK = 0o120000;
- pub const IFREG = 0o100000;
- pub const IFBLK = 0o060000;
- pub const IFDIR = 0o040000;
- pub const IFCHR = 0o020000;
- pub const IFIFO = 0o010000;
- pub const INDEX_DIR = 0o4000000000;
-
- pub const IUMSK = 0o7777;
- pub const ISUID = 0o4000;
- pub const ISGID = 0o2000;
- pub const ISVTX = 0o1000;
- pub const IRWXU = 0o700;
- pub const IRUSR = 0o400;
- pub const IWUSR = 0o200;
- pub const IXUSR = 0o100;
- pub const IRWXG = 0o070;
- pub const IRGRP = 0o040;
- pub const IWGRP = 0o020;
- pub const IXGRP = 0o010;
- pub const IRWXO = 0o007;
- pub const IROTH = 0o004;
- pub const IWOTH = 0o002;
- pub const IXOTH = 0o001;
+pub const NSIG = 65;
- pub fn ISREG(m: u32) bool {
- return m & IFMT == IFREG;
- }
+pub const mcontext_t = vregs;
- pub fn ISLNK(m: u32) bool {
- return m & IFMT == IFLNK;
- }
+pub const ucontext_t = extern struct {
+ link: ?*ucontext_t,
+ sigmask: sigset_t,
+ stack: stack_t,
+ mcontext: mcontext_t,
+};
- pub fn ISBLK(m: u32) bool {
- return m & IFMT == IFBLK;
- }
+// /system/develop/headers/posix/sys/stat.h
- pub fn ISDIR(m: u32) bool {
- return m & IFMT == IFDIR;
- }
+pub const Stat = extern struct {
+ dev: dev_t,
+ ino: ino_t,
+ mode: mode_t,
+ nlink: nlink_t,
+ uid: uid_t,
+ gid: gid_t,
+ size: off_t,
+ rdev: dev_t,
+ blksize: blksize_t,
+ atim: timespec,
+ mtim: timespec,
+ ctim: timespec,
+ crtim: timespec,
+ type: u32,
+ blocks: blkcnt_t,
- pub fn ISCHR(m: u32) bool {
- return m & IFMT == IFCHR;
+ pub fn atime(self: @This()) timespec {
+ return self.atim;
}
-
- pub fn ISFIFO(m: u32) bool {
- return m & IFMT == IFIFO;
+ pub fn mtime(self: @This()) timespec {
+ return self.mtim;
}
-
- pub fn ISSOCK(m: u32) bool {
- return m & IFMT == IFSOCK;
+ pub fn ctime(self: @This()) timespec {
+ return self.ctim;
}
-
- pub fn ISINDEX(m: u32) bool {
- return m & INDEX_DIR == INDEX_DIR;
+ pub fn birthtime(self: @This()) timespec {
+ return self.crtim;
}
};
-pub const HOST_NAME_MAX = 255;
+// /system/develop/headers/posix/sys/types.h
-pub const addrinfo = extern struct {
- flags: i32,
- family: i32,
- socktype: i32,
- protocol: i32,
- addrlen: socklen_t,
- canonname: ?[*:0]u8,
- addr: ?*sockaddr,
- next: ?*addrinfo,
-};
+pub const blkcnt_t = i64;
+pub const blksize_t = i32;
+pub const fsblkcnt_t = i64;
+pub const fsfilcnt_t = i64;
+pub const off_t = i64;
+pub const ino_t = i64;
+pub const cnt_t = i32;
+pub const dev_t = i32;
+pub const pid_t = i32;
+pub const id_t = i32;
-pub const IPPROTO = struct {
- pub const IP = 0;
- pub const HOPOPTS = 0;
- pub const ICMP = 1;
- pub const IGMP = 2;
- pub const TCP = 6;
- pub const UDP = 17;
- pub const IPV6 = 41;
- pub const ROUTING = 43;
- pub const FRAGMENT = 44;
- pub const ESP = 50;
- pub const AH = 51;
- pub const ICMPV6 = 58;
- pub const NONE = 59;
- pub const DSTOPTS = 60;
- pub const ETHERIP = 97;
- pub const RAW = 255;
- pub const MAX = 256;
-};
+pub const uid_t = u32;
+pub const gid_t = u32;
+pub const mode_t = u32;
+pub const umode_t = u32;
+pub const nlink_t = i32;
-pub const rlimit_resource = enum(c_int) {
- CORE = 0,
- CPU = 1,
- DATA = 2,
- FSIZE = 3,
- NOFILE = 4,
- STACK = 5,
- AS = 6,
- NOVMON = 7,
- _,
-};
+pub const clockid_t = i32;
+pub const timer_t = *opaque {};
-pub const rlim_t = i64;
+// /system/develop/headers/posix/time.h
-pub const RLIM = struct {
- /// No limit
- pub const INFINITY: rlim_t = (1 << 63) - 1;
+pub const clock_t = i32;
+pub const suseconds_t = i32;
+pub const useconds_t = u32;
- pub const SAVED_MAX = INFINITY;
- pub const SAVED_CUR = INFINITY;
-};
+pub const time_t = isize;
-pub const rlimit = extern struct {
- /// Soft limit
- cur: rlim_t,
- /// Hard limit
- max: rlim_t,
-};
+pub const CLOCKS_PER_SEC = 1_000_000;
+pub const CLK_TCK = CLOCKS_PER_SEC;
+pub const TIME_UTC = 1;
-pub const SHUT = struct {
- pub const RD = 0;
- pub const WR = 1;
- pub const RDWR = 2;
+pub const CLOCK = struct {
+ /// system-wide monotonic clock (aka system time)
+ pub const MONOTONIC: clockid_t = 0;
+ /// system-wide real time clock
+ pub const REALTIME: clockid_t = -1;
+ /// clock measuring the used CPU time of the current process
+ pub const PROCESS_CPUTIME_ID: clockid_t = -2;
+ /// clock measuring the used CPU time of the current thread
+ pub const THREAD_CPUTIME_ID: clockid_t = -3;
};
-// TODO fill out if needed
-pub const directory_which = enum(c_int) {
- B_USER_SETTINGS_DIRECTORY = 0xbbe,
+pub const timespec = extern struct {
+ /// seconds
+ tv_sec: time_t,
+ /// and nanoseconds
+ tv_nsec: isize,
+};
- _,
+pub const itimerspec = extern struct {
+ interval: timespec,
+ value: timespec,
};
-pub const MSG_NOSIGNAL = 0x0800;
+// /system/develop/headers/private/system/syscalls.h
+
+pub extern "root" fn _kern_get_current_team() team_id;
+pub extern "root" fn _kern_open_dir(fd: fd_t, path: [*:0]const u8) fd_t;
+pub extern "root" fn _kern_read_dir(fd: fd_t, buffer: [*]u8, bufferSize: usize, maxCount: u32) isize;
+pub extern "root" fn _kern_rewind_dir(fd: fd_t) status_t;
+pub extern "root" fn _kern_read_stat(fd: fd_t, path: [*:0]const u8, traverseLink: bool, stat: *Stat, statSize: usize) status_t;
diff --git a/lib/std/crypto/Certificate.zig b/lib/std/crypto/Certificate.zig
index c3ac3e22aa..b1cc4fc095 100644
--- a/lib/std/crypto/Certificate.zig
+++ b/lib/std/crypto/Certificate.zig
@@ -772,7 +772,7 @@ fn verifyRsa(
Hash.hash(message, &msg_hashed, .{});
switch (modulus.len) {
- inline 128, 256, 512 => |modulus_len| {
+ inline 128, 256, 384, 512 => |modulus_len| {
const ps_len = modulus_len - (hash_der.len + msg_hashed.len) - 3;
const em: [modulus_len]u8 =
[2]u8{ 0, 1 } ++
diff --git a/lib/std/crypto/benchmark.zig b/lib/std/crypto/benchmark.zig
index 7e118afb26..3e979175d8 100644
--- a/lib/std/crypto/benchmark.zig
+++ b/lib/std/crypto/benchmark.zig
@@ -131,7 +131,12 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c
return throughput;
}
-const signatures = [_]Crypto{Crypto{ .ty = crypto.sign.Ed25519, .name = "ed25519" }};
+const signatures = [_]Crypto{
+ Crypto{ .ty = crypto.sign.Ed25519, .name = "ed25519" },
+ Crypto{ .ty = crypto.sign.ecdsa.EcdsaP256Sha256, .name = "ecdsa-p256" },
+ Crypto{ .ty = crypto.sign.ecdsa.EcdsaP384Sha384, .name = "ecdsa-p384" },
+ Crypto{ .ty = crypto.sign.ecdsa.EcdsaSecp256k1Sha256, .name = "ecdsa-secp256k1" },
+};
pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 {
const msg = [_]u8{0} ** 64;
diff --git a/lib/std/crypto/ecdsa.zig b/lib/std/crypto/ecdsa.zig
index 70362470c3..b2751ce20a 100644
--- a/lib/std/crypto/ecdsa.zig
+++ b/lib/std/crypto/ecdsa.zig
@@ -4,6 +4,7 @@ const crypto = std.crypto;
const fmt = std.fmt;
const io = std.io;
const mem = std.mem;
+const sha3 = crypto.hash.sha3;
const testing = std.testing;
const EncodingError = crypto.errors.EncodingError;
@@ -26,7 +27,11 @@ pub const EcdsaSecp256k1Sha256oSha256 = Ecdsa(crypto.ecc.Secp256k1, crypto.hash.
/// Elliptic Curve Digital Signature Algorithm (ECDSA).
pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {
- const Hmac = crypto.auth.hmac.Hmac(Hash);
+ const Prf = switch (Hash) {
+ sha3.Shake128 => sha3.KMac128,
+ sha3.Shake256 => sha3.KMac256,
+ else => crypto.auth.hmac.Hmac(Hash),
+ };
return struct {
/// Length (in bytes) of optional random bytes, for non-deterministic signatures.
@@ -350,22 +355,22 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {
if (noise) |n| @memcpy(m_z, &n);
@memcpy(m_x, &secret_key);
@memcpy(m_h, &h);
- Hmac.create(&k, &m, &k);
- Hmac.create(m_v, m_v, &k);
+ Prf.create(&k, &m, &k);
+ Prf.create(m_v, m_v, &k);
m_i.* = 0x01;
- Hmac.create(&k, &m, &k);
- Hmac.create(m_v, m_v, &k);
+ Prf.create(&k, &m, &k);
+ Prf.create(m_v, m_v, &k);
while (true) {
var t_off: usize = 0;
while (t_off < t.len) : (t_off += m_v.len) {
const t_end = @min(t_off + m_v.len, t.len);
- Hmac.create(m_v, m_v, &k);
+ Prf.create(m_v, m_v, &k);
@memcpy(t[t_off..t_end], m_v[0 .. t_end - t_off]);
}
if (Curve.scalar.Scalar.fromBytes(t, .big)) |s| return s else |_| {}
m_i.* = 0x00;
- Hmac.create(&k, m[0 .. m_v.len + 1], &k);
- Hmac.create(m_v, m_v, &k);
+ Prf.create(&k, m[0 .. m_v.len + 1], &k);
+ Prf.create(m_v, m_v, &k);
}
}
};
diff --git a/lib/std/crypto/keccak_p.zig b/lib/std/crypto/keccak_p.zig
index d04373269e..352172a1f6 100644
--- a/lib/std/crypto/keccak_p.zig
+++ b/lib/std/crypto/keccak_p.zig
@@ -195,7 +195,7 @@ pub fn KeccakF(comptime f: u11) type {
}
/// A generic Keccak-P state.
-pub fn State(comptime f: u11, comptime capacity: u11, comptime delim: u8, comptime rounds: u5) type {
+pub fn State(comptime f: u11, comptime capacity: u11, comptime rounds: u5) type {
comptime assert(f > 200 and f <= 1600 and f % 200 == 0); // invalid state size
comptime assert(capacity < f and capacity % 8 == 0); // invalid capacity size
@@ -207,6 +207,9 @@ pub fn State(comptime f: u11, comptime capacity: u11, comptime delim: u8, compti
/// Keccak does not have any options.
pub const Options = struct {};
+ /// The input delimiter.
+ delim: u8,
+
offset: usize = 0,
buf: [rate]u8 = undefined,
@@ -238,10 +241,28 @@ pub fn State(comptime f: u11, comptime capacity: u11, comptime delim: u8, compti
}
}
+ /// Initialize the state from a slice of bytes.
+ pub fn init(bytes: [f / 8]u8) Self {
+ return .{ .st = KeccakF(f).init(bytes) };
+ }
+
+ /// Permute the state
+ pub fn permute(self: *Self) void {
+ self.st.permuteR(rounds);
+ self.offset = 0;
+ }
+
+ /// Align the input to the rate boundary.
+ pub fn fillBlock(self: *Self) void {
+ self.st.addBytes(self.buf[0..self.offset]);
+ self.st.permuteR(rounds);
+ self.offset = 0;
+ }
+
/// Mark the end of the input.
pub fn pad(self: *Self) void {
self.st.addBytes(self.buf[0..self.offset]);
- self.st.addByte(delim, self.offset);
+ self.st.addByte(self.delim, self.offset);
self.st.addByte(0x80, rate - 1);
self.st.permuteR(rounds);
self.offset = 0;
diff --git a/lib/std/crypto/pcurves/p256/p256_64.zig b/lib/std/crypto/pcurves/p256/p256_64.zig
index e8dbaead33..f3d38ca3e6 100644
--- a/lib/std/crypto/pcurves/p256/p256_64.zig
+++ b/lib/std/crypto/pcurves/p256/p256_64.zig
@@ -73,12 +73,9 @@ pub const NonMontgomeryDomainFieldElement = [4]u64;
/// out1: [0x0 ~> 0xffffffffffffffff]
/// out2: [0x0 ~> 0x1]
inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
- @setRuntimeSafety(mode == .Debug);
-
- const ov1 = @addWithOverflow(arg2, arg3);
- const ov2 = @addWithOverflow(ov1[0], arg1);
- out1.* = ov2[0];
- out2.* = ov1[1] | ov2[1];
+ const x = @as(u128, arg2) +% arg3 +% arg1;
+ out1.* = @truncate(x);
+ out2.* = @truncate(x >> 64);
}
/// The function subborrowxU64 is a subtraction with borrow.
@@ -95,12 +92,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
/// out1: [0x0 ~> 0xffffffffffffffff]
/// out2: [0x0 ~> 0x1]
inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
- @setRuntimeSafety(mode == .Debug);
-
- const ov1 = @subWithOverflow(arg2, arg3);
- const ov2 = @subWithOverflow(ov1[0], arg1);
- out1.* = ov2[0];
- out2.* = ov1[1] | ov2[1];
+ const x = @as(u128, arg2) -% arg3 -% arg1;
+ out1.* = @truncate(x);
+ out2.* = @truncate(x >> 64);
}
/// The function mulxU64 is a multiplication, returning the full double-width result.
diff --git a/lib/std/crypto/pcurves/p256/p256_scalar_64.zig b/lib/std/crypto/pcurves/p256/p256_scalar_64.zig
index 152c2b8787..736a3ea8b7 100644
--- a/lib/std/crypto/pcurves/p256/p256_scalar_64.zig
+++ b/lib/std/crypto/pcurves/p256/p256_scalar_64.zig
@@ -73,12 +73,9 @@ pub const NonMontgomeryDomainFieldElement = [4]u64;
/// out1: [0x0 ~> 0xffffffffffffffff]
/// out2: [0x0 ~> 0x1]
inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
- @setRuntimeSafety(mode == .Debug);
-
- const ov1 = @addWithOverflow(arg2, arg3);
- const ov2 = @addWithOverflow(ov1[0], arg1);
- out1.* = ov2[0];
- out2.* = ov1[1] | ov2[1];
+ const x = @as(u128, arg2) +% arg3 +% arg1;
+ out1.* = @truncate(x);
+ out2.* = @truncate(x >> 64);
}
/// The function subborrowxU64 is a subtraction with borrow.
@@ -95,12 +92,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
/// out1: [0x0 ~> 0xffffffffffffffff]
/// out2: [0x0 ~> 0x1]
inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
- @setRuntimeSafety(mode == .Debug);
-
- const ov1 = @subWithOverflow(arg2, arg3);
- const ov2 = @subWithOverflow(ov1[0], arg1);
- out1.* = ov2[0];
- out2.* = ov1[1] | ov2[1];
+ const x = @as(u128, arg2) -% arg3 -% arg1;
+ out1.* = @truncate(x);
+ out2.* = @truncate(x >> 64);
}
/// The function mulxU64 is a multiplication, returning the full double-width result.
diff --git a/lib/std/crypto/pcurves/p384/p384_64.zig b/lib/std/crypto/pcurves/p384/p384_64.zig
index f25a7d65b5..e1419e7c81 100644
--- a/lib/std/crypto/pcurves/p384/p384_64.zig
+++ b/lib/std/crypto/pcurves/p384/p384_64.zig
@@ -42,12 +42,9 @@ pub const NonMontgomeryDomainFieldElement = [6]u64;
/// out1: [0x0 ~> 0xffffffffffffffff]
/// out2: [0x0 ~> 0x1]
inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
- @setRuntimeSafety(mode == .Debug);
-
- const ov1 = @addWithOverflow(arg2, arg3);
- const ov2 = @addWithOverflow(ov1[0], arg1);
- out1.* = ov2[0];
- out2.* = ov1[1] | ov2[1];
+ const x = @as(u128, arg2) +% arg3 +% arg1;
+ out1.* = @truncate(x);
+ out2.* = @truncate(x >> 64);
}
/// The function subborrowxU64 is a subtraction with borrow.
@@ -64,12 +61,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
/// out1: [0x0 ~> 0xffffffffffffffff]
/// out2: [0x0 ~> 0x1]
inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
- @setRuntimeSafety(mode == .Debug);
-
- const ov1 = @subWithOverflow(arg2, arg3);
- const ov2 = @subWithOverflow(ov1[0], arg1);
- out1.* = ov2[0];
- out2.* = ov1[1] | ov2[1];
+ const x = @as(u128, arg2) -% arg3 -% arg1;
+ out1.* = @truncate(x);
+ out2.* = @truncate(x >> 64);
}
/// The function mulxU64 is a multiplication, returning the full double-width result.
diff --git a/lib/std/crypto/pcurves/p384/p384_scalar_64.zig b/lib/std/crypto/pcurves/p384/p384_scalar_64.zig
index fc787ba7b9..68a0a0ca2f 100644
--- a/lib/std/crypto/pcurves/p384/p384_scalar_64.zig
+++ b/lib/std/crypto/pcurves/p384/p384_scalar_64.zig
@@ -42,12 +42,9 @@ pub const NonMontgomeryDomainFieldElement = [6]u64;
/// out1: [0x0 ~> 0xffffffffffffffff]
/// out2: [0x0 ~> 0x1]
inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
- @setRuntimeSafety(mode == .Debug);
-
- const ov1 = @addWithOverflow(arg2, arg3);
- const ov2 = @addWithOverflow(ov1[0], arg1);
- out1.* = ov2[0];
- out2.* = ov1[1] | ov2[1];
+ const x = @as(u128, arg2) +% arg3 +% arg1;
+ out1.* = @truncate(x);
+ out2.* = @truncate(x >> 64);
}
/// The function subborrowxU64 is a subtraction with borrow.
@@ -64,12 +61,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
/// out1: [0x0 ~> 0xffffffffffffffff]
/// out2: [0x0 ~> 0x1]
inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
- @setRuntimeSafety(mode == .Debug);
-
- const ov1 = @subWithOverflow(arg2, arg3);
- const ov2 = @subWithOverflow(ov1[0], arg1);
- out1.* = ov2[0];
- out2.* = ov1[1] | ov2[1];
+ const x = @as(u128, arg2) -% arg3 -% arg1;
+ out1.* = @truncate(x);
+ out2.* = @truncate(x >> 64);
}
/// The function mulxU64 is a multiplication, returning the full double-width result.
diff --git a/lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig b/lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig
index ae3e97c619..1c69b90eea 100644
--- a/lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig
+++ b/lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig
@@ -42,12 +42,9 @@ pub const NonMontgomeryDomainFieldElement = [4]u64;
/// out1: [0x0 ~> 0xffffffffffffffff]
/// out2: [0x0 ~> 0x1]
inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
- @setRuntimeSafety(mode == .Debug);
-
- const ov1 = @addWithOverflow(arg2, arg3);
- const ov2 = @addWithOverflow(ov1[0], arg1);
- out1.* = ov2[0];
- out2.* = ov1[1] | ov2[1];
+ const x = @as(u128, arg2) +% arg3 +% arg1;
+ out1.* = @truncate(x);
+ out2.* = @truncate(x >> 64);
}
/// The function subborrowxU64 is a subtraction with borrow.
@@ -64,12 +61,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
/// out1: [0x0 ~> 0xffffffffffffffff]
/// out2: [0x0 ~> 0x1]
inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
- @setRuntimeSafety(mode == .Debug);
-
- const ov1 = @subWithOverflow(arg2, arg3);
- const ov2 = @subWithOverflow(ov1[0], arg1);
- out1.* = ov2[0];
- out2.* = ov1[1] | ov2[1];
+ const x = @as(u128, arg2) -% arg3 -% arg1;
+ out1.* = @truncate(x);
+ out2.* = @truncate(x >> 64);
}
/// The function mulxU64 is a multiplication, returning the full double-width result.
diff --git a/lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig b/lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig
index 12c833bb33..97bf5f0a45 100644
--- a/lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig
+++ b/lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig
@@ -42,12 +42,9 @@ pub const NonMontgomeryDomainFieldElement = [4]u64;
/// out1: [0x0 ~> 0xffffffffffffffff]
/// out2: [0x0 ~> 0x1]
inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
- @setRuntimeSafety(mode == .Debug);
-
- const ov1 = @addWithOverflow(arg2, arg3);
- const ov2 = @addWithOverflow(ov1[0], arg1);
- out1.* = ov2[0];
- out2.* = ov1[1] | ov2[1];
+ const x = @as(u128, arg2) +% arg3 +% arg1;
+ out1.* = @truncate(x);
+ out2.* = @truncate(x >> 64);
}
/// The function subborrowxU64 is a subtraction with borrow.
@@ -64,12 +61,9 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo
/// out1: [0x0 ~> 0xffffffffffffffff]
/// out2: [0x0 ~> 0x1]
inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void {
- @setRuntimeSafety(mode == .Debug);
-
- const ov1 = @subWithOverflow(arg2, arg3);
- const ov2 = @subWithOverflow(ov1[0], arg1);
- out1.* = ov2[0];
- out2.* = ov1[1] | ov2[1];
+ const x = @as(u128, arg2) -% arg3 -% arg1;
+ out1.* = @truncate(x);
+ out2.* = @truncate(x >> 64);
}
/// The function mulxU64 is a multiplication, returning the full double-width result.
diff --git a/lib/std/crypto/sha3.zig b/lib/std/crypto/sha3.zig
index 8fa76a48bf..e75dcb7b79 100644
--- a/lib/std/crypto/sha3.zig
+++ b/lib/std/crypto/sha3.zig
@@ -18,11 +18,20 @@ pub const Keccak_512 = @compileError("Deprecated: use `Keccak512` instead");
pub const Shake128 = Shake(128);
pub const Shake256 = Shake(256);
+pub const CShake128 = CShake(128, null);
+pub const CShake256 = CShake(256, null);
+
+pub const KMac128 = KMac(128);
+pub const KMac256 = KMac(256);
+
+pub const TupleHash128 = TupleHash(128);
+pub const TupleHash256 = TupleHash(256);
+
/// TurboSHAKE128 is a XOF (a secure hash function with a variable output length), with a 128 bit security level.
/// It is based on the same permutation as SHA3 and SHAKE128, but which much higher performance.
/// The delimiter is 0x1f by default, but can be changed for context-separation.
/// For a protocol that uses both KangarooTwelve and TurboSHAKE128, it is recommended to avoid using 0x06, 0x07 or 0x0b for the delimiter.
-pub fn TurboShake128(comptime delim: ?u7) type {
+pub fn TurboShake128(delim: ?u7) type {
return TurboShake(128, delim);
}
@@ -34,27 +43,26 @@ pub fn TurboShake256(comptime delim: ?u7) type {
}
/// A generic Keccak hash function.
-pub fn Keccak(comptime f: u11, comptime output_bits: u11, comptime delim: u8, comptime rounds: u5) type {
+pub fn Keccak(comptime f: u11, comptime output_bits: u11, comptime default_delim: u8, comptime rounds: u5) type {
comptime assert(output_bits > 0 and output_bits * 2 < f and output_bits % 8 == 0); // invalid output length
- const State = KeccakState(f, output_bits * 2, delim, rounds);
+ const State = KeccakState(f, output_bits * 2, rounds);
return struct {
const Self = @This();
- st: State = .{},
+ st: State,
/// The output length, in bytes.
pub const digest_length = output_bits / 8;
/// The block length, or rate, in bytes.
pub const block_length = State.rate;
- /// Keccak does not have any options.
- pub const Options = struct {};
+ /// The delimiter can be overwritten in the options.
+ pub const Options = struct { delim: u8 = default_delim };
/// Initialize a Keccak hash function.
pub fn init(options: Options) Self {
- _ = options;
- return Self{};
+ return Self{ .st = .{ .delim = options.delim } };
}
/// Hash a slice of bytes.
@@ -105,29 +113,28 @@ pub fn TurboShake(comptime security_level: u11, comptime delim: ?u7) type {
return ShakeLike(security_level, d, 12);
}
-fn ShakeLike(comptime security_level: u11, comptime delim: u8, comptime rounds: u5) type {
+fn ShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime rounds: u5) type {
const f = 1600;
- const State = KeccakState(f, security_level * 2, delim, rounds);
+ const State = KeccakState(f, security_level * 2, rounds);
return struct {
const Self = @This();
- st: State = .{},
+ st: State,
buf: [State.rate]u8 = undefined,
offset: usize = 0,
padded: bool = false,
/// The recommended output length, in bytes.
- pub const digest_length = security_level / 2;
+ pub const digest_length = security_level / 8 * 2;
/// The block length, or rate, in bytes.
pub const block_length = State.rate;
- /// Keccak does not have any options.
- pub const Options = struct {};
+ /// The delimiter can be overwritten in the options.
+ pub const Options = struct { delim: u8 = default_delim };
/// Initialize a SHAKE extensible hash function.
pub fn init(options: Options) Self {
- _ = options;
- return Self{};
+ return Self{ .st = .{ .delim = options.delim } };
}
/// Hash a slice of bytes.
@@ -182,6 +189,11 @@ fn ShakeLike(comptime security_level: u11, comptime delim: u8, comptime rounds:
self.st.st.clear(0, State.rate);
}
+ /// Align the input to a block boundary.
+ pub fn fillBlock(self: *Self) void {
+ self.st.fillBlock();
+ }
+
pub const Error = error{};
pub const Writer = std.io.Writer(*Self, Error, write);
@@ -196,6 +208,338 @@ fn ShakeLike(comptime security_level: u11, comptime delim: u8, comptime rounds:
};
}
+/// The cSHAKE extendable output hash function.
+/// cSHAKE is similar to SHAKE, but in addition to the input message, it also takes an optional context (aka customization string).
+pub fn CShake(comptime security_level: u11, comptime fname: ?[]const u8) type {
+ return CShakeLike(security_level, 0x04, 24, fname);
+}
+
+fn CShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime rounds: u5, comptime fname: ?[]const u8) type {
+ return struct {
+ const Shaker = ShakeLike(security_level, default_delim, rounds);
+ shaker: Shaker,
+
+ /// The recommended output length, in bytes.
+ pub const digest_length = Shaker.digest_length;
+ /// The block length, or rate, in bytes.
+ pub const block_length = Shaker.block_length;
+
+ /// cSHAKE options can include a context string.
+ pub const Options = struct { context: ?[]const u8 = null };
+
+ const Self = @This();
+
+ /// Initialize a SHAKE extensible hash function.
+ pub fn init(options: Options) Self {
+ if (fname == null and options.context == null) {
+ return Self{ .shaker = Shaker.init(.{ .delim = 0x1f }) };
+ }
+ var shaker = Shaker.init(.{});
+ comptime assert(Shaker.block_length % 8 == 0);
+ const encoded_rate_len = NistLengthEncoding.encode(.left, block_length / 8);
+ shaker.update(encoded_rate_len.slice());
+ const encoded_zero = comptime NistLengthEncoding.encode(.left, 0);
+ if (fname) |name| {
+ const encoded_fname_len = comptime NistLengthEncoding.encode(.left, name.len);
+ const encoded_fname = comptime encoded_fname_len.slice() ++ name;
+ shaker.update(encoded_fname);
+ } else {
+ shaker.update(encoded_zero.slice());
+ }
+ if (options.context) |context| {
+ const encoded_context_len = NistLengthEncoding.encode(.left, context.len);
+ shaker.update(encoded_context_len.slice());
+ shaker.update(context);
+ } else {
+ shaker.update(encoded_zero.slice());
+ }
+ shaker.st.fillBlock();
+ return Self{ .shaker = shaker };
+ }
+
+ /// Hash a slice of bytes.
+ /// `out` can be any length.
+ pub fn hash(bytes: []const u8, out: []u8, options: Options) void {
+ var st = Self.init(options);
+ st.update(bytes);
+ st.squeeze(out);
+ }
+
+ /// Absorb a slice of bytes into the state.
+ pub fn update(self: *Self, bytes: []const u8) void {
+ self.shaker.update(bytes);
+ }
+
+ /// Squeeze a slice of bytes from the state.
+ /// `out` can be any length, and the function can be called multiple times.
+ pub fn squeeze(self: *Self, out: []u8) void {
+ self.shaker.squeeze(out);
+ }
+
+ /// Return the hash of the absorbed bytes.
+ /// `out` can be of any length, but the function must not be called multiple times (use `squeeze` for that purpose instead).
+ pub fn final(self: *Self, out: []u8) void {
+ self.shaker.final(out);
+ }
+
+ /// Align the input to a block boundary.
+ pub fn fillBlock(self: *Self) void {
+ self.shaker.fillBlock();
+ }
+
+ pub const Error = error{};
+ pub const Writer = std.io.Writer(*Self, Error, write);
+
+ fn write(self: *Self, bytes: []const u8) Error!usize {
+ self.update(bytes);
+ return bytes.len;
+ }
+
+ pub fn writer(self: *Self) Writer {
+ return .{ .context = self };
+ }
+ };
+}
+
+/// The KMAC extendable output authentication function.
+/// KMAC is a keyed version of the cSHAKE function, with an optional context.
+/// It can be used as an SHA-3 based alternative to HMAC, as well as a generic keyed XoF (extendable output function).
+pub fn KMac(comptime security_level: u11) type {
+ return KMacLike(security_level, 0x04, 24);
+}
+
+fn KMacLike(comptime security_level: u11, comptime default_delim: u8, comptime rounds: u5) type {
+ const CShaker = CShakeLike(security_level, default_delim, rounds, "KMAC");
+
+ return struct {
+ const Self = @This();
+
+ /// The recommended output length, in bytes.
+ pub const mac_length = CShaker.digest_length;
+ /// The minimum output length, in bytes.
+ pub const mac_length_min = 4;
+ /// The recommended key length, in bytes.
+ pub const key_length = security_level / 8;
+ /// The minimum key length, in bytes.
+ pub const key_length_min = 0;
+ /// The block length, or rate, in bytes.
+ pub const block_length = CShaker.block_length;
+
+ cshaker: CShaker,
+ xof_mode: bool = false,
+
+ /// KMAC options can include a context string.
+ pub const Options = struct {
+ context: ?[]const u8 = null,
+ };
+
+ /// Initialize a state for the KMAC function, with an optional context and an arbitrary-long key.
+ /// If the context and key are going to be reused, the structure can be initialized once, and cloned for each message.
+ /// This is more efficient than reinitializing the state for each message at the cost of a small amount of memory.
+ pub fn initWithOptions(key: []const u8, options: Options) Self {
+ var cshaker = CShaker.init(.{ .context = options.context });
+ const encoded_rate_len = NistLengthEncoding.encode(.left, block_length / 8);
+ cshaker.update(encoded_rate_len.slice());
+ const encoded_key_len = NistLengthEncoding.encode(.left, key.len);
+ cshaker.update(encoded_key_len.slice());
+ cshaker.update(key);
+ cshaker.fillBlock();
+ return Self{
+ .cshaker = cshaker,
+ };
+ }
+
+ /// Initialize a state for the KMAC function.
+ /// If the context and key are going to be reused, the structure can be initialized once, and cloned for each message.
+ /// This is more efficient than reinitializing the state for each message at the cost of a small amount of memory.
+ pub fn init(key: []const u8) Self {
+ return initWithOptions(key, .{});
+ }
+
+ /// Add data to the state.
+ pub fn update(self: *Self, b: []const u8) void {
+ self.cshaker.update(b);
+ }
+
+ /// Return an authentication tag for the current state.
+ pub fn final(self: *Self, out: []u8) void {
+ const encoded_out_len = NistLengthEncoding.encode(.right, out.len);
+ self.update(encoded_out_len.slice());
+ self.cshaker.final(out);
+ }
+
+ /// Squeeze a slice of bytes from the state.
+ /// `out` can be any length, and the function can be called multiple times.
+ pub fn squeeze(self: *Self, out: []u8) void {
+ if (!self.xof_mode) {
+ const encoded_out_len = comptime NistLengthEncoding.encode(.right, 0);
+ self.update(encoded_out_len.slice());
+ self.xof_mode = true;
+ }
+ self.cshaker.squeeze(out);
+ }
+
+ /// Return an authentication tag for a message and a key, with an optional context.
+ pub fn createWithOptions(out: []u8, msg: []const u8, key: []const u8, options: Options) void {
+ var ctx = Self.initWithOptions(key, options);
+ ctx.update(msg);
+ ctx.final(out);
+ }
+
+ /// Return an authentication tag for a message and a key.
+ pub fn create(out: []u8, msg: []const u8, key: []const u8) void {
+ var ctx = Self.init(key);
+ ctx.update(msg);
+ ctx.final(out);
+ }
+
+ pub const Error = error{};
+ pub const Writer = std.io.Writer(*Self, Error, write);
+
+ fn write(self: *Self, bytes: []const u8) Error!usize {
+ self.update(bytes);
+ return bytes.len;
+ }
+
+ pub fn writer(self: *Self) Writer {
+ return .{ .context = self };
+ }
+ };
+}
+
+/// The TupleHash extendable output hash function, with domain-separated inputs.
+/// TupleHash is a secure hash function with a variable output length, based on the cSHAKE function.
+/// It is designed for unambiguously hashing tuples of data.
+///
+/// With most hash functions, calling `update("A")` followed by `update("B")`is identical to `update("AB")`.
+/// With TupleHash, this is not the case: `update("A"); update("B")` is different from `update("AB")`.
+///
+/// Any number of inputs can be hashed, and the output depends on individual inputs and their order.
+pub fn TupleHash(comptime security_level: u11) type {
+ return TupleHashLike(security_level, 0x04, 24);
+}
+
+fn TupleHashLike(comptime security_level: u11, comptime default_delim: u8, comptime rounds: u5) type {
+ const CShaker = CShakeLike(security_level, default_delim, rounds, "TupleHash");
+
+ return struct {
+ const Self = @This();
+
+ /// The output length, in bytes.
+ pub const digest_length = CShaker.digest_length;
+ /// The block length, or rate, in bytes.
+ pub const block_length = CShaker.block_length;
+
+ cshaker: CShaker,
+ xof_mode: bool = false,
+
+ /// TupleHash options can include a context string.
+ pub const Options = struct {
+ context: ?[]const u8 = null,
+ };
+
+ /// Initialize a state for the TupleHash function, with an optional context.
+ /// If the context is going to be reused, the structure can be initialized once, and cloned for each message.
+ /// This is more efficient than reinitializing the state for each message at the cost of a small amount of memory.
+ ///
+ /// A key can be optionally added to the context to create a keyed TupleHash function, similar to KMAC.
+ pub fn initWithOptions(options: Options) Self {
+ const cshaker = CShaker.init(.{ .context = options.context });
+ return Self{
+ .cshaker = cshaker,
+ };
+ }
+
+ /// Initialize a state for the MAC function.
+ pub fn init() Self {
+ return initWithOptions(.{});
+ }
+
+ /// Add data to the state, separated from previous updates.
+ pub fn update(self: *Self, b: []const u8) void {
+ const encoded_b_len = NistLengthEncoding.encode(.left, b.len);
+ self.cshaker.update(encoded_b_len.slice());
+ self.cshaker.update(b);
+ }
+
+ /// Return an authentication tag for the current state.
+ pub fn final(self: *Self, out: []u8) void {
+ const encoded_out_len = NistLengthEncoding.encode(.right, out.len);
+ self.cshaker.update(encoded_out_len.slice());
+ self.cshaker.final(out);
+ }
+
+ /// Align the input to a block boundary.
+ pub fn fillBlock(self: *Self) void {
+ self.cshaker.fillBlock();
+ }
+
+ /// Squeeze a slice of bytes from the state.
+ /// `out` can be any length, and the function can be called multiple times.
+ pub fn squeeze(self: *Self, out: []u8) void {
+ if (!self.xof_mode) {
+ const encoded_out_len = comptime NistLengthEncoding.encode(.right, 0);
+ self.update(encoded_out_len.slice());
+ self.xof_mode = true;
+ }
+ self.cshaker.squeeze(out);
+ }
+
+ pub const Error = error{};
+ pub const Writer = std.io.Writer(*Self, Error, write);
+
+ fn write(self: *Self, bytes: []const u8) Error!usize {
+ self.update(bytes);
+ return bytes.len;
+ }
+
+ pub fn writer(self: *Self) Writer {
+ return .{ .context = self };
+ }
+ };
+}
+
+/// The NIST SP 800-185 encoded length format.
+pub const NistLengthEncoding = enum {
+ left,
+ right,
+
+ /// A length encoded according to NIST SP 800-185.
+ pub const Length = struct {
+ /// The size of the encoded value, in bytes.
+ len: usize = 0,
+ /// A buffer to store the encoded length.
+ buf: [@sizeOf(usize) + 1]u8 = undefined,
+
+ /// Return the encoded length as a slice.
+ pub fn slice(self: *const Length) []const u8 {
+ return self.buf[0..self.len];
+ }
+ };
+
+ /// Encode a length according to NIST SP 800-185.
+ pub fn encode(comptime encoding: NistLengthEncoding, len: usize) Length {
+ const len_bits = @bitSizeOf(@TypeOf(len)) - @clz(len) + 3;
+ const len_bytes = std.math.divCeil(usize, len_bits, 8) catch unreachable;
+
+ var res = Length{ .len = len_bytes + 1 };
+ if (encoding == .right) {
+ res.buf[len_bytes] = @intCast(len_bytes);
+ }
+ const end = if (encoding == .right) len_bytes - 1 else len_bytes;
+ res.buf[end] = @truncate(len << 3);
+ var len_ = len >> 5;
+ for (1..len_bytes) |i| {
+ res.buf[end - i] = @truncate(len_);
+ len_ >>= 8;
+ }
+ if (encoding == .left) {
+ res.buf[0] = @intCast(len_bytes);
+ }
+ return res;
+ }
+};
+
const htest = @import("test.zig");
test "sha3-224 single" {
@@ -397,3 +741,88 @@ test "SHA-3 with streaming" {
h.final(&out);
try htest.assertEqual("5780048dfa381a1d01c747906e4a08711dd34fd712ecd7c6801dd2b38fd81a89", &out);
}
+
+test "cSHAKE-128 with no context nor function name" {
+ var out: [32]u8 = undefined;
+ CShake128.hash("hello123", &out, .{});
+ try htest.assertEqual("1b85861510bc4d8e467d6f8a92270533cbaa7ba5e06c2d2a502854bac468b8b9", &out);
+}
+
+test "cSHAKE-128 with context" {
+ var out: [32]u8 = undefined;
+ CShake128.hash("hello123", &out, .{ .context = "custom" });
+ try htest.assertEqual("7509fa13a6bd3e38ad5c6fac042142c233996e40ebffc86c276f108b3b19cc6a", &out);
+}
+
+test "cSHAKE-128 with context and function" {
+ var out: [32]u8 = undefined;
+ CShake(128, "function").hash("hello123", &out, .{ .context = "custom" });
+ try htest.assertEqual("ad7f4d7db2d96587fcd5047c65d37c368f5366e3afac60bb9b66b0bb95dfb675", &out);
+}
+
+test "cSHAKE-256" {
+ var out: [32]u8 = undefined;
+ CShake256.hash("hello123", &out, .{ .context = "custom" });
+ try htest.assertEqual("dabe027eb1a6cbe3a0542d0560eb4e6b39146dd72ae1bf89c970a61bd93b1813", &out);
+}
+
+test "KMAC-128 with empty key and message" {
+ var out: [KMac128.mac_length]u8 = undefined;
+ const key = "";
+ KMac128.create(&out, "", key);
+ try htest.assertEqual("5c135c615152fb4d9784dd1155f9b6034e013fd77165c327dfa4d36701983ef7", &out);
+}
+
+test "KMAC-128" {
+ var out: [KMac128.mac_length]u8 = undefined;
+ const key = "A KMAC secret key";
+ KMac128.create(&out, "hello123", key);
+ try htest.assertEqual("1fa1c0d761129a83f9a4299ca137674de8373a3cc437799ae4c129e651627f8e", &out);
+}
+
+test "KMAC-128 with a customization string" {
+ var out: [KMac128.mac_length]u8 = undefined;
+ const key = "A KMAC secret key";
+ KMac128.createWithOptions(&out, "hello123", key, .{ .context = "custom" });
+ try htest.assertEqual("c58c6d42dc00a27dfa8e7e08f8c9307cecb5d662ddb11b6c36057fc2e0e068ba", &out);
+}
+
+test "KMACXOF-128" {
+ const key = "A KMAC secret key";
+ var xof = KMac128.init(key);
+ xof.update("hello123");
+ var out: [50]u8 = undefined;
+ xof.squeeze(&out);
+ try htest.assertEqual("628c2fb870d294b3673ac82d9f0d651aae6a5bb8084ea8cd8343cb888d075b9053173200a71f301141069c3c0322527981f7", &out);
+ xof.squeeze(&out);
+ try htest.assertEqual("7b638e178cfdac5727a4ea7694efaa967a65a1d0034501855acff506b4158d187d5a18d668e67b43f2abf61144b20ed4c09f", &out);
+}
+
+test "KMACXOF-256" {
+ const key = "A KMAC secret key";
+ var xof = KMac256.init(key);
+ xof.update("hello123");
+ var out: [50]u8 = undefined;
+ xof.squeeze(&out);
+ try htest.assertEqual("23fc644bc2655ba6fde7b7c11f2804f22e8d8c6bd7db856268bf3370ce2362703f6c7e91916a1b8c116e60edfbcb25613054", &out);
+ xof.squeeze(&out);
+ try htest.assertEqual("ff97251020ff255ee65a1c1f5f78ebe904f61211c39f973f82fbce2b196b9f51c2cb12afe51549a0f1eaf7954e657ba11af3", &out);
+}
+
+test "TupleHash-128" {
+ var st = TupleHash128.init();
+ st.update("hello");
+ st.update("123");
+ var out: [32]u8 = undefined;
+ st.final(&out);
+ try htest.assertEqual("3938d49ade8ec0f0c305ac63497b2d2e8b2f650714f9667cc41816b1c11ffd20", &out);
+}
+
+test "TupleHash-256" {
+ var st = TupleHash256.init();
+ st.update("hello");
+ st.update("123");
+ var out: [64]u8 = undefined;
+ st.final(&out);
+ try htest.assertEqual("2dca563c2882f2ba4f46a441a4c5e13fb97150d1436fe99c7e4e43a2d20d0f1cd3d38483bde4a966930606dfa6c61c4ca6400aeedfb474d1bf0d7f6a70968289", &out);
+}
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
index d1d6201b80..eaa5ca9ff7 100644
--- a/lib/std/debug.zig
+++ b/lib/std/debug.zig
@@ -406,7 +406,7 @@ pub fn assert(ok: bool) void {
pub fn panic(comptime format: []const u8, args: anytype) noreturn {
@setCold(true);
- panicExtra(null, null, format, args);
+ panicExtra(@errorReturnTrace(), @returnAddress(), format, args);
}
/// `panicExtra` is useful when you want to print out an `@errorReturnTrace`
@@ -661,7 +661,7 @@ pub const StackIterator = struct {
fn isValidMemory(address: usize) bool {
// We are unable to determine validity of memory for freestanding targets
- if (native_os == .freestanding) return true;
+ if (native_os == .freestanding or native_os == .uefi) return true;
const aligned_address = address & ~@as(usize, @intCast((mem.page_size - 1)));
if (aligned_address == 0) return false;
diff --git a/lib/std/fs/Dir.zig b/lib/std/fs/Dir.zig
index 74d91239f8..b6222f942f 100644
--- a/lib/std/fs/Dir.zig
+++ b/lib/std/fs/Dir.zig
@@ -220,71 +220,83 @@ pub const Iterator = switch (native_os) {
},
.haiku => struct {
dir: Dir,
- buf: [1024]u8, // TODO align(@alignOf(posix.dirent64)),
+ buf: [@sizeOf(DirEnt) + posix.PATH_MAX]u8 align(@alignOf(DirEnt)),
+ offset: usize,
index: usize,
end_index: usize,
first_iter: bool,
const Self = @This();
+ const DirEnt = posix.system.DirEnt;
pub const Error = IteratorError;
/// Memory such as file names referenced in this returned entry becomes invalid
/// with subsequent calls to `next`, as well as when this `Dir` is deinitialized.
pub fn next(self: *Self) Error!?Entry {
- start_over: while (true) {
- // TODO: find a better max
- const HAIKU_MAX_COUNT = 10000;
+ while (true) {
if (self.index >= self.end_index) {
if (self.first_iter) {
- posix.lseek_SET(self.dir.fd, 0) catch unreachable; // EBADF here likely means that the Dir was not opened with iteration permissions
+ switch (@as(posix.E, @enumFromInt(posix.system._kern_rewind_dir(self.dir.fd)))) {
+ .SUCCESS => {},
+ .BADF => unreachable, // Dir is invalid
+ .FAULT => unreachable,
+ .NOTDIR => unreachable,
+ .INVAL => unreachable,
+ .ACCES => return error.AccessDenied,
+ .PERM => return error.AccessDenied,
+ else => |err| return posix.unexpectedErrno(err),
+ }
self.first_iter = false;
}
const rc = posix.system._kern_read_dir(
self.dir.fd,
&self.buf,
self.buf.len,
- HAIKU_MAX_COUNT,
+ self.buf.len / @sizeOf(DirEnt),
);
if (rc == 0) return null;
if (rc < 0) {
- switch (posix.errno(rc)) {
- .BADF => unreachable, // Dir is invalid or was opened without iteration ability
+ switch (@as(posix.E, @enumFromInt(rc))) {
+ .BADF => unreachable, // Dir is invalid
.FAULT => unreachable,
.NOTDIR => unreachable,
.INVAL => unreachable,
+ .OVERFLOW => unreachable,
+ .ACCES => return error.AccessDenied,
+ .PERM => return error.AccessDenied,
else => |err| return posix.unexpectedErrno(err),
}
}
+ self.offset = 0;
self.index = 0;
- self.end_index = @as(usize, @intCast(rc));
- }
- const haiku_entry = @as(*align(1) posix.system.dirent, @ptrCast(&self.buf[self.index]));
- const next_index = self.index + haiku_entry.reclen;
- self.index = next_index;
- const name = mem.sliceTo(@as([*:0]u8, @ptrCast(&haiku_entry.name)), 0);
-
- if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..") or (haiku_entry.ino == 0)) {
- continue :start_over;
+ self.end_index = @intCast(rc);
}
+ const dirent: *DirEnt = @ptrCast(@alignCast(&self.buf[self.offset]));
+ self.offset += dirent.reclen;
+ self.index += 1;
+ const name = mem.span(dirent.getName());
+ if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..") or dirent.ino == 0) continue;
var stat_info: posix.Stat = undefined;
- const rc = posix.system._kern_read_stat(
+ switch (@as(posix.E, @enumFromInt(posix.system._kern_read_stat(
self.dir.fd,
- &haiku_entry.name,
+ name,
false,
&stat_info,
0,
- );
- if (rc != 0) {
- switch (posix.errno(rc)) {
- .SUCCESS => {},
- .BADF => unreachable, // Dir is invalid or was opened without iteration ability
- .FAULT => unreachable,
- .NOTDIR => unreachable,
- .INVAL => unreachable,
- else => |err| return posix.unexpectedErrno(err),
- }
+ )))) {
+ .SUCCESS => {},
+ .INVAL => unreachable,
+ .BADF => unreachable, // Dir is invalid
+ .NOMEM => return error.SystemResources,
+ .ACCES => return error.AccessDenied,
+ .PERM => return error.AccessDenied,
+ .FAULT => unreachable,
+ .NAMETOOLONG => unreachable,
+ .LOOP => unreachable,
+ .NOENT => continue,
+ else => |err| return posix.unexpectedErrno(err),
}
const statmode = stat_info.mode & posix.S.IFMT;
@@ -315,7 +327,7 @@ pub const Iterator = switch (native_os) {
dir: Dir,
// The if guard is solely there to prevent compile errors from missing `linux.dirent64`
// definition when compiling for other OSes. It doesn't do anything when compiling for Linux.
- buf: [1024]u8 align(if (native_os != .linux) 1 else @alignOf(linux.dirent64)),
+ buf: [1024]u8 align(@alignOf(linux.dirent64)),
index: usize,
end_index: usize,
first_iter: bool,
@@ -599,8 +611,16 @@ fn iterateImpl(self: Dir, first_iter_start_value: bool) Iterator {
.buf = undefined,
.first_iter = first_iter_start_value,
},
- .linux, .haiku => return Iterator{
+ .linux => return Iterator{
+ .dir = self,
+ .index = 0,
+ .end_index = 0,
+ .buf = undefined,
+ .first_iter = first_iter_start_value,
+ },
+ .haiku => return Iterator{
.dir = self,
+ .offset = 0,
.index = 0,
.end_index = 0,
.buf = undefined,
@@ -626,16 +646,17 @@ fn iterateImpl(self: Dir, first_iter_start_value: bool) Iterator {
}
pub const Walker = struct {
- stack: std.ArrayList(StackItem),
- name_buffer: std.ArrayList(u8),
+ stack: std.ArrayListUnmanaged(StackItem),
+ name_buffer: std.ArrayListUnmanaged(u8),
+ allocator: Allocator,
- pub const WalkerEntry = struct {
+ pub const Entry = struct {
/// The containing directory. This can be used to operate directly on `basename`
/// rather than `path`, avoiding `error.NameTooLong` for deeply nested paths.
/// The directory remains open until `next` or `deinit` is called.
dir: Dir,
- basename: []const u8,
- path: []const u8,
+ basename: [:0]const u8,
+ path: [:0]const u8,
kind: Dir.Entry.Kind,
};
@@ -647,7 +668,8 @@ pub const Walker = struct {
/// After each call to this function, and on deinit(), the memory returned
/// from this function becomes invalid. A copy must be made in order to keep
/// a reference to the path.
- pub fn next(self: *Walker) !?WalkerEntry {
+ pub fn next(self: *Walker) !?Walker.Entry {
+ const gpa = self.allocator;
while (self.stack.items.len != 0) {
// `top` and `containing` become invalid after appending to `self.stack`
var top = &self.stack.items[self.stack.items.len - 1];
@@ -666,10 +688,12 @@ pub const Walker = struct {
}) |base| {
self.name_buffer.shrinkRetainingCapacity(dirname_len);
if (self.name_buffer.items.len != 0) {
- try self.name_buffer.append(fs.path.sep);
+ try self.name_buffer.append(gpa, fs.path.sep);
dirname_len += 1;
}
- try self.name_buffer.appendSlice(base.name);
+ try self.name_buffer.ensureUnusedCapacity(gpa, base.name.len + 1);
+ self.name_buffer.appendSliceAssumeCapacity(base.name);
+ self.name_buffer.appendAssumeCapacity(0);
if (base.kind == .directory) {
var new_dir = top.iter.dir.openDir(base.name, .{ .iterate = true }) catch |err| switch (err) {
error.NameTooLong => unreachable, // no path sep in base.name
@@ -677,18 +701,18 @@ pub const Walker = struct {
};
{
errdefer new_dir.close();
- try self.stack.append(StackItem{
+ try self.stack.append(gpa, .{
.iter = new_dir.iterateAssumeFirstIteration(),
- .dirname_len = self.name_buffer.items.len,
+ .dirname_len = self.name_buffer.items.len - 1,
});
top = &self.stack.items[self.stack.items.len - 1];
containing = &self.stack.items[self.stack.items.len - 2];
}
}
- return WalkerEntry{
+ return .{
.dir = containing.iter.dir,
- .basename = self.name_buffer.items[dirname_len..],
- .path = self.name_buffer.items,
+ .basename = self.name_buffer.items[dirname_len .. self.name_buffer.items.len - 1 :0],
+ .path = self.name_buffer.items[0 .. self.name_buffer.items.len - 1 :0],
.kind = base.kind,
};
} else {
@@ -702,37 +726,39 @@ pub const Walker = struct {
}
pub fn deinit(self: *Walker) void {
+ const gpa = self.allocator;
// Close any remaining directories except the initial one (which is always at index 0)
if (self.stack.items.len > 1) {
for (self.stack.items[1..]) |*item| {
item.iter.dir.close();
}
}
- self.stack.deinit();
- self.name_buffer.deinit();
+ self.stack.deinit(gpa);
+ self.name_buffer.deinit(gpa);
}
};
/// Recursively iterates over a directory.
+///
/// `self` must have been opened with `OpenDirOptions{.iterate = true}`.
-/// Must call `Walker.deinit` when done.
+///
+/// `Walker.deinit` releases allocated memory and directory handles.
+///
/// The order of returned file system entries is undefined.
+///
/// `self` will not be closed after walking it.
-pub fn walk(self: Dir, allocator: Allocator) !Walker {
- var name_buffer = std.ArrayList(u8).init(allocator);
- errdefer name_buffer.deinit();
-
- var stack = std.ArrayList(Walker.StackItem).init(allocator);
- errdefer stack.deinit();
+pub fn walk(self: Dir, allocator: Allocator) Allocator.Error!Walker {
+ var stack: std.ArrayListUnmanaged(Walker.StackItem) = .{};
- try stack.append(Walker.StackItem{
+ try stack.append(allocator, .{
.iter = self.iterate(),
.dirname_len = 0,
});
- return Walker{
+ return .{
.stack = stack,
- .name_buffer = name_buffer,
+ .name_buffer = .{},
+ .allocator = allocator,
};
}
@@ -1429,6 +1455,27 @@ pub fn openDirZ(self: Dir, sub_path_c: [*:0]const u8, args: OpenDirOptions) Open
.wasi => {
return openDir(self, mem.sliceTo(sub_path_c, 0), args);
},
+ .haiku => {
+ const rc = posix.system._kern_open_dir(self.fd, sub_path_c);
+ if (rc >= 0) return .{ .fd = rc };
+ switch (@as(posix.E, @enumFromInt(rc))) {
+ .FAULT => unreachable,
+ .INVAL => unreachable,
+ .BADF => unreachable,
+ .ACCES => return error.AccessDenied,
+ .LOOP => return error.SymLinkLoop,
+ .MFILE => return error.ProcessFdQuotaExceeded,
+ .NAMETOOLONG => return error.NameTooLong,
+ .NFILE => return error.SystemFdQuotaExceeded,
+ .NODEV => return error.NoDevice,
+ .NOENT => return error.FileNotFound,
+ .NOMEM => return error.SystemResources,
+ .NOTDIR => return error.NotDir,
+ .PERM => return error.AccessDenied,
+ .BUSY => return error.DeviceBusy,
+ else => |err| return posix.unexpectedErrno(err),
+ }
+ },
else => {
var symlink_flags: posix.O = .{
.ACCMODE = .RDONLY,
diff --git a/lib/std/hash/crc.zig b/lib/std/hash/crc.zig
index 0ac4de761e..732c03e721 100644
--- a/lib/std/hash/crc.zig
+++ b/lib/std/hash/crc.zig
@@ -1,285 +1,911 @@
-// There are two implementations of CRC32 implemented with the following key characteristics:
-//
-// - Crc32WithPoly uses 8Kb of tables but is ~10x faster than the small method.
-//
-// - Crc32SmallWithPoly uses only 64 bytes of memory but is slower. Be aware that this is
-// still moderately fast just slow relative to the slicing approach.
-
-const std = @import("std");
-const builtin = @import("builtin");
-const debug = std.debug;
-const testing = std.testing;
-
-pub usingnamespace @import("crc/catalog.zig");
-
-pub fn Algorithm(comptime W: type) type {
- return struct {
- polynomial: W,
- initial: W,
- reflect_input: bool,
- reflect_output: bool,
- xor_output: W,
- };
-}
+//! This file is auto-generated by tools/update_crc_catalog.zig.
-pub fn Crc(comptime W: type, comptime algorithm: Algorithm(W)) type {
- return struct {
- const Self = @This();
- const I = if (@bitSizeOf(W) < 8) u8 else W;
- const lookup_table = blk: {
- @setEvalBranchQuota(2500);
-
- const poly = if (algorithm.reflect_input)
- @bitReverse(@as(I, algorithm.polynomial)) >> (@bitSizeOf(I) - @bitSizeOf(W))
- else
- @as(I, algorithm.polynomial) << (@bitSizeOf(I) - @bitSizeOf(W));
-
- var table: [256]I = undefined;
- for (&table, 0..) |*e, i| {
- var crc: I = i;
- if (algorithm.reflect_input) {
- var j: usize = 0;
- while (j < 8) : (j += 1) {
- crc = (crc >> 1) ^ ((crc & 1) * poly);
- }
- } else {
- crc <<= @bitSizeOf(I) - 8;
- var j: usize = 0;
- while (j < 8) : (j += 1) {
- crc = (crc << 1) ^ (((crc >> (@bitSizeOf(I) - 1)) & 1) * poly);
- }
- }
- e.* = crc;
- }
- break :blk table;
- };
-
- crc: I,
-
- pub fn init() Self {
- const initial = if (algorithm.reflect_input)
- @bitReverse(@as(I, algorithm.initial)) >> (@bitSizeOf(I) - @bitSizeOf(W))
- else
- @as(I, algorithm.initial) << (@bitSizeOf(I) - @bitSizeOf(W));
- return Self{ .crc = initial };
- }
-
- inline fn tableEntry(index: I) I {
- return lookup_table[@as(u8, @intCast(index & 0xFF))];
- }
-
- pub fn update(self: *Self, bytes: []const u8) void {
- var i: usize = 0;
- if (@bitSizeOf(I) <= 8) {
- while (i < bytes.len) : (i += 1) {
- self.crc = tableEntry(self.crc ^ bytes[i]);
- }
- } else if (algorithm.reflect_input) {
- while (i < bytes.len) : (i += 1) {
- const table_index = self.crc ^ bytes[i];
- self.crc = tableEntry(table_index) ^ (self.crc >> 8);
- }
- } else {
- while (i < bytes.len) : (i += 1) {
- const table_index = (self.crc >> (@bitSizeOf(I) - 8)) ^ bytes[i];
- self.crc = tableEntry(table_index) ^ (self.crc << 8);
- }
- }
- }
-
- pub fn final(self: Self) W {
- var c = self.crc;
- if (algorithm.reflect_input != algorithm.reflect_output) {
- c = @bitReverse(c);
- }
- if (!algorithm.reflect_output) {
- c >>= @bitSizeOf(I) - @bitSizeOf(W);
- }
- return @as(W, @intCast(c ^ algorithm.xor_output));
- }
-
- pub fn hash(bytes: []const u8) W {
- var c = Self.init();
- c.update(bytes);
- return c.final();
- }
- };
-}
+const impl = @import("crc/impl.zig");
-pub const Polynomial = enum(u32) {
- IEEE = 0xedb88320,
- Castagnoli = 0x82f63b78,
- Koopman = 0xeb31d82e,
- _,
-};
+pub const Crc = impl.Crc;
+pub const Polynomial = impl.Polynomial;
+pub const Crc32WithPoly = impl.Crc32WithPoly;
+pub const Crc32SmallWithPoly = impl.Crc32SmallWithPoly;
// IEEE is by far the most common CRC and so is aliased by default.
pub const Crc32 = Crc32WithPoly(.IEEE);
-// slicing-by-8 crc32 implementation.
-pub fn Crc32WithPoly(comptime poly: Polynomial) type {
- return struct {
- const Self = @This();
- const lookup_tables = block: {
- @setEvalBranchQuota(20000);
- var tables: [8][256]u32 = undefined;
-
- for (&tables[0], 0..) |*e, i| {
- var crc = @as(u32, @intCast(i));
- var j: usize = 0;
- while (j < 8) : (j += 1) {
- if (crc & 1 == 1) {
- crc = (crc >> 1) ^ @intFromEnum(poly);
- } else {
- crc = (crc >> 1);
- }
- }
- e.* = crc;
- }
-
- var i: usize = 0;
- while (i < 256) : (i += 1) {
- var crc = tables[0][i];
- var j: usize = 1;
- while (j < 8) : (j += 1) {
- const index: u8 = @truncate(crc);
- crc = tables[0][index] ^ (crc >> 8);
- tables[j][i] = crc;
- }
- }
-
- break :block tables;
- };
-
- crc: u32,
-
- pub fn init() Self {
- return Self{ .crc = 0xffffffff };
- }
-
- pub fn update(self: *Self, input: []const u8) void {
- var i: usize = 0;
- while (i + 8 <= input.len) : (i += 8) {
- const p = input[i..][0..8];
-
- // Unrolling this way gives ~50Mb/s increase
- self.crc ^= std.mem.readInt(u32, p[0..4], .little);
-
- self.crc =
- lookup_tables[0][p[7]] ^
- lookup_tables[1][p[6]] ^
- lookup_tables[2][p[5]] ^
- lookup_tables[3][p[4]] ^
- lookup_tables[4][@as(u8, @truncate(self.crc >> 24))] ^
- lookup_tables[5][@as(u8, @truncate(self.crc >> 16))] ^
- lookup_tables[6][@as(u8, @truncate(self.crc >> 8))] ^
- lookup_tables[7][@as(u8, @truncate(self.crc >> 0))];
- }
-
- while (i < input.len) : (i += 1) {
- const index = @as(u8, @truncate(self.crc)) ^ input[i];
- self.crc = (self.crc >> 8) ^ lookup_tables[0][index];
- }
- }
-
- pub fn final(self: *Self) u32 {
- return ~self.crc;
- }
-
- pub fn hash(input: []const u8) u32 {
- var c = Self.init();
- c.update(input);
- return c.final();
- }
- };
-}
-
-const verify = @import("verify.zig");
-
-test "crc32 ieee" {
- const Crc32Ieee = Crc32WithPoly(.IEEE);
-
- try testing.expect(Crc32Ieee.hash("") == 0x00000000);
- try testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43);
- try testing.expect(Crc32Ieee.hash("abc") == 0x352441c2);
-}
-
-test "crc32 castagnoli" {
- const Crc32Castagnoli = Crc32WithPoly(.Castagnoli);
-
- try testing.expect(Crc32Castagnoli.hash("") == 0x00000000);
- try testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330);
- try testing.expect(Crc32Castagnoli.hash("abc") == 0x364b3fb7);
-}
-
-test "crc32 iterative" {
- try verify.iterativeApi(Crc32WithPoly(.IEEE));
-}
-
-// half-byte lookup table implementation.
-pub fn Crc32SmallWithPoly(comptime poly: Polynomial) type {
- return struct {
- const Self = @This();
- const lookup_table = block: {
- var table: [16]u32 = undefined;
-
- for (&table, 0..) |*e, i| {
- var crc = @as(u32, @intCast(i * 16));
- var j: usize = 0;
- while (j < 8) : (j += 1) {
- if (crc & 1 == 1) {
- crc = (crc >> 1) ^ @intFromEnum(poly);
- } else {
- crc = (crc >> 1);
- }
- }
- e.* = crc;
- }
-
- break :block table;
- };
-
- crc: u32,
-
- pub fn init() Self {
- return Self{ .crc = 0xffffffff };
- }
-
- pub fn update(self: *Self, input: []const u8) void {
- for (input) |b| {
- self.crc = lookup_table[@as(u4, @truncate(self.crc ^ (b >> 0)))] ^ (self.crc >> 4);
- self.crc = lookup_table[@as(u4, @truncate(self.crc ^ (b >> 4)))] ^ (self.crc >> 4);
- }
- }
-
- pub fn final(self: *Self) u32 {
- return ~self.crc;
- }
-
- pub fn hash(input: []const u8) u32 {
- var c = Self.init();
- c.update(input);
- return c.final();
- }
- };
-}
-
-test "small crc32 iterative" {
- try verify.iterativeApi(Crc32SmallWithPoly(.IEEE));
+test {
+ _ = @import("crc/test.zig");
}
-test "small crc32 ieee" {
- const Crc32Ieee = Crc32SmallWithPoly(.IEEE);
-
- try testing.expect(Crc32Ieee.hash("") == 0x00000000);
- try testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43);
- try testing.expect(Crc32Ieee.hash("abc") == 0x352441c2);
-}
-
-test "small crc32 castagnoli" {
- const Crc32Castagnoli = Crc32SmallWithPoly(.Castagnoli);
-
- try testing.expect(Crc32Castagnoli.hash("") == 0x00000000);
- try testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330);
- try testing.expect(Crc32Castagnoli.hash("abc") == 0x364b3fb7);
-}
+pub const Crc3Gsm = Crc(u3, .{
+ .polynomial = 0x3,
+ .initial = 0x0,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x7,
+});
+
+pub const Crc3Rohc = Crc(u3, .{
+ .polynomial = 0x3,
+ .initial = 0x7,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x0,
+});
+
+pub const Crc4G704 = Crc(u4, .{
+ .polynomial = 0x3,
+ .initial = 0x0,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x0,
+});
+
+pub const Crc4Interlaken = Crc(u4, .{
+ .polynomial = 0x3,
+ .initial = 0xf,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0xf,
+});
+
+pub const Crc5EpcC1g2 = Crc(u5, .{
+ .polynomial = 0x09,
+ .initial = 0x09,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00,
+});
+
+pub const Crc5G704 = Crc(u5, .{
+ .polynomial = 0x15,
+ .initial = 0x00,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x00,
+});
+
+pub const Crc5Usb = Crc(u5, .{
+ .polynomial = 0x05,
+ .initial = 0x1f,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x1f,
+});
+
+pub const Crc6Cdma2000A = Crc(u6, .{
+ .polynomial = 0x27,
+ .initial = 0x3f,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00,
+});
+
+pub const Crc6Cdma2000B = Crc(u6, .{
+ .polynomial = 0x07,
+ .initial = 0x3f,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00,
+});
+
+pub const Crc6Darc = Crc(u6, .{
+ .polynomial = 0x19,
+ .initial = 0x00,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x00,
+});
+
+pub const Crc6G704 = Crc(u6, .{
+ .polynomial = 0x03,
+ .initial = 0x00,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x00,
+});
+
+pub const Crc6Gsm = Crc(u6, .{
+ .polynomial = 0x2f,
+ .initial = 0x00,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x3f,
+});
+
+pub const Crc7Mmc = Crc(u7, .{
+ .polynomial = 0x09,
+ .initial = 0x00,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00,
+});
+
+pub const Crc7Rohc = Crc(u7, .{
+ .polynomial = 0x4f,
+ .initial = 0x7f,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x00,
+});
+
+pub const Crc7Umts = Crc(u7, .{
+ .polynomial = 0x45,
+ .initial = 0x00,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00,
+});
+
+pub const Crc8Autosar = Crc(u8, .{
+ .polynomial = 0x2f,
+ .initial = 0xff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0xff,
+});
+
+pub const Crc8Bluetooth = Crc(u8, .{
+ .polynomial = 0xa7,
+ .initial = 0x00,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x00,
+});
+
+pub const Crc8Cdma2000 = Crc(u8, .{
+ .polynomial = 0x9b,
+ .initial = 0xff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00,
+});
+
+pub const Crc8Darc = Crc(u8, .{
+ .polynomial = 0x39,
+ .initial = 0x00,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x00,
+});
+
+pub const Crc8DvbS2 = Crc(u8, .{
+ .polynomial = 0xd5,
+ .initial = 0x00,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00,
+});
+
+pub const Crc8GsmA = Crc(u8, .{
+ .polynomial = 0x1d,
+ .initial = 0x00,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00,
+});
+
+pub const Crc8GsmB = Crc(u8, .{
+ .polynomial = 0x49,
+ .initial = 0x00,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0xff,
+});
+
+pub const Crc8Hitag = Crc(u8, .{
+ .polynomial = 0x1d,
+ .initial = 0xff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00,
+});
+
+pub const Crc8I4321 = Crc(u8, .{
+ .polynomial = 0x07,
+ .initial = 0x00,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x55,
+});
+
+pub const Crc8ICode = Crc(u8, .{
+ .polynomial = 0x1d,
+ .initial = 0xfd,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00,
+});
+
+pub const Crc8Lte = Crc(u8, .{
+ .polynomial = 0x9b,
+ .initial = 0x00,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00,
+});
+
+pub const Crc8MaximDow = Crc(u8, .{
+ .polynomial = 0x31,
+ .initial = 0x00,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x00,
+});
+
+pub const Crc8MifareMad = Crc(u8, .{
+ .polynomial = 0x1d,
+ .initial = 0xc7,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00,
+});
+
+pub const Crc8Nrsc5 = Crc(u8, .{
+ .polynomial = 0x31,
+ .initial = 0xff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00,
+});
+
+pub const Crc8Opensafety = Crc(u8, .{
+ .polynomial = 0x2f,
+ .initial = 0x00,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00,
+});
+
+pub const Crc8Rohc = Crc(u8, .{
+ .polynomial = 0x07,
+ .initial = 0xff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x00,
+});
+
+pub const Crc8SaeJ1850 = Crc(u8, .{
+ .polynomial = 0x1d,
+ .initial = 0xff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0xff,
+});
+
+pub const Crc8Smbus = Crc(u8, .{
+ .polynomial = 0x07,
+ .initial = 0x00,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00,
+});
+
+pub const Crc8Tech3250 = Crc(u8, .{
+ .polynomial = 0x1d,
+ .initial = 0xff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x00,
+});
+
+pub const Crc8Wcdma = Crc(u8, .{
+ .polynomial = 0x9b,
+ .initial = 0x00,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x00,
+});
+
+pub const Crc10Atm = Crc(u10, .{
+ .polynomial = 0x233,
+ .initial = 0x000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x000,
+});
+
+pub const Crc10Cdma2000 = Crc(u10, .{
+ .polynomial = 0x3d9,
+ .initial = 0x3ff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x000,
+});
+
+pub const Crc10Gsm = Crc(u10, .{
+ .polynomial = 0x175,
+ .initial = 0x000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x3ff,
+});
+
+pub const Crc11Flexray = Crc(u11, .{
+ .polynomial = 0x385,
+ .initial = 0x01a,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x000,
+});
+
+pub const Crc11Umts = Crc(u11, .{
+ .polynomial = 0x307,
+ .initial = 0x000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x000,
+});
+
+pub const Crc12Cdma2000 = Crc(u12, .{
+ .polynomial = 0xf13,
+ .initial = 0xfff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x000,
+});
+
+pub const Crc12Dect = Crc(u12, .{
+ .polynomial = 0x80f,
+ .initial = 0x000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x000,
+});
+
+pub const Crc12Gsm = Crc(u12, .{
+ .polynomial = 0xd31,
+ .initial = 0x000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0xfff,
+});
+
+pub const Crc12Umts = Crc(u12, .{
+ .polynomial = 0x80f,
+ .initial = 0x000,
+ .reflect_input = false,
+ .reflect_output = true,
+ .xor_output = 0x000,
+});
+
+pub const Crc13Bbc = Crc(u13, .{
+ .polynomial = 0x1cf5,
+ .initial = 0x0000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000,
+});
+
+pub const Crc14Darc = Crc(u14, .{
+ .polynomial = 0x0805,
+ .initial = 0x0000,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x0000,
+});
+
+pub const Crc14Gsm = Crc(u14, .{
+ .polynomial = 0x202d,
+ .initial = 0x0000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x3fff,
+});
+
+pub const Crc15Can = Crc(u15, .{
+ .polynomial = 0x4599,
+ .initial = 0x0000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000,
+});
+
+pub const Crc15Mpt1327 = Crc(u15, .{
+ .polynomial = 0x6815,
+ .initial = 0x0000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0001,
+});
+
+pub const Crc16Arc = Crc(u16, .{
+ .polynomial = 0x8005,
+ .initial = 0x0000,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16Cdma2000 = Crc(u16, .{
+ .polynomial = 0xc867,
+ .initial = 0xffff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16Cms = Crc(u16, .{
+ .polynomial = 0x8005,
+ .initial = 0xffff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16Dds110 = Crc(u16, .{
+ .polynomial = 0x8005,
+ .initial = 0x800d,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16DectR = Crc(u16, .{
+ .polynomial = 0x0589,
+ .initial = 0x0000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0001,
+});
+
+pub const Crc16DectX = Crc(u16, .{
+ .polynomial = 0x0589,
+ .initial = 0x0000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16Dnp = Crc(u16, .{
+ .polynomial = 0x3d65,
+ .initial = 0x0000,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0xffff,
+});
+
+pub const Crc16En13757 = Crc(u16, .{
+ .polynomial = 0x3d65,
+ .initial = 0x0000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0xffff,
+});
+
+pub const Crc16Genibus = Crc(u16, .{
+ .polynomial = 0x1021,
+ .initial = 0xffff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0xffff,
+});
+
+pub const Crc16Gsm = Crc(u16, .{
+ .polynomial = 0x1021,
+ .initial = 0x0000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0xffff,
+});
+
+pub const Crc16Ibm3740 = Crc(u16, .{
+ .polynomial = 0x1021,
+ .initial = 0xffff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16IbmSdlc = Crc(u16, .{
+ .polynomial = 0x1021,
+ .initial = 0xffff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0xffff,
+});
+
+pub const Crc16IsoIec144433A = Crc(u16, .{
+ .polynomial = 0x1021,
+ .initial = 0xc6c6,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16Kermit = Crc(u16, .{
+ .polynomial = 0x1021,
+ .initial = 0x0000,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16Lj1200 = Crc(u16, .{
+ .polynomial = 0x6f63,
+ .initial = 0x0000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16M17 = Crc(u16, .{
+ .polynomial = 0x5935,
+ .initial = 0xffff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16MaximDow = Crc(u16, .{
+ .polynomial = 0x8005,
+ .initial = 0x0000,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0xffff,
+});
+
+pub const Crc16Mcrf4xx = Crc(u16, .{
+ .polynomial = 0x1021,
+ .initial = 0xffff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16Modbus = Crc(u16, .{
+ .polynomial = 0x8005,
+ .initial = 0xffff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16Nrsc5 = Crc(u16, .{
+ .polynomial = 0x080b,
+ .initial = 0xffff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16OpensafetyA = Crc(u16, .{
+ .polynomial = 0x5935,
+ .initial = 0x0000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16OpensafetyB = Crc(u16, .{
+ .polynomial = 0x755b,
+ .initial = 0x0000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16Profibus = Crc(u16, .{
+ .polynomial = 0x1dcf,
+ .initial = 0xffff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0xffff,
+});
+
+pub const Crc16Riello = Crc(u16, .{
+ .polynomial = 0x1021,
+ .initial = 0xb2aa,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16SpiFujitsu = Crc(u16, .{
+ .polynomial = 0x1021,
+ .initial = 0x1d0f,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16T10Dif = Crc(u16, .{
+ .polynomial = 0x8bb7,
+ .initial = 0x0000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16Teledisk = Crc(u16, .{
+ .polynomial = 0xa097,
+ .initial = 0x0000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16Tms37157 = Crc(u16, .{
+ .polynomial = 0x1021,
+ .initial = 0x89ec,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16Umts = Crc(u16, .{
+ .polynomial = 0x8005,
+ .initial = 0x0000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000,
+});
+
+pub const Crc16Usb = Crc(u16, .{
+ .polynomial = 0x8005,
+ .initial = 0xffff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0xffff,
+});
+
+pub const Crc16Xmodem = Crc(u16, .{
+ .polynomial = 0x1021,
+ .initial = 0x0000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000,
+});
+
+pub const Crc17CanFd = Crc(u17, .{
+ .polynomial = 0x1685b,
+ .initial = 0x00000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00000,
+});
+
+pub const Crc21CanFd = Crc(u21, .{
+ .polynomial = 0x102899,
+ .initial = 0x000000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x000000,
+});
+
+pub const Crc24Ble = Crc(u24, .{
+ .polynomial = 0x00065b,
+ .initial = 0x555555,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x000000,
+});
+
+pub const Crc24FlexrayA = Crc(u24, .{
+ .polynomial = 0x5d6dcb,
+ .initial = 0xfedcba,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x000000,
+});
+
+pub const Crc24FlexrayB = Crc(u24, .{
+ .polynomial = 0x5d6dcb,
+ .initial = 0xabcdef,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x000000,
+});
+
+pub const Crc24Interlaken = Crc(u24, .{
+ .polynomial = 0x328b63,
+ .initial = 0xffffff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0xffffff,
+});
+
+pub const Crc24LteA = Crc(u24, .{
+ .polynomial = 0x864cfb,
+ .initial = 0x000000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x000000,
+});
+
+pub const Crc24LteB = Crc(u24, .{
+ .polynomial = 0x800063,
+ .initial = 0x000000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x000000,
+});
+
+pub const Crc24Openpgp = Crc(u24, .{
+ .polynomial = 0x864cfb,
+ .initial = 0xb704ce,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x000000,
+});
+
+pub const Crc24Os9 = Crc(u24, .{
+ .polynomial = 0x800063,
+ .initial = 0xffffff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0xffffff,
+});
+
+pub const Crc30Cdma = Crc(u30, .{
+ .polynomial = 0x2030b9c7,
+ .initial = 0x3fffffff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x3fffffff,
+});
+
+pub const Crc31Philips = Crc(u31, .{
+ .polynomial = 0x04c11db7,
+ .initial = 0x7fffffff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x7fffffff,
+});
+
+pub const Crc32Aixm = Crc(u32, .{
+ .polynomial = 0x814141ab,
+ .initial = 0x00000000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00000000,
+});
+
+pub const Crc32Autosar = Crc(u32, .{
+ .polynomial = 0xf4acfb13,
+ .initial = 0xffffffff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0xffffffff,
+});
+
+pub const Crc32Base91D = Crc(u32, .{
+ .polynomial = 0xa833982b,
+ .initial = 0xffffffff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0xffffffff,
+});
+
+pub const Crc32Bzip2 = Crc(u32, .{
+ .polynomial = 0x04c11db7,
+ .initial = 0xffffffff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0xffffffff,
+});
+
+pub const Crc32CdRomEdc = Crc(u32, .{
+ .polynomial = 0x8001801b,
+ .initial = 0x00000000,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x00000000,
+});
+
+pub const Crc32Cksum = Crc(u32, .{
+ .polynomial = 0x04c11db7,
+ .initial = 0x00000000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0xffffffff,
+});
+
+pub const Crc32Iscsi = Crc(u32, .{
+ .polynomial = 0x1edc6f41,
+ .initial = 0xffffffff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0xffffffff,
+});
+
+pub const Crc32IsoHdlc = Crc(u32, .{
+ .polynomial = 0x04c11db7,
+ .initial = 0xffffffff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0xffffffff,
+});
+
+pub const Crc32Jamcrc = Crc(u32, .{
+ .polynomial = 0x04c11db7,
+ .initial = 0xffffffff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x00000000,
+});
+
+pub const Crc32Mef = Crc(u32, .{
+ .polynomial = 0x741b8cd7,
+ .initial = 0xffffffff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x00000000,
+});
+
+pub const Crc32Mpeg2 = Crc(u32, .{
+ .polynomial = 0x04c11db7,
+ .initial = 0xffffffff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00000000,
+});
+
+pub const Crc32Xfer = Crc(u32, .{
+ .polynomial = 0x000000af,
+ .initial = 0x00000000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x00000000,
+});
+
+pub const Crc40Gsm = Crc(u40, .{
+ .polynomial = 0x0004820009,
+ .initial = 0x0000000000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0xffffffffff,
+});
+
+pub const Crc64Ecma182 = Crc(u64, .{
+ .polynomial = 0x42f0e1eba9ea3693,
+ .initial = 0x0000000000000000,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0x0000000000000000,
+});
+
+pub const Crc64GoIso = Crc(u64, .{
+ .polynomial = 0x000000000000001b,
+ .initial = 0xffffffffffffffff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0xffffffffffffffff,
+});
+
+pub const Crc64Ms = Crc(u64, .{
+ .polynomial = 0x259c84cba6426349,
+ .initial = 0xffffffffffffffff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x0000000000000000,
+});
+
+pub const Crc64Redis = Crc(u64, .{
+ .polynomial = 0xad93d23594c935a9,
+ .initial = 0x0000000000000000,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x0000000000000000,
+});
+
+pub const Crc64We = Crc(u64, .{
+ .polynomial = 0x42f0e1eba9ea3693,
+ .initial = 0xffffffffffffffff,
+ .reflect_input = false,
+ .reflect_output = false,
+ .xor_output = 0xffffffffffffffff,
+});
+
+pub const Crc64Xz = Crc(u64, .{
+ .polynomial = 0x42f0e1eba9ea3693,
+ .initial = 0xffffffffffffffff,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0xffffffffffffffff,
+});
+
+pub const Crc82Darc = Crc(u82, .{
+ .polynomial = 0x0308c0111011401440411,
+ .initial = 0x000000000000000000000,
+ .reflect_input = true,
+ .reflect_output = true,
+ .xor_output = 0x000000000000000000000,
+});
diff --git a/lib/std/hash/crc/catalog.zig b/lib/std/hash/crc/catalog.zig
deleted file mode 100644
index ed08accce6..0000000000
--- a/lib/std/hash/crc/catalog.zig
+++ /dev/null
@@ -1,903 +0,0 @@
-//! This file is auto-generated by tools/update_crc_catalog.zig.
-
-const Crc = @import("../crc.zig").Crc;
-
-test {
- _ = @import("catalog_test.zig");
-}
-
-pub const Crc3Gsm = Crc(u3, .{
- .polynomial = 0x3,
- .initial = 0x0,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x7,
-});
-
-pub const Crc3Rohc = Crc(u3, .{
- .polynomial = 0x3,
- .initial = 0x7,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x0,
-});
-
-pub const Crc4G704 = Crc(u4, .{
- .polynomial = 0x3,
- .initial = 0x0,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x0,
-});
-
-pub const Crc4Interlaken = Crc(u4, .{
- .polynomial = 0x3,
- .initial = 0xf,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0xf,
-});
-
-pub const Crc5EpcC1g2 = Crc(u5, .{
- .polynomial = 0x09,
- .initial = 0x09,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00,
-});
-
-pub const Crc5G704 = Crc(u5, .{
- .polynomial = 0x15,
- .initial = 0x00,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x00,
-});
-
-pub const Crc5Usb = Crc(u5, .{
- .polynomial = 0x05,
- .initial = 0x1f,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x1f,
-});
-
-pub const Crc6Cdma2000A = Crc(u6, .{
- .polynomial = 0x27,
- .initial = 0x3f,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00,
-});
-
-pub const Crc6Cdma2000B = Crc(u6, .{
- .polynomial = 0x07,
- .initial = 0x3f,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00,
-});
-
-pub const Crc6Darc = Crc(u6, .{
- .polynomial = 0x19,
- .initial = 0x00,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x00,
-});
-
-pub const Crc6G704 = Crc(u6, .{
- .polynomial = 0x03,
- .initial = 0x00,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x00,
-});
-
-pub const Crc6Gsm = Crc(u6, .{
- .polynomial = 0x2f,
- .initial = 0x00,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x3f,
-});
-
-pub const Crc7Mmc = Crc(u7, .{
- .polynomial = 0x09,
- .initial = 0x00,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00,
-});
-
-pub const Crc7Rohc = Crc(u7, .{
- .polynomial = 0x4f,
- .initial = 0x7f,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x00,
-});
-
-pub const Crc7Umts = Crc(u7, .{
- .polynomial = 0x45,
- .initial = 0x00,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00,
-});
-
-pub const Crc8Autosar = Crc(u8, .{
- .polynomial = 0x2f,
- .initial = 0xff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0xff,
-});
-
-pub const Crc8Bluetooth = Crc(u8, .{
- .polynomial = 0xa7,
- .initial = 0x00,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x00,
-});
-
-pub const Crc8Cdma2000 = Crc(u8, .{
- .polynomial = 0x9b,
- .initial = 0xff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00,
-});
-
-pub const Crc8Darc = Crc(u8, .{
- .polynomial = 0x39,
- .initial = 0x00,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x00,
-});
-
-pub const Crc8DvbS2 = Crc(u8, .{
- .polynomial = 0xd5,
- .initial = 0x00,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00,
-});
-
-pub const Crc8GsmA = Crc(u8, .{
- .polynomial = 0x1d,
- .initial = 0x00,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00,
-});
-
-pub const Crc8GsmB = Crc(u8, .{
- .polynomial = 0x49,
- .initial = 0x00,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0xff,
-});
-
-pub const Crc8Hitag = Crc(u8, .{
- .polynomial = 0x1d,
- .initial = 0xff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00,
-});
-
-pub const Crc8I4321 = Crc(u8, .{
- .polynomial = 0x07,
- .initial = 0x00,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x55,
-});
-
-pub const Crc8ICode = Crc(u8, .{
- .polynomial = 0x1d,
- .initial = 0xfd,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00,
-});
-
-pub const Crc8Lte = Crc(u8, .{
- .polynomial = 0x9b,
- .initial = 0x00,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00,
-});
-
-pub const Crc8MaximDow = Crc(u8, .{
- .polynomial = 0x31,
- .initial = 0x00,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x00,
-});
-
-pub const Crc8MifareMad = Crc(u8, .{
- .polynomial = 0x1d,
- .initial = 0xc7,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00,
-});
-
-pub const Crc8Nrsc5 = Crc(u8, .{
- .polynomial = 0x31,
- .initial = 0xff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00,
-});
-
-pub const Crc8Opensafety = Crc(u8, .{
- .polynomial = 0x2f,
- .initial = 0x00,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00,
-});
-
-pub const Crc8Rohc = Crc(u8, .{
- .polynomial = 0x07,
- .initial = 0xff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x00,
-});
-
-pub const Crc8SaeJ1850 = Crc(u8, .{
- .polynomial = 0x1d,
- .initial = 0xff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0xff,
-});
-
-pub const Crc8Smbus = Crc(u8, .{
- .polynomial = 0x07,
- .initial = 0x00,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00,
-});
-
-pub const Crc8Tech3250 = Crc(u8, .{
- .polynomial = 0x1d,
- .initial = 0xff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x00,
-});
-
-pub const Crc8Wcdma = Crc(u8, .{
- .polynomial = 0x9b,
- .initial = 0x00,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x00,
-});
-
-pub const Crc10Atm = Crc(u10, .{
- .polynomial = 0x233,
- .initial = 0x000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x000,
-});
-
-pub const Crc10Cdma2000 = Crc(u10, .{
- .polynomial = 0x3d9,
- .initial = 0x3ff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x000,
-});
-
-pub const Crc10Gsm = Crc(u10, .{
- .polynomial = 0x175,
- .initial = 0x000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x3ff,
-});
-
-pub const Crc11Flexray = Crc(u11, .{
- .polynomial = 0x385,
- .initial = 0x01a,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x000,
-});
-
-pub const Crc11Umts = Crc(u11, .{
- .polynomial = 0x307,
- .initial = 0x000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x000,
-});
-
-pub const Crc12Cdma2000 = Crc(u12, .{
- .polynomial = 0xf13,
- .initial = 0xfff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x000,
-});
-
-pub const Crc12Dect = Crc(u12, .{
- .polynomial = 0x80f,
- .initial = 0x000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x000,
-});
-
-pub const Crc12Gsm = Crc(u12, .{
- .polynomial = 0xd31,
- .initial = 0x000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0xfff,
-});
-
-pub const Crc12Umts = Crc(u12, .{
- .polynomial = 0x80f,
- .initial = 0x000,
- .reflect_input = false,
- .reflect_output = true,
- .xor_output = 0x000,
-});
-
-pub const Crc13Bbc = Crc(u13, .{
- .polynomial = 0x1cf5,
- .initial = 0x0000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000,
-});
-
-pub const Crc14Darc = Crc(u14, .{
- .polynomial = 0x0805,
- .initial = 0x0000,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x0000,
-});
-
-pub const Crc14Gsm = Crc(u14, .{
- .polynomial = 0x202d,
- .initial = 0x0000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x3fff,
-});
-
-pub const Crc15Can = Crc(u15, .{
- .polynomial = 0x4599,
- .initial = 0x0000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000,
-});
-
-pub const Crc15Mpt1327 = Crc(u15, .{
- .polynomial = 0x6815,
- .initial = 0x0000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0001,
-});
-
-pub const Crc16Arc = Crc(u16, .{
- .polynomial = 0x8005,
- .initial = 0x0000,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x0000,
-});
-
-pub const Crc16Cdma2000 = Crc(u16, .{
- .polynomial = 0xc867,
- .initial = 0xffff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000,
-});
-
-pub const Crc16Cms = Crc(u16, .{
- .polynomial = 0x8005,
- .initial = 0xffff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000,
-});
-
-pub const Crc16Dds110 = Crc(u16, .{
- .polynomial = 0x8005,
- .initial = 0x800d,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000,
-});
-
-pub const Crc16DectR = Crc(u16, .{
- .polynomial = 0x0589,
- .initial = 0x0000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0001,
-});
-
-pub const Crc16DectX = Crc(u16, .{
- .polynomial = 0x0589,
- .initial = 0x0000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000,
-});
-
-pub const Crc16Dnp = Crc(u16, .{
- .polynomial = 0x3d65,
- .initial = 0x0000,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0xffff,
-});
-
-pub const Crc16En13757 = Crc(u16, .{
- .polynomial = 0x3d65,
- .initial = 0x0000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0xffff,
-});
-
-pub const Crc16Genibus = Crc(u16, .{
- .polynomial = 0x1021,
- .initial = 0xffff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0xffff,
-});
-
-pub const Crc16Gsm = Crc(u16, .{
- .polynomial = 0x1021,
- .initial = 0x0000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0xffff,
-});
-
-pub const Crc16Ibm3740 = Crc(u16, .{
- .polynomial = 0x1021,
- .initial = 0xffff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000,
-});
-
-pub const Crc16IbmSdlc = Crc(u16, .{
- .polynomial = 0x1021,
- .initial = 0xffff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0xffff,
-});
-
-pub const Crc16IsoIec144433A = Crc(u16, .{
- .polynomial = 0x1021,
- .initial = 0xc6c6,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x0000,
-});
-
-pub const Crc16Kermit = Crc(u16, .{
- .polynomial = 0x1021,
- .initial = 0x0000,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x0000,
-});
-
-pub const Crc16Lj1200 = Crc(u16, .{
- .polynomial = 0x6f63,
- .initial = 0x0000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000,
-});
-
-pub const Crc16M17 = Crc(u16, .{
- .polynomial = 0x5935,
- .initial = 0xffff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000,
-});
-
-pub const Crc16MaximDow = Crc(u16, .{
- .polynomial = 0x8005,
- .initial = 0x0000,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0xffff,
-});
-
-pub const Crc16Mcrf4xx = Crc(u16, .{
- .polynomial = 0x1021,
- .initial = 0xffff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x0000,
-});
-
-pub const Crc16Modbus = Crc(u16, .{
- .polynomial = 0x8005,
- .initial = 0xffff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x0000,
-});
-
-pub const Crc16Nrsc5 = Crc(u16, .{
- .polynomial = 0x080b,
- .initial = 0xffff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x0000,
-});
-
-pub const Crc16OpensafetyA = Crc(u16, .{
- .polynomial = 0x5935,
- .initial = 0x0000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000,
-});
-
-pub const Crc16OpensafetyB = Crc(u16, .{
- .polynomial = 0x755b,
- .initial = 0x0000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000,
-});
-
-pub const Crc16Profibus = Crc(u16, .{
- .polynomial = 0x1dcf,
- .initial = 0xffff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0xffff,
-});
-
-pub const Crc16Riello = Crc(u16, .{
- .polynomial = 0x1021,
- .initial = 0xb2aa,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x0000,
-});
-
-pub const Crc16SpiFujitsu = Crc(u16, .{
- .polynomial = 0x1021,
- .initial = 0x1d0f,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000,
-});
-
-pub const Crc16T10Dif = Crc(u16, .{
- .polynomial = 0x8bb7,
- .initial = 0x0000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000,
-});
-
-pub const Crc16Teledisk = Crc(u16, .{
- .polynomial = 0xa097,
- .initial = 0x0000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000,
-});
-
-pub const Crc16Tms37157 = Crc(u16, .{
- .polynomial = 0x1021,
- .initial = 0x89ec,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x0000,
-});
-
-pub const Crc16Umts = Crc(u16, .{
- .polynomial = 0x8005,
- .initial = 0x0000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000,
-});
-
-pub const Crc16Usb = Crc(u16, .{
- .polynomial = 0x8005,
- .initial = 0xffff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0xffff,
-});
-
-pub const Crc16Xmodem = Crc(u16, .{
- .polynomial = 0x1021,
- .initial = 0x0000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000,
-});
-
-pub const Crc17CanFd = Crc(u17, .{
- .polynomial = 0x1685b,
- .initial = 0x00000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00000,
-});
-
-pub const Crc21CanFd = Crc(u21, .{
- .polynomial = 0x102899,
- .initial = 0x000000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x000000,
-});
-
-pub const Crc24Ble = Crc(u24, .{
- .polynomial = 0x00065b,
- .initial = 0x555555,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x000000,
-});
-
-pub const Crc24FlexrayA = Crc(u24, .{
- .polynomial = 0x5d6dcb,
- .initial = 0xfedcba,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x000000,
-});
-
-pub const Crc24FlexrayB = Crc(u24, .{
- .polynomial = 0x5d6dcb,
- .initial = 0xabcdef,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x000000,
-});
-
-pub const Crc24Interlaken = Crc(u24, .{
- .polynomial = 0x328b63,
- .initial = 0xffffff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0xffffff,
-});
-
-pub const Crc24LteA = Crc(u24, .{
- .polynomial = 0x864cfb,
- .initial = 0x000000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x000000,
-});
-
-pub const Crc24LteB = Crc(u24, .{
- .polynomial = 0x800063,
- .initial = 0x000000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x000000,
-});
-
-pub const Crc24Openpgp = Crc(u24, .{
- .polynomial = 0x864cfb,
- .initial = 0xb704ce,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x000000,
-});
-
-pub const Crc24Os9 = Crc(u24, .{
- .polynomial = 0x800063,
- .initial = 0xffffff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0xffffff,
-});
-
-pub const Crc30Cdma = Crc(u30, .{
- .polynomial = 0x2030b9c7,
- .initial = 0x3fffffff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x3fffffff,
-});
-
-pub const Crc31Philips = Crc(u31, .{
- .polynomial = 0x04c11db7,
- .initial = 0x7fffffff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x7fffffff,
-});
-
-pub const Crc32Aixm = Crc(u32, .{
- .polynomial = 0x814141ab,
- .initial = 0x00000000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00000000,
-});
-
-pub const Crc32Autosar = Crc(u32, .{
- .polynomial = 0xf4acfb13,
- .initial = 0xffffffff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0xffffffff,
-});
-
-pub const Crc32Base91D = Crc(u32, .{
- .polynomial = 0xa833982b,
- .initial = 0xffffffff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0xffffffff,
-});
-
-pub const Crc32Bzip2 = Crc(u32, .{
- .polynomial = 0x04c11db7,
- .initial = 0xffffffff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0xffffffff,
-});
-
-pub const Crc32CdRomEdc = Crc(u32, .{
- .polynomial = 0x8001801b,
- .initial = 0x00000000,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x00000000,
-});
-
-pub const Crc32Cksum = Crc(u32, .{
- .polynomial = 0x04c11db7,
- .initial = 0x00000000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0xffffffff,
-});
-
-pub const Crc32Iscsi = Crc(u32, .{
- .polynomial = 0x1edc6f41,
- .initial = 0xffffffff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0xffffffff,
-});
-
-pub const Crc32IsoHdlc = Crc(u32, .{
- .polynomial = 0x04c11db7,
- .initial = 0xffffffff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0xffffffff,
-});
-
-pub const Crc32Jamcrc = Crc(u32, .{
- .polynomial = 0x04c11db7,
- .initial = 0xffffffff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x00000000,
-});
-
-pub const Crc32Mef = Crc(u32, .{
- .polynomial = 0x741b8cd7,
- .initial = 0xffffffff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x00000000,
-});
-
-pub const Crc32Mpeg2 = Crc(u32, .{
- .polynomial = 0x04c11db7,
- .initial = 0xffffffff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00000000,
-});
-
-pub const Crc32Xfer = Crc(u32, .{
- .polynomial = 0x000000af,
- .initial = 0x00000000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x00000000,
-});
-
-pub const Crc40Gsm = Crc(u40, .{
- .polynomial = 0x0004820009,
- .initial = 0x0000000000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0xffffffffff,
-});
-
-pub const Crc64Ecma182 = Crc(u64, .{
- .polynomial = 0x42f0e1eba9ea3693,
- .initial = 0x0000000000000000,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0x0000000000000000,
-});
-
-pub const Crc64GoIso = Crc(u64, .{
- .polynomial = 0x000000000000001b,
- .initial = 0xffffffffffffffff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0xffffffffffffffff,
-});
-
-pub const Crc64Ms = Crc(u64, .{
- .polynomial = 0x259c84cba6426349,
- .initial = 0xffffffffffffffff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x0000000000000000,
-});
-
-pub const Crc64Redis = Crc(u64, .{
- .polynomial = 0xad93d23594c935a9,
- .initial = 0x0000000000000000,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x0000000000000000,
-});
-
-pub const Crc64We = Crc(u64, .{
- .polynomial = 0x42f0e1eba9ea3693,
- .initial = 0xffffffffffffffff,
- .reflect_input = false,
- .reflect_output = false,
- .xor_output = 0xffffffffffffffff,
-});
-
-pub const Crc64Xz = Crc(u64, .{
- .polynomial = 0x42f0e1eba9ea3693,
- .initial = 0xffffffffffffffff,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0xffffffffffffffff,
-});
-
-pub const Crc82Darc = Crc(u82, .{
- .polynomial = 0x0308c0111011401440411,
- .initial = 0x000000000000000000000,
- .reflect_input = true,
- .reflect_output = true,
- .xor_output = 0x000000000000000000000,
-});
diff --git a/lib/std/hash/crc/impl.zig b/lib/std/hash/crc/impl.zig
new file mode 100644
index 0000000000..f0fd5ac14e
--- /dev/null
+++ b/lib/std/hash/crc/impl.zig
@@ -0,0 +1,241 @@
+// There is a generic CRC implementation "Crc()" which can be paramterized via
+// the Algorithm struct for a plethora of uses, along with two implementations
+// of CRC32 implemented with the following key characteristics:
+//
+// - Crc32WithPoly uses 8Kb of tables but is ~10x faster than the small method.
+//
+// - Crc32SmallWithPoly uses only 64 bytes of memory but is slower. Be aware that this is
+// still moderately fast just slow relative to the slicing approach.
+//
+// The primary interface for all of the standard CRC algorithms is the
+// generated file "crc.zig", which uses the implementation code here to define
+// many standard CRCs.
+
+const std = @import("std");
+
+pub fn Algorithm(comptime W: type) type {
+ return struct {
+ polynomial: W,
+ initial: W,
+ reflect_input: bool,
+ reflect_output: bool,
+ xor_output: W,
+ };
+}
+
+pub fn Crc(comptime W: type, comptime algorithm: Algorithm(W)) type {
+ return struct {
+ const Self = @This();
+ const I = if (@bitSizeOf(W) < 8) u8 else W;
+ const lookup_table = blk: {
+ @setEvalBranchQuota(2500);
+
+ const poly = if (algorithm.reflect_input)
+ @bitReverse(@as(I, algorithm.polynomial)) >> (@bitSizeOf(I) - @bitSizeOf(W))
+ else
+ @as(I, algorithm.polynomial) << (@bitSizeOf(I) - @bitSizeOf(W));
+
+ var table: [256]I = undefined;
+ for (&table, 0..) |*e, i| {
+ var crc: I = i;
+ if (algorithm.reflect_input) {
+ var j: usize = 0;
+ while (j < 8) : (j += 1) {
+ crc = (crc >> 1) ^ ((crc & 1) * poly);
+ }
+ } else {
+ crc <<= @bitSizeOf(I) - 8;
+ var j: usize = 0;
+ while (j < 8) : (j += 1) {
+ crc = (crc << 1) ^ (((crc >> (@bitSizeOf(I) - 1)) & 1) * poly);
+ }
+ }
+ e.* = crc;
+ }
+ break :blk table;
+ };
+
+ crc: I,
+
+ pub fn init() Self {
+ const initial = if (algorithm.reflect_input)
+ @bitReverse(@as(I, algorithm.initial)) >> (@bitSizeOf(I) - @bitSizeOf(W))
+ else
+ @as(I, algorithm.initial) << (@bitSizeOf(I) - @bitSizeOf(W));
+ return Self{ .crc = initial };
+ }
+
+ inline fn tableEntry(index: I) I {
+ return lookup_table[@as(u8, @intCast(index & 0xFF))];
+ }
+
+ pub fn update(self: *Self, bytes: []const u8) void {
+ var i: usize = 0;
+ if (@bitSizeOf(I) <= 8) {
+ while (i < bytes.len) : (i += 1) {
+ self.crc = tableEntry(self.crc ^ bytes[i]);
+ }
+ } else if (algorithm.reflect_input) {
+ while (i < bytes.len) : (i += 1) {
+ const table_index = self.crc ^ bytes[i];
+ self.crc = tableEntry(table_index) ^ (self.crc >> 8);
+ }
+ } else {
+ while (i < bytes.len) : (i += 1) {
+ const table_index = (self.crc >> (@bitSizeOf(I) - 8)) ^ bytes[i];
+ self.crc = tableEntry(table_index) ^ (self.crc << 8);
+ }
+ }
+ }
+
+ pub fn final(self: Self) W {
+ var c = self.crc;
+ if (algorithm.reflect_input != algorithm.reflect_output) {
+ c = @bitReverse(c);
+ }
+ if (!algorithm.reflect_output) {
+ c >>= @bitSizeOf(I) - @bitSizeOf(W);
+ }
+ return @as(W, @intCast(c ^ algorithm.xor_output));
+ }
+
+ pub fn hash(bytes: []const u8) W {
+ var c = Self.init();
+ c.update(bytes);
+ return c.final();
+ }
+ };
+}
+
+pub const Polynomial = enum(u32) {
+ IEEE = 0xedb88320,
+ Castagnoli = 0x82f63b78,
+ Koopman = 0xeb31d82e,
+ _,
+};
+
+// slicing-by-8 crc32 implementation.
+pub fn Crc32WithPoly(comptime poly: Polynomial) type {
+ return struct {
+ const Self = @This();
+ const lookup_tables = block: {
+ @setEvalBranchQuota(20000);
+ var tables: [8][256]u32 = undefined;
+
+ for (&tables[0], 0..) |*e, i| {
+ var crc = @as(u32, @intCast(i));
+ var j: usize = 0;
+ while (j < 8) : (j += 1) {
+ if (crc & 1 == 1) {
+ crc = (crc >> 1) ^ @intFromEnum(poly);
+ } else {
+ crc = (crc >> 1);
+ }
+ }
+ e.* = crc;
+ }
+
+ var i: usize = 0;
+ while (i < 256) : (i += 1) {
+ var crc = tables[0][i];
+ var j: usize = 1;
+ while (j < 8) : (j += 1) {
+ const index: u8 = @truncate(crc);
+ crc = tables[0][index] ^ (crc >> 8);
+ tables[j][i] = crc;
+ }
+ }
+
+ break :block tables;
+ };
+
+ crc: u32,
+
+ pub fn init() Self {
+ return Self{ .crc = 0xffffffff };
+ }
+
+ pub fn update(self: *Self, input: []const u8) void {
+ var i: usize = 0;
+ while (i + 8 <= input.len) : (i += 8) {
+ const p = input[i..][0..8];
+
+ // Unrolling this way gives ~50Mb/s increase
+ self.crc ^= std.mem.readInt(u32, p[0..4], .little);
+
+ self.crc =
+ lookup_tables[0][p[7]] ^
+ lookup_tables[1][p[6]] ^
+ lookup_tables[2][p[5]] ^
+ lookup_tables[3][p[4]] ^
+ lookup_tables[4][@as(u8, @truncate(self.crc >> 24))] ^
+ lookup_tables[5][@as(u8, @truncate(self.crc >> 16))] ^
+ lookup_tables[6][@as(u8, @truncate(self.crc >> 8))] ^
+ lookup_tables[7][@as(u8, @truncate(self.crc >> 0))];
+ }
+
+ while (i < input.len) : (i += 1) {
+ const index = @as(u8, @truncate(self.crc)) ^ input[i];
+ self.crc = (self.crc >> 8) ^ lookup_tables[0][index];
+ }
+ }
+
+ pub fn final(self: *Self) u32 {
+ return ~self.crc;
+ }
+
+ pub fn hash(input: []const u8) u32 {
+ var c = Self.init();
+ c.update(input);
+ return c.final();
+ }
+ };
+}
+
+// half-byte lookup table implementation.
+pub fn Crc32SmallWithPoly(comptime poly: Polynomial) type {
+ return struct {
+ const Self = @This();
+ const lookup_table = block: {
+ var table: [16]u32 = undefined;
+
+ for (&table, 0..) |*e, i| {
+ var crc = @as(u32, @intCast(i * 16));
+ var j: usize = 0;
+ while (j < 8) : (j += 1) {
+ if (crc & 1 == 1) {
+ crc = (crc >> 1) ^ @intFromEnum(poly);
+ } else {
+ crc = (crc >> 1);
+ }
+ }
+ e.* = crc;
+ }
+
+ break :block table;
+ };
+
+ crc: u32,
+
+ pub fn init() Self {
+ return Self{ .crc = 0xffffffff };
+ }
+
+ pub fn update(self: *Self, input: []const u8) void {
+ for (input) |b| {
+ self.crc = lookup_table[@as(u4, @truncate(self.crc ^ (b >> 0)))] ^ (self.crc >> 4);
+ self.crc = lookup_table[@as(u4, @truncate(self.crc ^ (b >> 4)))] ^ (self.crc >> 4);
+ }
+ }
+
+ pub fn final(self: *Self) u32 {
+ return ~self.crc;
+ }
+
+ pub fn hash(input: []const u8) u32 {
+ var c = Self.init();
+ c.update(input);
+ return c.final();
+ }
+ };
+}
diff --git a/lib/std/hash/crc/catalog_test.zig b/lib/std/hash/crc/test.zig
index ab89745ca8..c9cabf6463 100644
--- a/lib/std/hash/crc/catalog_test.zig
+++ b/lib/std/hash/crc/test.zig
@@ -2,10 +2,29 @@
const std = @import("std");
const testing = std.testing;
-const catalog = @import("catalog.zig");
+const verify = @import("../verify.zig");
+const crc = @import("../crc.zig");
+
+test "crc32 ieee" {
+ inline for ([2]type{ crc.Crc32WithPoly(.IEEE), crc.Crc32SmallWithPoly(.IEEE) }) |ieee| {
+ try testing.expect(ieee.hash("") == 0x00000000);
+ try testing.expect(ieee.hash("a") == 0xe8b7be43);
+ try testing.expect(ieee.hash("abc") == 0x352441c2);
+ try verify.iterativeApi(ieee);
+ }
+}
+
+test "crc32 castagnoli" {
+ inline for ([2]type{ crc.Crc32WithPoly(.Castagnoli), crc.Crc32SmallWithPoly(.Castagnoli) }) |casta| {
+ try testing.expect(casta.hash("") == 0x00000000);
+ try testing.expect(casta.hash("a") == 0xc1d04330);
+ try testing.expect(casta.hash("abc") == 0x364b3fb7);
+ try verify.iterativeApi(casta);
+ }
+}
test "CRC-3/GSM" {
- const Crc3Gsm = catalog.Crc3Gsm;
+ const Crc3Gsm = crc.Crc3Gsm;
try testing.expectEqual(@as(u3, 0x4), Crc3Gsm.hash("123456789"));
@@ -16,7 +35,7 @@ test "CRC-3/GSM" {
}
test "CRC-3/ROHC" {
- const Crc3Rohc = catalog.Crc3Rohc;
+ const Crc3Rohc = crc.Crc3Rohc;
try testing.expectEqual(@as(u3, 0x6), Crc3Rohc.hash("123456789"));
@@ -27,7 +46,7 @@ test "CRC-3/ROHC" {
}
test "CRC-4/G-704" {
- const Crc4G704 = catalog.Crc4G704;
+ const Crc4G704 = crc.Crc4G704;
try testing.expectEqual(@as(u4, 0x7), Crc4G704.hash("123456789"));
@@ -38,7 +57,7 @@ test "CRC-4/G-704" {
}
test "CRC-4/INTERLAKEN" {
- const Crc4Interlaken = catalog.Crc4Interlaken;
+ const Crc4Interlaken = crc.Crc4Interlaken;
try testing.expectEqual(@as(u4, 0xb), Crc4Interlaken.hash("123456789"));
@@ -49,7 +68,7 @@ test "CRC-4/INTERLAKEN" {
}
test "CRC-5/EPC-C1G2" {
- const Crc5EpcC1g2 = catalog.Crc5EpcC1g2;
+ const Crc5EpcC1g2 = crc.Crc5EpcC1g2;
try testing.expectEqual(@as(u5, 0x00), Crc5EpcC1g2.hash("123456789"));
@@ -60,7 +79,7 @@ test "CRC-5/EPC-C1G2" {
}
test "CRC-5/G-704" {
- const Crc5G704 = catalog.Crc5G704;
+ const Crc5G704 = crc.Crc5G704;
try testing.expectEqual(@as(u5, 0x07), Crc5G704.hash("123456789"));
@@ -71,7 +90,7 @@ test "CRC-5/G-704" {
}
test "CRC-5/USB" {
- const Crc5Usb = catalog.Crc5Usb;
+ const Crc5Usb = crc.Crc5Usb;
try testing.expectEqual(@as(u5, 0x19), Crc5Usb.hash("123456789"));
@@ -82,7 +101,7 @@ test "CRC-5/USB" {
}
test "CRC-6/CDMA2000-A" {
- const Crc6Cdma2000A = catalog.Crc6Cdma2000A;
+ const Crc6Cdma2000A = crc.Crc6Cdma2000A;
try testing.expectEqual(@as(u6, 0x0d), Crc6Cdma2000A.hash("123456789"));
@@ -93,7 +112,7 @@ test "CRC-6/CDMA2000-A" {
}
test "CRC-6/CDMA2000-B" {
- const Crc6Cdma2000B = catalog.Crc6Cdma2000B;
+ const Crc6Cdma2000B = crc.Crc6Cdma2000B;
try testing.expectEqual(@as(u6, 0x3b), Crc6Cdma2000B.hash("123456789"));
@@ -104,7 +123,7 @@ test "CRC-6/CDMA2000-B" {
}
test "CRC-6/DARC" {
- const Crc6Darc = catalog.Crc6Darc;
+ const Crc6Darc = crc.Crc6Darc;
try testing.expectEqual(@as(u6, 0x26), Crc6Darc.hash("123456789"));
@@ -115,7 +134,7 @@ test "CRC-6/DARC" {
}
test "CRC-6/G-704" {
- const Crc6G704 = catalog.Crc6G704;
+ const Crc6G704 = crc.Crc6G704;
try testing.expectEqual(@as(u6, 0x06), Crc6G704.hash("123456789"));
@@ -126,7 +145,7 @@ test "CRC-6/G-704" {
}
test "CRC-6/GSM" {
- const Crc6Gsm = catalog.Crc6Gsm;
+ const Crc6Gsm = crc.Crc6Gsm;
try testing.expectEqual(@as(u6, 0x13), Crc6Gsm.hash("123456789"));
@@ -137,7 +156,7 @@ test "CRC-6/GSM" {
}
test "CRC-7/MMC" {
- const Crc7Mmc = catalog.Crc7Mmc;
+ const Crc7Mmc = crc.Crc7Mmc;
try testing.expectEqual(@as(u7, 0x75), Crc7Mmc.hash("123456789"));
@@ -148,7 +167,7 @@ test "CRC-7/MMC" {
}
test "CRC-7/ROHC" {
- const Crc7Rohc = catalog.Crc7Rohc;
+ const Crc7Rohc = crc.Crc7Rohc;
try testing.expectEqual(@as(u7, 0x53), Crc7Rohc.hash("123456789"));
@@ -159,7 +178,7 @@ test "CRC-7/ROHC" {
}
test "CRC-7/UMTS" {
- const Crc7Umts = catalog.Crc7Umts;
+ const Crc7Umts = crc.Crc7Umts;
try testing.expectEqual(@as(u7, 0x61), Crc7Umts.hash("123456789"));
@@ -170,7 +189,7 @@ test "CRC-7/UMTS" {
}
test "CRC-8/AUTOSAR" {
- const Crc8Autosar = catalog.Crc8Autosar;
+ const Crc8Autosar = crc.Crc8Autosar;
try testing.expectEqual(@as(u8, 0xdf), Crc8Autosar.hash("123456789"));
@@ -181,7 +200,7 @@ test "CRC-8/AUTOSAR" {
}
test "CRC-8/BLUETOOTH" {
- const Crc8Bluetooth = catalog.Crc8Bluetooth;
+ const Crc8Bluetooth = crc.Crc8Bluetooth;
try testing.expectEqual(@as(u8, 0x26), Crc8Bluetooth.hash("123456789"));
@@ -192,7 +211,7 @@ test "CRC-8/BLUETOOTH" {
}
test "CRC-8/CDMA2000" {
- const Crc8Cdma2000 = catalog.Crc8Cdma2000;
+ const Crc8Cdma2000 = crc.Crc8Cdma2000;
try testing.expectEqual(@as(u8, 0xda), Crc8Cdma2000.hash("123456789"));
@@ -203,7 +222,7 @@ test "CRC-8/CDMA2000" {
}
test "CRC-8/DARC" {
- const Crc8Darc = catalog.Crc8Darc;
+ const Crc8Darc = crc.Crc8Darc;
try testing.expectEqual(@as(u8, 0x15), Crc8Darc.hash("123456789"));
@@ -214,7 +233,7 @@ test "CRC-8/DARC" {
}
test "CRC-8/DVB-S2" {
- const Crc8DvbS2 = catalog.Crc8DvbS2;
+ const Crc8DvbS2 = crc.Crc8DvbS2;
try testing.expectEqual(@as(u8, 0xbc), Crc8DvbS2.hash("123456789"));
@@ -225,7 +244,7 @@ test "CRC-8/DVB-S2" {
}
test "CRC-8/GSM-A" {
- const Crc8GsmA = catalog.Crc8GsmA;
+ const Crc8GsmA = crc.Crc8GsmA;
try testing.expectEqual(@as(u8, 0x37), Crc8GsmA.hash("123456789"));
@@ -236,7 +255,7 @@ test "CRC-8/GSM-A" {
}
test "CRC-8/GSM-B" {
- const Crc8GsmB = catalog.Crc8GsmB;
+ const Crc8GsmB = crc.Crc8GsmB;
try testing.expectEqual(@as(u8, 0x94), Crc8GsmB.hash("123456789"));
@@ -247,7 +266,7 @@ test "CRC-8/GSM-B" {
}
test "CRC-8/HITAG" {
- const Crc8Hitag = catalog.Crc8Hitag;
+ const Crc8Hitag = crc.Crc8Hitag;
try testing.expectEqual(@as(u8, 0xb4), Crc8Hitag.hash("123456789"));
@@ -258,7 +277,7 @@ test "CRC-8/HITAG" {
}
test "CRC-8/I-432-1" {
- const Crc8I4321 = catalog.Crc8I4321;
+ const Crc8I4321 = crc.Crc8I4321;
try testing.expectEqual(@as(u8, 0xa1), Crc8I4321.hash("123456789"));
@@ -269,7 +288,7 @@ test "CRC-8/I-432-1" {
}
test "CRC-8/I-CODE" {
- const Crc8ICode = catalog.Crc8ICode;
+ const Crc8ICode = crc.Crc8ICode;
try testing.expectEqual(@as(u8, 0x7e), Crc8ICode.hash("123456789"));
@@ -280,7 +299,7 @@ test "CRC-8/I-CODE" {
}
test "CRC-8/LTE" {
- const Crc8Lte = catalog.Crc8Lte;
+ const Crc8Lte = crc.Crc8Lte;
try testing.expectEqual(@as(u8, 0xea), Crc8Lte.hash("123456789"));
@@ -291,7 +310,7 @@ test "CRC-8/LTE" {
}
test "CRC-8/MAXIM-DOW" {
- const Crc8MaximDow = catalog.Crc8MaximDow;
+ const Crc8MaximDow = crc.Crc8MaximDow;
try testing.expectEqual(@as(u8, 0xa1), Crc8MaximDow.hash("123456789"));
@@ -302,7 +321,7 @@ test "CRC-8/MAXIM-DOW" {
}
test "CRC-8/MIFARE-MAD" {
- const Crc8MifareMad = catalog.Crc8MifareMad;
+ const Crc8MifareMad = crc.Crc8MifareMad;
try testing.expectEqual(@as(u8, 0x99), Crc8MifareMad.hash("123456789"));
@@ -313,7 +332,7 @@ test "CRC-8/MIFARE-MAD" {
}
test "CRC-8/NRSC-5" {
- const Crc8Nrsc5 = catalog.Crc8Nrsc5;
+ const Crc8Nrsc5 = crc.Crc8Nrsc5;
try testing.expectEqual(@as(u8, 0xf7), Crc8Nrsc5.hash("123456789"));
@@ -324,7 +343,7 @@ test "CRC-8/NRSC-5" {
}
test "CRC-8/OPENSAFETY" {
- const Crc8Opensafety = catalog.Crc8Opensafety;
+ const Crc8Opensafety = crc.Crc8Opensafety;
try testing.expectEqual(@as(u8, 0x3e), Crc8Opensafety.hash("123456789"));
@@ -335,7 +354,7 @@ test "CRC-8/OPENSAFETY" {
}
test "CRC-8/ROHC" {
- const Crc8Rohc = catalog.Crc8Rohc;
+ const Crc8Rohc = crc.Crc8Rohc;
try testing.expectEqual(@as(u8, 0xd0), Crc8Rohc.hash("123456789"));
@@ -346,7 +365,7 @@ test "CRC-8/ROHC" {
}
test "CRC-8/SAE-J1850" {
- const Crc8SaeJ1850 = catalog.Crc8SaeJ1850;
+ const Crc8SaeJ1850 = crc.Crc8SaeJ1850;
try testing.expectEqual(@as(u8, 0x4b), Crc8SaeJ1850.hash("123456789"));
@@ -357,7 +376,7 @@ test "CRC-8/SAE-J1850" {
}
test "CRC-8/SMBUS" {
- const Crc8Smbus = catalog.Crc8Smbus;
+ const Crc8Smbus = crc.Crc8Smbus;
try testing.expectEqual(@as(u8, 0xf4), Crc8Smbus.hash("123456789"));
@@ -368,7 +387,7 @@ test "CRC-8/SMBUS" {
}
test "CRC-8/TECH-3250" {
- const Crc8Tech3250 = catalog.Crc8Tech3250;
+ const Crc8Tech3250 = crc.Crc8Tech3250;
try testing.expectEqual(@as(u8, 0x97), Crc8Tech3250.hash("123456789"));
@@ -379,7 +398,7 @@ test "CRC-8/TECH-3250" {
}
test "CRC-8/WCDMA" {
- const Crc8Wcdma = catalog.Crc8Wcdma;
+ const Crc8Wcdma = crc.Crc8Wcdma;
try testing.expectEqual(@as(u8, 0x25), Crc8Wcdma.hash("123456789"));
@@ -390,7 +409,7 @@ test "CRC-8/WCDMA" {
}
test "CRC-10/ATM" {
- const Crc10Atm = catalog.Crc10Atm;
+ const Crc10Atm = crc.Crc10Atm;
try testing.expectEqual(@as(u10, 0x199), Crc10Atm.hash("123456789"));
@@ -401,7 +420,7 @@ test "CRC-10/ATM" {
}
test "CRC-10/CDMA2000" {
- const Crc10Cdma2000 = catalog.Crc10Cdma2000;
+ const Crc10Cdma2000 = crc.Crc10Cdma2000;
try testing.expectEqual(@as(u10, 0x233), Crc10Cdma2000.hash("123456789"));
@@ -412,7 +431,7 @@ test "CRC-10/CDMA2000" {
}
test "CRC-10/GSM" {
- const Crc10Gsm = catalog.Crc10Gsm;
+ const Crc10Gsm = crc.Crc10Gsm;
try testing.expectEqual(@as(u10, 0x12a), Crc10Gsm.hash("123456789"));
@@ -423,7 +442,7 @@ test "CRC-10/GSM" {
}
test "CRC-11/FLEXRAY" {
- const Crc11Flexray = catalog.Crc11Flexray;
+ const Crc11Flexray = crc.Crc11Flexray;
try testing.expectEqual(@as(u11, 0x5a3), Crc11Flexray.hash("123456789"));
@@ -434,7 +453,7 @@ test "CRC-11/FLEXRAY" {
}
test "CRC-11/UMTS" {
- const Crc11Umts = catalog.Crc11Umts;
+ const Crc11Umts = crc.Crc11Umts;
try testing.expectEqual(@as(u11, 0x061), Crc11Umts.hash("123456789"));
@@ -445,7 +464,7 @@ test "CRC-11/UMTS" {
}
test "CRC-12/CDMA2000" {
- const Crc12Cdma2000 = catalog.Crc12Cdma2000;
+ const Crc12Cdma2000 = crc.Crc12Cdma2000;
try testing.expectEqual(@as(u12, 0xd4d), Crc12Cdma2000.hash("123456789"));
@@ -456,7 +475,7 @@ test "CRC-12/CDMA2000" {
}
test "CRC-12/DECT" {
- const Crc12Dect = catalog.Crc12Dect;
+ const Crc12Dect = crc.Crc12Dect;
try testing.expectEqual(@as(u12, 0xf5b), Crc12Dect.hash("123456789"));
@@ -467,7 +486,7 @@ test "CRC-12/DECT" {
}
test "CRC-12/GSM" {
- const Crc12Gsm = catalog.Crc12Gsm;
+ const Crc12Gsm = crc.Crc12Gsm;
try testing.expectEqual(@as(u12, 0xb34), Crc12Gsm.hash("123456789"));
@@ -478,7 +497,7 @@ test "CRC-12/GSM" {
}
test "CRC-12/UMTS" {
- const Crc12Umts = catalog.Crc12Umts;
+ const Crc12Umts = crc.Crc12Umts;
try testing.expectEqual(@as(u12, 0xdaf), Crc12Umts.hash("123456789"));
@@ -489,7 +508,7 @@ test "CRC-12/UMTS" {
}
test "CRC-13/BBC" {
- const Crc13Bbc = catalog.Crc13Bbc;
+ const Crc13Bbc = crc.Crc13Bbc;
try testing.expectEqual(@as(u13, 0x04fa), Crc13Bbc.hash("123456789"));
@@ -500,7 +519,7 @@ test "CRC-13/BBC" {
}
test "CRC-14/DARC" {
- const Crc14Darc = catalog.Crc14Darc;
+ const Crc14Darc = crc.Crc14Darc;
try testing.expectEqual(@as(u14, 0x082d), Crc14Darc.hash("123456789"));
@@ -511,7 +530,7 @@ test "CRC-14/DARC" {
}
test "CRC-14/GSM" {
- const Crc14Gsm = catalog.Crc14Gsm;
+ const Crc14Gsm = crc.Crc14Gsm;
try testing.expectEqual(@as(u14, 0x30ae), Crc14Gsm.hash("123456789"));
@@ -522,7 +541,7 @@ test "CRC-14/GSM" {
}
test "CRC-15/CAN" {
- const Crc15Can = catalog.Crc15Can;
+ const Crc15Can = crc.Crc15Can;
try testing.expectEqual(@as(u15, 0x059e), Crc15Can.hash("123456789"));
@@ -533,7 +552,7 @@ test "CRC-15/CAN" {
}
test "CRC-15/MPT1327" {
- const Crc15Mpt1327 = catalog.Crc15Mpt1327;
+ const Crc15Mpt1327 = crc.Crc15Mpt1327;
try testing.expectEqual(@as(u15, 0x2566), Crc15Mpt1327.hash("123456789"));
@@ -544,7 +563,7 @@ test "CRC-15/MPT1327" {
}
test "CRC-16/ARC" {
- const Crc16Arc = catalog.Crc16Arc;
+ const Crc16Arc = crc.Crc16Arc;
try testing.expectEqual(@as(u16, 0xbb3d), Crc16Arc.hash("123456789"));
@@ -555,7 +574,7 @@ test "CRC-16/ARC" {
}
test "CRC-16/CDMA2000" {
- const Crc16Cdma2000 = catalog.Crc16Cdma2000;
+ const Crc16Cdma2000 = crc.Crc16Cdma2000;
try testing.expectEqual(@as(u16, 0x4c06), Crc16Cdma2000.hash("123456789"));
@@ -566,7 +585,7 @@ test "CRC-16/CDMA2000" {
}
test "CRC-16/CMS" {
- const Crc16Cms = catalog.Crc16Cms;
+ const Crc16Cms = crc.Crc16Cms;
try testing.expectEqual(@as(u16, 0xaee7), Crc16Cms.hash("123456789"));
@@ -577,7 +596,7 @@ test "CRC-16/CMS" {
}
test "CRC-16/DDS-110" {
- const Crc16Dds110 = catalog.Crc16Dds110;
+ const Crc16Dds110 = crc.Crc16Dds110;
try testing.expectEqual(@as(u16, 0x9ecf), Crc16Dds110.hash("123456789"));
@@ -588,7 +607,7 @@ test "CRC-16/DDS-110" {
}
test "CRC-16/DECT-R" {
- const Crc16DectR = catalog.Crc16DectR;
+ const Crc16DectR = crc.Crc16DectR;
try testing.expectEqual(@as(u16, 0x007e), Crc16DectR.hash("123456789"));
@@ -599,7 +618,7 @@ test "CRC-16/DECT-R" {
}
test "CRC-16/DECT-X" {
- const Crc16DectX = catalog.Crc16DectX;
+ const Crc16DectX = crc.Crc16DectX;
try testing.expectEqual(@as(u16, 0x007f), Crc16DectX.hash("123456789"));
@@ -610,7 +629,7 @@ test "CRC-16/DECT-X" {
}
test "CRC-16/DNP" {
- const Crc16Dnp = catalog.Crc16Dnp;
+ const Crc16Dnp = crc.Crc16Dnp;
try testing.expectEqual(@as(u16, 0xea82), Crc16Dnp.hash("123456789"));
@@ -621,7 +640,7 @@ test "CRC-16/DNP" {
}
test "CRC-16/EN-13757" {
- const Crc16En13757 = catalog.Crc16En13757;
+ const Crc16En13757 = crc.Crc16En13757;
try testing.expectEqual(@as(u16, 0xc2b7), Crc16En13757.hash("123456789"));
@@ -632,7 +651,7 @@ test "CRC-16/EN-13757" {
}
test "CRC-16/GENIBUS" {
- const Crc16Genibus = catalog.Crc16Genibus;
+ const Crc16Genibus = crc.Crc16Genibus;
try testing.expectEqual(@as(u16, 0xd64e), Crc16Genibus.hash("123456789"));
@@ -643,7 +662,7 @@ test "CRC-16/GENIBUS" {
}
test "CRC-16/GSM" {
- const Crc16Gsm = catalog.Crc16Gsm;
+ const Crc16Gsm = crc.Crc16Gsm;
try testing.expectEqual(@as(u16, 0xce3c), Crc16Gsm.hash("123456789"));
@@ -654,7 +673,7 @@ test "CRC-16/GSM" {
}
test "CRC-16/IBM-3740" {
- const Crc16Ibm3740 = catalog.Crc16Ibm3740;
+ const Crc16Ibm3740 = crc.Crc16Ibm3740;
try testing.expectEqual(@as(u16, 0x29b1), Crc16Ibm3740.hash("123456789"));
@@ -665,7 +684,7 @@ test "CRC-16/IBM-3740" {
}
test "CRC-16/IBM-SDLC" {
- const Crc16IbmSdlc = catalog.Crc16IbmSdlc;
+ const Crc16IbmSdlc = crc.Crc16IbmSdlc;
try testing.expectEqual(@as(u16, 0x906e), Crc16IbmSdlc.hash("123456789"));
@@ -676,7 +695,7 @@ test "CRC-16/IBM-SDLC" {
}
test "CRC-16/ISO-IEC-14443-3-A" {
- const Crc16IsoIec144433A = catalog.Crc16IsoIec144433A;
+ const Crc16IsoIec144433A = crc.Crc16IsoIec144433A;
try testing.expectEqual(@as(u16, 0xbf05), Crc16IsoIec144433A.hash("123456789"));
@@ -687,7 +706,7 @@ test "CRC-16/ISO-IEC-14443-3-A" {
}
test "CRC-16/KERMIT" {
- const Crc16Kermit = catalog.Crc16Kermit;
+ const Crc16Kermit = crc.Crc16Kermit;
try testing.expectEqual(@as(u16, 0x2189), Crc16Kermit.hash("123456789"));
@@ -698,7 +717,7 @@ test "CRC-16/KERMIT" {
}
test "CRC-16/LJ1200" {
- const Crc16Lj1200 = catalog.Crc16Lj1200;
+ const Crc16Lj1200 = crc.Crc16Lj1200;
try testing.expectEqual(@as(u16, 0xbdf4), Crc16Lj1200.hash("123456789"));
@@ -709,7 +728,7 @@ test "CRC-16/LJ1200" {
}
test "CRC-16/M17" {
- const Crc16M17 = catalog.Crc16M17;
+ const Crc16M17 = crc.Crc16M17;
try testing.expectEqual(@as(u16, 0x772b), Crc16M17.hash("123456789"));
@@ -720,7 +739,7 @@ test "CRC-16/M17" {
}
test "CRC-16/MAXIM-DOW" {
- const Crc16MaximDow = catalog.Crc16MaximDow;
+ const Crc16MaximDow = crc.Crc16MaximDow;
try testing.expectEqual(@as(u16, 0x44c2), Crc16MaximDow.hash("123456789"));
@@ -731,7 +750,7 @@ test "CRC-16/MAXIM-DOW" {
}
test "CRC-16/MCRF4XX" {
- const Crc16Mcrf4xx = catalog.Crc16Mcrf4xx;
+ const Crc16Mcrf4xx = crc.Crc16Mcrf4xx;
try testing.expectEqual(@as(u16, 0x6f91), Crc16Mcrf4xx.hash("123456789"));
@@ -742,7 +761,7 @@ test "CRC-16/MCRF4XX" {
}
test "CRC-16/MODBUS" {
- const Crc16Modbus = catalog.Crc16Modbus;
+ const Crc16Modbus = crc.Crc16Modbus;
try testing.expectEqual(@as(u16, 0x4b37), Crc16Modbus.hash("123456789"));
@@ -753,7 +772,7 @@ test "CRC-16/MODBUS" {
}
test "CRC-16/NRSC-5" {
- const Crc16Nrsc5 = catalog.Crc16Nrsc5;
+ const Crc16Nrsc5 = crc.Crc16Nrsc5;
try testing.expectEqual(@as(u16, 0xa066), Crc16Nrsc5.hash("123456789"));
@@ -764,7 +783,7 @@ test "CRC-16/NRSC-5" {
}
test "CRC-16/OPENSAFETY-A" {
- const Crc16OpensafetyA = catalog.Crc16OpensafetyA;
+ const Crc16OpensafetyA = crc.Crc16OpensafetyA;
try testing.expectEqual(@as(u16, 0x5d38), Crc16OpensafetyA.hash("123456789"));
@@ -775,7 +794,7 @@ test "CRC-16/OPENSAFETY-A" {
}
test "CRC-16/OPENSAFETY-B" {
- const Crc16OpensafetyB = catalog.Crc16OpensafetyB;
+ const Crc16OpensafetyB = crc.Crc16OpensafetyB;
try testing.expectEqual(@as(u16, 0x20fe), Crc16OpensafetyB.hash("123456789"));
@@ -786,7 +805,7 @@ test "CRC-16/OPENSAFETY-B" {
}
test "CRC-16/PROFIBUS" {
- const Crc16Profibus = catalog.Crc16Profibus;
+ const Crc16Profibus = crc.Crc16Profibus;
try testing.expectEqual(@as(u16, 0xa819), Crc16Profibus.hash("123456789"));
@@ -797,7 +816,7 @@ test "CRC-16/PROFIBUS" {
}
test "CRC-16/RIELLO" {
- const Crc16Riello = catalog.Crc16Riello;
+ const Crc16Riello = crc.Crc16Riello;
try testing.expectEqual(@as(u16, 0x63d0), Crc16Riello.hash("123456789"));
@@ -808,7 +827,7 @@ test "CRC-16/RIELLO" {
}
test "CRC-16/SPI-FUJITSU" {
- const Crc16SpiFujitsu = catalog.Crc16SpiFujitsu;
+ const Crc16SpiFujitsu = crc.Crc16SpiFujitsu;
try testing.expectEqual(@as(u16, 0xe5cc), Crc16SpiFujitsu.hash("123456789"));
@@ -819,7 +838,7 @@ test "CRC-16/SPI-FUJITSU" {
}
test "CRC-16/T10-DIF" {
- const Crc16T10Dif = catalog.Crc16T10Dif;
+ const Crc16T10Dif = crc.Crc16T10Dif;
try testing.expectEqual(@as(u16, 0xd0db), Crc16T10Dif.hash("123456789"));
@@ -830,7 +849,7 @@ test "CRC-16/T10-DIF" {
}
test "CRC-16/TELEDISK" {
- const Crc16Teledisk = catalog.Crc16Teledisk;
+ const Crc16Teledisk = crc.Crc16Teledisk;
try testing.expectEqual(@as(u16, 0x0fb3), Crc16Teledisk.hash("123456789"));
@@ -841,7 +860,7 @@ test "CRC-16/TELEDISK" {
}
test "CRC-16/TMS37157" {
- const Crc16Tms37157 = catalog.Crc16Tms37157;
+ const Crc16Tms37157 = crc.Crc16Tms37157;
try testing.expectEqual(@as(u16, 0x26b1), Crc16Tms37157.hash("123456789"));
@@ -852,7 +871,7 @@ test "CRC-16/TMS37157" {
}
test "CRC-16/UMTS" {
- const Crc16Umts = catalog.Crc16Umts;
+ const Crc16Umts = crc.Crc16Umts;
try testing.expectEqual(@as(u16, 0xfee8), Crc16Umts.hash("123456789"));
@@ -863,7 +882,7 @@ test "CRC-16/UMTS" {
}
test "CRC-16/USB" {
- const Crc16Usb = catalog.Crc16Usb;
+ const Crc16Usb = crc.Crc16Usb;
try testing.expectEqual(@as(u16, 0xb4c8), Crc16Usb.hash("123456789"));
@@ -874,7 +893,7 @@ test "CRC-16/USB" {
}
test "CRC-16/XMODEM" {
- const Crc16Xmodem = catalog.Crc16Xmodem;
+ const Crc16Xmodem = crc.Crc16Xmodem;
try testing.expectEqual(@as(u16, 0x31c3), Crc16Xmodem.hash("123456789"));
@@ -885,7 +904,7 @@ test "CRC-16/XMODEM" {
}
test "CRC-17/CAN-FD" {
- const Crc17CanFd = catalog.Crc17CanFd;
+ const Crc17CanFd = crc.Crc17CanFd;
try testing.expectEqual(@as(u17, 0x04f03), Crc17CanFd.hash("123456789"));
@@ -896,7 +915,7 @@ test "CRC-17/CAN-FD" {
}
test "CRC-21/CAN-FD" {
- const Crc21CanFd = catalog.Crc21CanFd;
+ const Crc21CanFd = crc.Crc21CanFd;
try testing.expectEqual(@as(u21, 0x0ed841), Crc21CanFd.hash("123456789"));
@@ -907,7 +926,7 @@ test "CRC-21/CAN-FD" {
}
test "CRC-24/BLE" {
- const Crc24Ble = catalog.Crc24Ble;
+ const Crc24Ble = crc.Crc24Ble;
try testing.expectEqual(@as(u24, 0xc25a56), Crc24Ble.hash("123456789"));
@@ -918,7 +937,7 @@ test "CRC-24/BLE" {
}
test "CRC-24/FLEXRAY-A" {
- const Crc24FlexrayA = catalog.Crc24FlexrayA;
+ const Crc24FlexrayA = crc.Crc24FlexrayA;
try testing.expectEqual(@as(u24, 0x7979bd), Crc24FlexrayA.hash("123456789"));
@@ -929,7 +948,7 @@ test "CRC-24/FLEXRAY-A" {
}
test "CRC-24/FLEXRAY-B" {
- const Crc24FlexrayB = catalog.Crc24FlexrayB;
+ const Crc24FlexrayB = crc.Crc24FlexrayB;
try testing.expectEqual(@as(u24, 0x1f23b8), Crc24FlexrayB.hash("123456789"));
@@ -940,7 +959,7 @@ test "CRC-24/FLEXRAY-B" {
}
test "CRC-24/INTERLAKEN" {
- const Crc24Interlaken = catalog.Crc24Interlaken;
+ const Crc24Interlaken = crc.Crc24Interlaken;
try testing.expectEqual(@as(u24, 0xb4f3e6), Crc24Interlaken.hash("123456789"));
@@ -951,7 +970,7 @@ test "CRC-24/INTERLAKEN" {
}
test "CRC-24/LTE-A" {
- const Crc24LteA = catalog.Crc24LteA;
+ const Crc24LteA = crc.Crc24LteA;
try testing.expectEqual(@as(u24, 0xcde703), Crc24LteA.hash("123456789"));
@@ -962,7 +981,7 @@ test "CRC-24/LTE-A" {
}
test "CRC-24/LTE-B" {
- const Crc24LteB = catalog.Crc24LteB;
+ const Crc24LteB = crc.Crc24LteB;
try testing.expectEqual(@as(u24, 0x23ef52), Crc24LteB.hash("123456789"));
@@ -973,7 +992,7 @@ test "CRC-24/LTE-B" {
}
test "CRC-24/OPENPGP" {
- const Crc24Openpgp = catalog.Crc24Openpgp;
+ const Crc24Openpgp = crc.Crc24Openpgp;
try testing.expectEqual(@as(u24, 0x21cf02), Crc24Openpgp.hash("123456789"));
@@ -984,7 +1003,7 @@ test "CRC-24/OPENPGP" {
}
test "CRC-24/OS-9" {
- const Crc24Os9 = catalog.Crc24Os9;
+ const Crc24Os9 = crc.Crc24Os9;
try testing.expectEqual(@as(u24, 0x200fa5), Crc24Os9.hash("123456789"));
@@ -995,7 +1014,7 @@ test "CRC-24/OS-9" {
}
test "CRC-30/CDMA" {
- const Crc30Cdma = catalog.Crc30Cdma;
+ const Crc30Cdma = crc.Crc30Cdma;
try testing.expectEqual(@as(u30, 0x04c34abf), Crc30Cdma.hash("123456789"));
@@ -1006,7 +1025,7 @@ test "CRC-30/CDMA" {
}
test "CRC-31/PHILIPS" {
- const Crc31Philips = catalog.Crc31Philips;
+ const Crc31Philips = crc.Crc31Philips;
try testing.expectEqual(@as(u31, 0x0ce9e46c), Crc31Philips.hash("123456789"));
@@ -1017,7 +1036,7 @@ test "CRC-31/PHILIPS" {
}
test "CRC-32/AIXM" {
- const Crc32Aixm = catalog.Crc32Aixm;
+ const Crc32Aixm = crc.Crc32Aixm;
try testing.expectEqual(@as(u32, 0x3010bf7f), Crc32Aixm.hash("123456789"));
@@ -1028,7 +1047,7 @@ test "CRC-32/AIXM" {
}
test "CRC-32/AUTOSAR" {
- const Crc32Autosar = catalog.Crc32Autosar;
+ const Crc32Autosar = crc.Crc32Autosar;
try testing.expectEqual(@as(u32, 0x1697d06a), Crc32Autosar.hash("123456789"));
@@ -1039,7 +1058,7 @@ test "CRC-32/AUTOSAR" {
}
test "CRC-32/BASE91-D" {
- const Crc32Base91D = catalog.Crc32Base91D;
+ const Crc32Base91D = crc.Crc32Base91D;
try testing.expectEqual(@as(u32, 0x87315576), Crc32Base91D.hash("123456789"));
@@ -1050,7 +1069,7 @@ test "CRC-32/BASE91-D" {
}
test "CRC-32/BZIP2" {
- const Crc32Bzip2 = catalog.Crc32Bzip2;
+ const Crc32Bzip2 = crc.Crc32Bzip2;
try testing.expectEqual(@as(u32, 0xfc891918), Crc32Bzip2.hash("123456789"));
@@ -1061,7 +1080,7 @@ test "CRC-32/BZIP2" {
}
test "CRC-32/CD-ROM-EDC" {
- const Crc32CdRomEdc = catalog.Crc32CdRomEdc;
+ const Crc32CdRomEdc = crc.Crc32CdRomEdc;
try testing.expectEqual(@as(u32, 0x6ec2edc4), Crc32CdRomEdc.hash("123456789"));
@@ -1072,7 +1091,7 @@ test "CRC-32/CD-ROM-EDC" {
}
test "CRC-32/CKSUM" {
- const Crc32Cksum = catalog.Crc32Cksum;
+ const Crc32Cksum = crc.Crc32Cksum;
try testing.expectEqual(@as(u32, 0x765e7680), Crc32Cksum.hash("123456789"));
@@ -1083,7 +1102,7 @@ test "CRC-32/CKSUM" {
}
test "CRC-32/ISCSI" {
- const Crc32Iscsi = catalog.Crc32Iscsi;
+ const Crc32Iscsi = crc.Crc32Iscsi;
try testing.expectEqual(@as(u32, 0xe3069283), Crc32Iscsi.hash("123456789"));
@@ -1094,7 +1113,7 @@ test "CRC-32/ISCSI" {
}
test "CRC-32/ISO-HDLC" {
- const Crc32IsoHdlc = catalog.Crc32IsoHdlc;
+ const Crc32IsoHdlc = crc.Crc32IsoHdlc;
try testing.expectEqual(@as(u32, 0xcbf43926), Crc32IsoHdlc.hash("123456789"));
@@ -1105,7 +1124,7 @@ test "CRC-32/ISO-HDLC" {
}
test "CRC-32/JAMCRC" {
- const Crc32Jamcrc = catalog.Crc32Jamcrc;
+ const Crc32Jamcrc = crc.Crc32Jamcrc;
try testing.expectEqual(@as(u32, 0x340bc6d9), Crc32Jamcrc.hash("123456789"));
@@ -1116,7 +1135,7 @@ test "CRC-32/JAMCRC" {
}
test "CRC-32/MEF" {
- const Crc32Mef = catalog.Crc32Mef;
+ const Crc32Mef = crc.Crc32Mef;
try testing.expectEqual(@as(u32, 0xd2c22f51), Crc32Mef.hash("123456789"));
@@ -1127,7 +1146,7 @@ test "CRC-32/MEF" {
}
test "CRC-32/MPEG-2" {
- const Crc32Mpeg2 = catalog.Crc32Mpeg2;
+ const Crc32Mpeg2 = crc.Crc32Mpeg2;
try testing.expectEqual(@as(u32, 0x0376e6e7), Crc32Mpeg2.hash("123456789"));
@@ -1138,7 +1157,7 @@ test "CRC-32/MPEG-2" {
}
test "CRC-32/XFER" {
- const Crc32Xfer = catalog.Crc32Xfer;
+ const Crc32Xfer = crc.Crc32Xfer;
try testing.expectEqual(@as(u32, 0xbd0be338), Crc32Xfer.hash("123456789"));
@@ -1149,7 +1168,7 @@ test "CRC-32/XFER" {
}
test "CRC-40/GSM" {
- const Crc40Gsm = catalog.Crc40Gsm;
+ const Crc40Gsm = crc.Crc40Gsm;
try testing.expectEqual(@as(u40, 0xd4164fc646), Crc40Gsm.hash("123456789"));
@@ -1160,7 +1179,7 @@ test "CRC-40/GSM" {
}
test "CRC-64/ECMA-182" {
- const Crc64Ecma182 = catalog.Crc64Ecma182;
+ const Crc64Ecma182 = crc.Crc64Ecma182;
try testing.expectEqual(@as(u64, 0x6c40df5f0b497347), Crc64Ecma182.hash("123456789"));
@@ -1171,7 +1190,7 @@ test "CRC-64/ECMA-182" {
}
test "CRC-64/GO-ISO" {
- const Crc64GoIso = catalog.Crc64GoIso;
+ const Crc64GoIso = crc.Crc64GoIso;
try testing.expectEqual(@as(u64, 0xb90956c775a41001), Crc64GoIso.hash("123456789"));
@@ -1182,7 +1201,7 @@ test "CRC-64/GO-ISO" {
}
test "CRC-64/MS" {
- const Crc64Ms = catalog.Crc64Ms;
+ const Crc64Ms = crc.Crc64Ms;
try testing.expectEqual(@as(u64, 0x75d4b74f024eceea), Crc64Ms.hash("123456789"));
@@ -1193,7 +1212,7 @@ test "CRC-64/MS" {
}
test "CRC-64/REDIS" {
- const Crc64Redis = catalog.Crc64Redis;
+ const Crc64Redis = crc.Crc64Redis;
try testing.expectEqual(@as(u64, 0xe9c6d914c4b8d9ca), Crc64Redis.hash("123456789"));
@@ -1204,7 +1223,7 @@ test "CRC-64/REDIS" {
}
test "CRC-64/WE" {
- const Crc64We = catalog.Crc64We;
+ const Crc64We = crc.Crc64We;
try testing.expectEqual(@as(u64, 0x62ec59e3f1a4f00a), Crc64We.hash("123456789"));
@@ -1215,7 +1234,7 @@ test "CRC-64/WE" {
}
test "CRC-64/XZ" {
- const Crc64Xz = catalog.Crc64Xz;
+ const Crc64Xz = crc.Crc64Xz;
try testing.expectEqual(@as(u64, 0x995dc9bbdf1939fa), Crc64Xz.hash("123456789"));
@@ -1226,7 +1245,7 @@ test "CRC-64/XZ" {
}
test "CRC-82/DARC" {
- const Crc82Darc = catalog.Crc82Darc;
+ const Crc82Darc = crc.Crc82Darc;
try testing.expectEqual(@as(u82, 0x09ea83f625023801fd612), Crc82Darc.hash("123456789"));
diff --git a/lib/std/http/Client.zig b/lib/std/http/Client.zig
index 2cec73f281..837bdc63c7 100644
--- a/lib/std/http/Client.zig
+++ b/lib/std/http/Client.zig
@@ -771,17 +771,41 @@ pub const Request = struct {
req.client.connection_pool.release(req.client.allocator, req.connection.?);
req.connection = null;
- const protocol = protocol_map.get(uri.scheme) orelse return error.UnsupportedUrlScheme;
+ var server_header = std.heap.FixedBufferAllocator.init(req.response.parser.header_bytes_buffer);
+ defer req.response.parser.header_bytes_buffer = server_header.buffer[server_header.end_index..];
+ const protocol, const valid_uri = try validateUri(uri, server_header.allocator());
+
+ const new_host = valid_uri.host.?.raw;
+ const prev_host = req.uri.host.?.raw;
+ const keep_privileged_headers =
+ std.ascii.eqlIgnoreCase(valid_uri.scheme, req.uri.scheme) and
+ std.ascii.endsWithIgnoreCase(new_host, prev_host) and
+ (new_host.len == prev_host.len or new_host[new_host.len - prev_host.len - 1] == '.');
+ if (!keep_privileged_headers) {
+ // When redirecting to a different domain, strip privileged headers.
+ req.privileged_headers = &.{};
+ }
- const port: u16 = uri.port orelse switch (protocol) {
- .plain => 80,
- .tls => 443,
- };
+ if (switch (req.response.status) {
+ .see_other => true,
+ .moved_permanently, .found => req.method == .POST,
+ else => false,
+ }) {
+ // A redirect to a GET must change the method and remove the body.
+ req.method = .GET;
+ req.transfer_encoding = .none;
+ req.headers.content_type = .omit;
+ }
- const host = uri.host orelse return error.UriMissingHost;
+ if (req.transfer_encoding != .none) {
+ // The request body has already been sent. The request is
+ // still in a valid state, but the redirect must be handled
+ // manually.
+ return error.RedirectRequiresResend;
+ }
- req.uri = uri;
- req.connection = try req.client.connect(host, port, protocol);
+ req.uri = valid_uri;
+ req.connection = try req.client.connect(new_host, uriPort(valid_uri, protocol), protocol);
req.redirect_behavior.subtractOne();
req.response.parser.reset();
@@ -796,13 +820,8 @@ pub const Request = struct {
pub const SendError = Connection.WriteError || error{ InvalidContentLength, UnsupportedTransferEncoding };
- pub const SendOptions = struct {
- /// Specifies that the uri is already escaped.
- raw_uri: bool = false,
- };
-
/// Send the HTTP request headers to the server.
- pub fn send(req: *Request, options: SendOptions) SendError!void {
+ pub fn send(req: *Request) SendError!void {
if (!req.method.requestHasBody() and req.transfer_encoding != .none)
return error.UnsupportedTransferEncoding;
@@ -821,7 +840,6 @@ pub const Request = struct {
.authority = connection.proxied,
.path = true,
.query = true,
- .raw = options.raw_uri,
}, w);
}
try w.writeByte(' ');
@@ -1038,55 +1056,19 @@ pub const Request = struct {
const location = req.response.location orelse
return error.HttpRedirectLocationMissing;
- // This mutates the beginning of header_buffer and uses that
- // for the backing memory of the returned new_uri.
- const header_buffer = req.response.parser.header_bytes_buffer;
- const new_uri = req.uri.resolve_inplace(location, header_buffer) catch
- return error.HttpRedirectLocationInvalid;
-
- // The new URI references the beginning of header_bytes_buffer memory.
- // That memory will be kept, but everything after it will be
- // reused by the subsequent request. In other words,
- // header_bytes_buffer must be large enough to store all
- // redirect locations as well as the final request header.
- const path_end = new_uri.path.ptr + new_uri.path.len;
- // https://github.com/ziglang/zig/issues/1738
- const path_offset = @intFromPtr(path_end) - @intFromPtr(header_buffer.ptr);
- const end_offset = @max(path_offset, location.len);
- req.response.parser.header_bytes_buffer = header_buffer[end_offset..];
-
- const is_same_domain_or_subdomain =
- std.ascii.endsWithIgnoreCase(new_uri.host.?, req.uri.host.?) and
- (new_uri.host.?.len == req.uri.host.?.len or
- new_uri.host.?[new_uri.host.?.len - req.uri.host.?.len - 1] == '.');
-
- if (new_uri.host == null or !is_same_domain_or_subdomain or
- !std.ascii.eqlIgnoreCase(new_uri.scheme, req.uri.scheme))
- {
- // When redirecting to a different domain, strip privileged headers.
- req.privileged_headers = &.{};
- }
-
- if (switch (req.response.status) {
- .see_other => true,
- .moved_permanently, .found => req.method == .POST,
- else => false,
- }) {
- // A redirect to a GET must change the method and remove the body.
- req.method = .GET;
- req.transfer_encoding = .none;
- req.headers.content_type = .omit;
- }
-
- if (req.transfer_encoding != .none) {
- // The request body has already been sent. The request is
- // still in a valid state, but the redirect must be handled
- // manually.
- return error.RedirectRequiresResend;
- }
-
- try req.redirect(new_uri);
- try req.send(.{});
+ // This mutates the beginning of header_bytes_buffer and uses that
+ // for the backing memory of the returned Uri.
+ try req.redirect(req.uri.resolve_inplace(
+ location,
+ &req.response.parser.header_bytes_buffer,
+ ) catch |err| switch (err) {
+ error.UnexpectedCharacter,
+ error.InvalidFormat,
+ error.InvalidPort,
+ => return error.HttpRedirectLocationInvalid,
+ error.NoSpaceLeft => return error.HttpHeadersOversize,
+ });
+ try req.send();
} else {
req.response.skip = false;
if (!req.response.parser.done) {
@@ -1264,30 +1246,25 @@ fn createProxyFromEnvVar(arena: Allocator, env_var_names: []const []const u8) !?
};
} else return null;
- const uri = Uri.parse(content) catch try Uri.parseWithoutScheme(content);
-
- const protocol = if (uri.scheme.len == 0)
- .plain // No scheme, assume http://
- else
- protocol_map.get(uri.scheme) orelse return null; // Unknown scheme, ignore
-
- const host = uri.host orelse return error.HttpProxyMissingHost;
+ const uri = Uri.parse(content) catch try Uri.parseAfterScheme("http", content);
+ const protocol, const valid_uri = validateUri(uri, arena) catch |err| switch (err) {
+ error.UnsupportedUriScheme => return null,
+ error.UriMissingHost => return error.HttpProxyMissingHost,
+ error.OutOfMemory => |e| return e,
+ };
- const authorization: ?[]const u8 = if (uri.user != null or uri.password != null) a: {
- const authorization = try arena.alloc(u8, basic_authorization.valueLengthFromUri(uri));
- assert(basic_authorization.value(uri, authorization).len == authorization.len);
+ const authorization: ?[]const u8 = if (valid_uri.user != null or valid_uri.password != null) a: {
+ const authorization = try arena.alloc(u8, basic_authorization.valueLengthFromUri(valid_uri));
+ assert(basic_authorization.value(valid_uri, authorization).len == authorization.len);
break :a authorization;
} else null;
const proxy = try arena.create(Proxy);
proxy.* = .{
.protocol = protocol,
- .host = host,
+ .host = valid_uri.host.?.raw,
.authorization = authorization,
- .port = uri.port orelse switch (protocol) {
- .plain => 80,
- .tls => 443,
- },
+ .port = uriPort(valid_uri, protocol),
.supports_connect = true,
};
return proxy;
@@ -1305,24 +1282,26 @@ pub const basic_authorization = struct {
}
pub fn valueLengthFromUri(uri: Uri) usize {
- return valueLength(
- if (uri.user) |user| user.len else 0,
- if (uri.password) |password| password.len else 0,
- );
+ var stream = std.io.countingWriter(std.io.null_writer);
+ try stream.writer().print("{user}", .{uri.user orelse Uri.Component.empty});
+ const user_len = stream.bytes_written;
+ stream.bytes_written = 0;
+ try stream.writer().print("{password}", .{uri.password orelse Uri.Component.empty});
+ const password_len = stream.bytes_written;
+ return valueLength(@intCast(user_len), @intCast(password_len));
}
pub fn value(uri: Uri, out: []u8) []u8 {
- assert(uri.user == null or uri.user.?.len <= max_user_len);
- assert(uri.password == null or uri.password.?.len <= max_password_len);
-
- @memcpy(out[0..prefix.len], prefix);
-
var buf: [max_user_len + ":".len + max_password_len]u8 = undefined;
- const unencoded = std.fmt.bufPrint(&buf, "{s}:{s}", .{
- uri.user orelse "", uri.password orelse "",
- }) catch unreachable;
- const base64 = std.base64.standard.Encoder.encode(out[prefix.len..], unencoded);
+ var stream = std.io.fixedBufferStream(&buf);
+ stream.writer().print("{user}", .{uri.user orelse Uri.Component.empty}) catch
+ unreachable;
+ assert(stream.pos <= max_user_len);
+ stream.writer().print(":{password}", .{uri.password orelse Uri.Component.empty}) catch
+ unreachable;
+ @memcpy(out[0..prefix.len], prefix);
+ const base64 = std.base64.standard.Encoder.encode(out[prefix.len..], stream.getWritten());
return out[0 .. prefix.len + base64.len];
}
};
@@ -1337,8 +1316,7 @@ pub fn connectTcp(client: *Client, host: []const u8, port: u16, protocol: Connec
.host = host,
.port = port,
.protocol = protocol,
- })) |node|
- return node;
+ })) |node| return node;
if (disable_tls and protocol == .tls)
return error.TlsInitializationFailed;
@@ -1449,19 +1427,12 @@ pub fn connectTunnel(
client.connection_pool.release(client.allocator, conn);
}
- const uri: Uri = .{
+ var buffer: [8096]u8 = undefined;
+ var req = client.open(.CONNECT, .{
.scheme = "http",
- .user = null,
- .password = null,
- .host = tunnel_host,
+ .host = .{ .raw = tunnel_host },
.port = tunnel_port,
- .path = "",
- .query = null,
- .fragment = null,
- };
-
- var buffer: [8096]u8 = undefined;
- var req = client.open(.CONNECT, uri, .{
+ }, .{
.redirect_behavior = .unhandled,
.connection = conn,
.server_header_buffer = &buffer,
@@ -1471,7 +1442,7 @@ pub fn connectTunnel(
};
defer req.deinit();
- req.send(.{ .raw_uri = true }) catch |err| break :tunnel err;
+ req.send() catch |err| break :tunnel err;
req.wait() catch |err| break :tunnel err;
if (req.response.status.class() == .server_error) {
@@ -1500,7 +1471,7 @@ pub fn connectTunnel(
}
// Prevents a dependency loop in open()
-const ConnectErrorPartial = ConnectTcpError || error{ UnsupportedUrlScheme, ConnectionRefused };
+const ConnectErrorPartial = ConnectTcpError || error{ UnsupportedUriScheme, ConnectionRefused };
pub const ConnectError = ConnectErrorPartial || RequestError;
/// Connect to `host:port` using the specified protocol. This will reuse a
@@ -1548,7 +1519,7 @@ pub fn connect(
pub const RequestError = ConnectTcpError || ConnectErrorPartial || Request.SendError ||
std.fmt.ParseIntError || Connection.WriteError ||
error{ // TODO: file a zig fmt issue for this bad indentation
- UnsupportedUrlScheme,
+ UnsupportedUriScheme,
UriMissingHost,
CertificateBundleLoadFailure,
@@ -1598,12 +1569,28 @@ pub const RequestOptions = struct {
privileged_headers: []const http.Header = &.{},
};
-pub const protocol_map = std.ComptimeStringMap(Connection.Protocol, .{
- .{ "http", .plain },
- .{ "ws", .plain },
- .{ "https", .tls },
- .{ "wss", .tls },
-});
+fn validateUri(uri: Uri, arena: Allocator) !struct { Connection.Protocol, Uri } {
+ const protocol_map = std.ComptimeStringMap(Connection.Protocol, .{
+ .{ "http", .plain },
+ .{ "ws", .plain },
+ .{ "https", .tls },
+ .{ "wss", .tls },
+ });
+ const protocol = protocol_map.get(uri.scheme) orelse return error.UnsupportedUriScheme;
+ var valid_uri = uri;
+ // The host is always going to be needed as a raw string for hostname resolution anyway.
+ valid_uri.host = .{
+ .raw = try (uri.host orelse return error.UriMissingHost).toRawMaybeAlloc(arena),
+ };
+ return .{ protocol, valid_uri };
+}
+
+fn uriPort(uri: Uri, protocol: Connection.Protocol) u16 {
+ return uri.port orelse switch (protocol) {
+ .plain => 80,
+ .tls => 443,
+ };
+}
/// Open a connection to the host specified by `uri` and prepare to send a HTTP request.
///
@@ -1633,14 +1620,8 @@ pub fn open(
}
}
- const protocol = protocol_map.get(uri.scheme) orelse return error.UnsupportedUrlScheme;
-
- const port: u16 = uri.port orelse switch (protocol) {
- .plain => 80,
- .tls => 443,
- };
-
- const host = uri.host orelse return error.UriMissingHost;
+ var server_header = std.heap.FixedBufferAllocator.init(options.server_header_buffer);
+ const protocol, const valid_uri = try validateUri(uri, server_header.allocator());
if (protocol == .tls and @atomicLoad(bool, &client.next_https_rescan_certs, .acquire)) {
if (disable_tls) unreachable;
@@ -1649,15 +1630,17 @@ pub fn open(
defer client.ca_bundle_mutex.unlock();
if (client.next_https_rescan_certs) {
- client.ca_bundle.rescan(client.allocator) catch return error.CertificateBundleLoadFailure;
+ client.ca_bundle.rescan(client.allocator) catch
+ return error.CertificateBundleLoadFailure;
@atomicStore(bool, &client.next_https_rescan_certs, false, .release);
}
}
- const conn = options.connection orelse try client.connect(host, port, protocol);
+ const conn = options.connection orelse
+ try client.connect(valid_uri.host.?.raw, uriPort(valid_uri, protocol), protocol);
var req: Request = .{
- .uri = uri,
+ .uri = valid_uri,
.client = client,
.connection = conn,
.keep_alive = options.keep_alive,
@@ -1671,7 +1654,7 @@ pub fn open(
.status = undefined,
.reason = undefined,
.keep_alive = undefined,
- .parser = proto.HeadersParser.init(options.server_header_buffer),
+ .parser = proto.HeadersParser.init(server_header.buffer[server_header.end_index..]),
},
.headers = options.headers,
.extra_headers = options.extra_headers,
@@ -1751,7 +1734,7 @@ pub fn fetch(client: *Client, options: FetchOptions) !FetchResult {
if (options.payload) |payload| req.transfer_encoding = .{ .content_length = payload.len };
- try req.send(.{ .raw_uri = options.raw_uri });
+ try req.send();
if (options.payload) |payload| try req.writeAll(payload);
diff --git a/lib/std/http/test.zig b/lib/std/http/test.zig
index e2aa810d58..caeed0e1ea 100644
--- a/lib/std/http/test.zig
+++ b/lib/std/http/test.zig
@@ -64,7 +64,7 @@ test "trailers" {
});
defer req.deinit();
- try req.send(.{});
+ try req.send();
try req.wait();
const body = try req.reader().readAllAlloc(gpa, 8192);
@@ -474,6 +474,15 @@ test "general client/server API coverage" {
.{ .name = "location", .value = "/redirect/3" },
},
});
+ } else if (mem.eql(u8, request.head.target, "/redirect/5")) {
+ try request.respond("Hello, Redirected!\n", .{
+ .status = .found,
+ .extra_headers = &.{
+ .{ .name = "location", .value = "/%2525" },
+ },
+ });
+ } else if (mem.eql(u8, request.head.target, "/%2525")) {
+ try request.respond("Encoded redirect successful!\n", .{});
} else if (mem.eql(u8, request.head.target, "/redirect/invalid")) {
const invalid_port = try getUnusedTcpPort();
const location = try std.fmt.allocPrint(gpa, "http://127.0.0.1:{d}", .{invalid_port});
@@ -529,7 +538,7 @@ test "general client/server API coverage" {
});
defer req.deinit();
- try req.send(.{});
+ try req.send();
try req.wait();
const body = try req.reader().readAllAlloc(gpa, 8192);
@@ -554,7 +563,7 @@ test "general client/server API coverage" {
});
defer req.deinit();
- try req.send(.{});
+ try req.send();
try req.wait();
const body = try req.reader().readAllAlloc(gpa, 8192 * 1024);
@@ -578,7 +587,7 @@ test "general client/server API coverage" {
});
defer req.deinit();
- try req.send(.{});
+ try req.send();
try req.wait();
const body = try req.reader().readAllAlloc(gpa, 8192);
@@ -604,7 +613,7 @@ test "general client/server API coverage" {
});
defer req.deinit();
- try req.send(.{});
+ try req.send();
try req.wait();
const body = try req.reader().readAllAlloc(gpa, 8192);
@@ -629,7 +638,7 @@ test "general client/server API coverage" {
});
defer req.deinit();
- try req.send(.{});
+ try req.send();
try req.wait();
const body = try req.reader().readAllAlloc(gpa, 8192);
@@ -656,7 +665,7 @@ test "general client/server API coverage" {
});
defer req.deinit();
- try req.send(.{});
+ try req.send();
try req.wait();
const body = try req.reader().readAllAlloc(gpa, 8192);
@@ -684,7 +693,7 @@ test "general client/server API coverage" {
});
defer req.deinit();
- try req.send(.{});
+ try req.send();
try req.wait();
try std.testing.expectEqual(.ok, req.response.status);
@@ -725,7 +734,7 @@ test "general client/server API coverage" {
});
defer req.deinit();
- try req.send(.{});
+ try req.send();
try req.wait();
const body = try req.reader().readAllAlloc(gpa, 8192);
@@ -749,7 +758,7 @@ test "general client/server API coverage" {
});
defer req.deinit();
- try req.send(.{});
+ try req.send();
try req.wait();
const body = try req.reader().readAllAlloc(gpa, 8192);
@@ -773,7 +782,7 @@ test "general client/server API coverage" {
});
defer req.deinit();
- try req.send(.{});
+ try req.send();
try req.wait();
const body = try req.reader().readAllAlloc(gpa, 8192);
@@ -797,13 +806,34 @@ test "general client/server API coverage" {
});
defer req.deinit();
- try req.send(.{});
+ try req.send();
req.wait() catch |err| switch (err) {
error.TooManyHttpRedirects => {},
else => return err,
};
}
+ { // redirect to encoded url
+ const location = try std.fmt.allocPrint(gpa, "http://127.0.0.1:{d}/redirect/5", .{port});
+ defer gpa.free(location);
+ const uri = try std.Uri.parse(location);
+
+ log.info("{s}", .{location});
+ var server_header_buffer: [1024]u8 = undefined;
+ var req = try client.open(.GET, uri, .{
+ .server_header_buffer = &server_header_buffer,
+ });
+ defer req.deinit();
+
+ try req.send();
+ try req.wait();
+
+ const body = try req.reader().readAllAlloc(gpa, 8192);
+ defer gpa.free(body);
+
+ try expectEqualStrings("Encoded redirect successful!\n", body);
+ }
+
// connection has been kept alive
try expect(client.http_proxy != null or client.connection_pool.free_len == 1);
@@ -819,7 +849,7 @@ test "general client/server API coverage" {
});
defer req.deinit();
- try req.send(.{});
+ try req.send();
const result = req.wait();
// a proxy without an upstream is likely to return a 5xx status.
@@ -913,16 +943,16 @@ test "Server streams both reading and writing" {
var server_header_buffer: [555]u8 = undefined;
var req = try client.open(.POST, .{
.scheme = "http",
- .host = "127.0.0.1",
+ .host = .{ .raw = "127.0.0.1" },
.port = test_server.port(),
- .path = "/",
+ .path = .{ .percent_encoded = "/" },
}, .{
.server_header_buffer = &server_header_buffer,
});
defer req.deinit();
req.transfer_encoding = .chunked;
- try req.send(.{});
+ try req.send();
try req.wait();
try req.writeAll("one ");
@@ -956,7 +986,7 @@ fn echoTests(client: *http.Client, port: u16) !void {
req.transfer_encoding = .{ .content_length = 14 };
- try req.send(.{});
+ try req.send();
try req.writeAll("Hello, ");
try req.writeAll("World!\n");
try req.finish();
@@ -990,7 +1020,7 @@ fn echoTests(client: *http.Client, port: u16) !void {
req.transfer_encoding = .chunked;
- try req.send(.{});
+ try req.send();
try req.writeAll("Hello, ");
try req.writeAll("World!\n");
try req.finish();
@@ -1044,7 +1074,7 @@ fn echoTests(client: *http.Client, port: u16) !void {
req.transfer_encoding = .chunked;
- try req.send(.{});
+ try req.send();
try req.writeAll("Hello, ");
try req.writeAll("World!\n");
try req.finish();
@@ -1075,7 +1105,7 @@ fn echoTests(client: *http.Client, port: u16) !void {
req.transfer_encoding = .chunked;
- try req.send(.{});
+ try req.send();
try req.wait();
try expectEqual(.expectation_failed, req.response.status);
}
@@ -1180,7 +1210,7 @@ test "redirect to different connection" {
});
defer req.deinit();
- try req.send(.{});
+ try req.send();
try req.wait();
const body = try req.reader().readAllAlloc(gpa, 8192);
diff --git a/lib/std/io.zig b/lib/std/io.zig
index 9f0f444a83..ab89114000 100644
--- a/lib/std/io.zig
+++ b/lib/std/io.zig
@@ -413,7 +413,7 @@ pub const StreamSource = @import("io/stream_source.zig").StreamSource;
pub const tty = @import("io/tty.zig");
/// A Writer that doesn't write to anything.
-pub const null_writer = @as(NullWriter, .{ .context = {} });
+pub const null_writer: NullWriter = .{ .context = {} };
const NullWriter = Writer(void, error{}, dummyWrite);
fn dummyWrite(context: void, data: []const u8) error{}!usize {
diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig
index b564d9a99b..93ad1ccbe2 100644
--- a/lib/std/math/big/int.zig
+++ b/lib/std/math/big/int.zig
@@ -3776,19 +3776,19 @@ fn llshr(r: []Limb, a: []const Limb, shift: usize) void {
const limb_shift = shift / limb_bits;
const interior_limb_shift = @as(Log2Limb, @truncate(shift));
- var carry: Limb = 0;
var i: usize = 0;
while (i < a.len - limb_shift) : (i += 1) {
- const src_i = a.len - i - 1;
- const dst_i = src_i - limb_shift;
+ const dst_i = i;
+ const src_i = dst_i + limb_shift;
const src_digit = a[src_i];
- r[dst_i] = carry | (src_digit >> interior_limb_shift);
- carry = @call(.always_inline, math.shl, .{
+ const src_digit_next = if (src_i + 1 < a.len) a[src_i + 1] else 0;
+ const carry = @call(.always_inline, math.shl, .{
Limb,
- src_digit,
+ src_digit_next,
limb_bits - @as(Limb, @intCast(interior_limb_shift)),
});
+ r[dst_i] = carry | (src_digit >> interior_limb_shift);
}
}
diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig
index f9d7543c2b..624bdc0b83 100644
--- a/lib/std/math/big/int_test.zig
+++ b/lib/std/math/big/int_test.zig
@@ -2019,6 +2019,19 @@ test "shift-right multi" {
try a.shiftRight(&a, 63);
try a.shiftRight(&a, 2);
try testing.expect(a.eqlZero());
+
+ try a.set(0xffff0000eeee1111dddd2222cccc3333000000000000000000000);
+ try a.shiftRight(&a, 84);
+ const string = try a.toString(
+ testing.allocator,
+ 16,
+ .lower,
+ );
+ defer testing.allocator.free(string);
+ try std.testing.expectEqualStrings(
+ string,
+ "ffff0000eeee1111dddd2222cccc3333",
+ );
}
test "shift-left single" {
diff --git a/lib/std/once.zig b/lib/std/once.zig
index 2f6ee709e2..ee3a8b7a35 100644
--- a/lib/std/once.zig
+++ b/lib/std/once.zig
@@ -7,6 +7,7 @@ pub fn once(comptime f: fn () void) Once(f) {
}
/// An object that executes the function `f` just once.
+/// It is undefined behavior if `f` re-enters the same Once instance.
pub fn Once(comptime f: fn () void) type {
return struct {
done: bool = false,
@@ -51,15 +52,18 @@ test "Once executes its function just once" {
global_once.call();
} else {
var threads: [10]std.Thread = undefined;
- defer for (threads) |handle| handle.join();
+ var thread_count: usize = 0;
+ defer for (threads[0..thread_count]) |handle| handle.join();
for (&threads) |*handle| {
handle.* = try std.Thread.spawn(.{}, struct {
fn thread_fn(x: u8) void {
_ = x;
global_once.call();
+ if (global_number != 1) @panic("memory ordering bug");
}
}.thread_fn, .{0});
+ thread_count += 1;
}
}
diff --git a/lib/std/posix/test.zig b/lib/std/posix/test.zig
index 1020bef4b7..1847ceb8a1 100644
--- a/lib/std/posix/test.zig
+++ b/lib/std/posix/test.zig
@@ -839,7 +839,7 @@ test "sigaction" {
const S = struct {
var handler_called_count: u32 = 0;
- fn handler(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) void {
+ fn handler(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopaque) callconv(.C) void {
_ = ctx_ptr;
// Check that we received the correct signal.
switch (native_os) {
diff --git a/lib/std/tar.zig b/lib/std/tar.zig
index 2977bc16cc..9dc5bb4a53 100644
--- a/lib/std/tar.zig
+++ b/lib/std/tar.zig
@@ -30,7 +30,7 @@ pub const Diagnostics = struct {
errors: std.ArrayListUnmanaged(Error) = .{},
root_entries: usize = 0,
- root_dir: ?[]const u8 = null,
+ root_dir: []const u8 = "",
pub const Error = union(enum) {
unable_to_create_sym_link: struct {
@@ -55,10 +55,8 @@ pub const Diagnostics = struct {
d.root_dir = try d.allocator.dupe(u8, root_dir);
return;
}
- if (d.root_dir) |r| {
- d.allocator.free(r);
- d.root_dir = null;
- }
+ d.allocator.free(d.root_dir);
+ d.root_dir = "";
}
}
@@ -103,10 +101,7 @@ pub const Diagnostics = struct {
}
}
d.errors.deinit(d.allocator);
- if (d.root_dir) |r| {
- d.allocator.free(r);
- d.root_dir = null;
- }
+ d.allocator.free(d.root_dir);
d.* = undefined;
}
};
@@ -1060,7 +1055,7 @@ test "pipeToFileSystem root_dir" {
};
// there is no root_dir
- try testing.expect(diagnostics.root_dir == null);
+ try testing.expectEqual(0, diagnostics.root_dir.len);
try testing.expectEqual(3, diagnostics.root_entries);
}
@@ -1082,7 +1077,7 @@ test "pipeToFileSystem root_dir" {
};
// root_dir found
- try testing.expectEqualStrings("example", diagnostics.root_dir.?);
+ try testing.expectEqualStrings("example", diagnostics.root_dir);
try testing.expectEqual(1, diagnostics.root_entries);
}
}
diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig
index db082b7f8e..64e8a1c805 100644
--- a/lib/std/zig/Zir.zig
+++ b/lib/std/zig/Zir.zig
@@ -106,12 +106,8 @@ pub const NullTerminatedString = enum(u32) {
/// Given an index into `string_bytes` returns the null-terminated string found there.
pub fn nullTerminatedString(code: Zir, index: NullTerminatedString) [:0]const u8 {
- const start = @intFromEnum(index);
- var end: u32 = start;
- while (code.string_bytes[end] != 0) {
- end += 1;
- }
- return code.string_bytes[start..end :0];
+ const slice = code.string_bytes[@intFromEnum(index)..];
+ return slice[0..std.mem.indexOfScalar(u8, slice, 0).? :0];
}
pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref {
diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig
index c9fe14a1c6..af0986e0b8 100644
--- a/lib/std/zig/system.zig
+++ b/lib/std/zig/system.zig
@@ -988,9 +988,13 @@ fn detectAbiAndDynamicLinker(
// if it finds one, then instead of using /usr/bin/env as the ELF file to examine, it uses the file it references instead,
// doing the same logic recursively in case it finds another shebang line.
- // Since /usr/bin/env is hard-coded into the shebang line of many portable scripts, it's a
- // reasonably reliable path to start with.
- var file_name: []const u8 = "/usr/bin/env";
+ var file_name: []const u8 = switch (os.tag) {
+ // Since /usr/bin/env is hard-coded into the shebang line of many portable scripts, it's a
+ // reasonably reliable path to start with.
+ else => "/usr/bin/env",
+ // Haiku does not have a /usr root directory.
+ .haiku => "/bin/env",
+ };
// #! (2) + 255 (max length of shebang line since Linux 5.1) + \n (1)
var buffer: [258]u8 = undefined;
while (true) {
diff --git a/lib/std/zig/system/NativePaths.zig b/lib/std/zig/system/NativePaths.zig
index 9d9ab22812..2a50e27b0c 100644
--- a/lib/std/zig/system/NativePaths.zig
+++ b/lib/std/zig/system/NativePaths.zig
@@ -105,6 +105,13 @@ pub fn detect(arena: Allocator, native_target: std.Target) !NativePaths {
return self;
}
+ if (builtin.os.tag == .haiku) {
+ try self.addLibDir("/system/non-packaged/lib");
+ try self.addLibDir("/system/develop/lib");
+ try self.addLibDir("/system/lib");
+ return self;
+ }
+
if (builtin.os.tag != .windows and builtin.os.tag != .wasi) {
const triple = try native_target.linuxTriple(arena);