| author | |
| committer | |
| log | 750b00c642782127736eb378ec9583db2d680bb6 |
| tree | 095ef980bdd7cdaeffaa2277be775b2cb1e4a2f2 |
| parent | fa6d150441d1d8679a77c5e9a6071fa952851376 |
| parent | a0c0f9ead53dab4f558dbb51cc8a49961fc6984f |
26 files changed, 2611 insertions(+), 1170 deletions(-)
CMakeLists.txt+6| ... | @@ -55,6 +55,7 @@ set(ZIG_PREFER_CLANG_CPP_DYLIB off CACHE BOOL "Try to link against -lclang-cpp") | ... | @@ -55,6 +55,7 @@ set(ZIG_PREFER_CLANG_CPP_DYLIB off CACHE BOOL "Try to link against -lclang-cpp") |
| 55 | set(ZIG_WORKAROUND_4799 off CACHE BOOL "workaround for https://github.com/ziglang/zig/issues/4799") | 55 | set(ZIG_WORKAROUND_4799 off CACHE BOOL "workaround for https://github.com/ziglang/zig/issues/4799") |
| 56 | set(ZIG_WORKAROUND_POLLY_SO off CACHE STRING "workaround for https://github.com/ziglang/zig/issues/4799") | 56 | set(ZIG_WORKAROUND_POLLY_SO off CACHE STRING "workaround for https://github.com/ziglang/zig/issues/4799") |
| 57 | set(ZIG_USE_CCACHE off CACHE BOOL "Use ccache if available") | 57 | set(ZIG_USE_CCACHE off CACHE BOOL "Use ccache if available") |
| 58 | set(ZIG_WORKAROUND_6087 off CACHE BOOL "workaround for https://github.com/ziglang/zig/issues/6087") | ||
| 58 | 59 | ||
| 59 | if(CCACHE_PROGRAM AND ZIG_USE_CCACHE) | 60 | if(CCACHE_PROGRAM AND ZIG_USE_CCACHE) |
| 60 | SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}") | 61 | SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}") |
| ... | @@ -84,6 +85,11 @@ if(APPLE AND ZIG_STATIC) | ... | @@ -84,6 +85,11 @@ if(APPLE AND ZIG_STATIC) |
| 84 | list(APPEND LLVM_LIBRARIES "${ZLIB}") | 85 | list(APPEND LLVM_LIBRARIES "${ZLIB}") |
| 85 | endif() | 86 | endif() |
| 86 | 87 | ||
| 88 | if(APPLE AND ZIG_WORKAROUND_6087) | ||
| 89 | list(REMOVE_ITEM LLVM_LIBRARIES "-llibxml2.tbd") | ||
| 90 | list(APPEND LLVM_LIBRARIES "-lxml2") | ||
| 91 | endif() | ||
| 92 | |||
| 87 | if(APPLE AND ZIG_WORKAROUND_4799) | 93 | if(APPLE AND ZIG_WORKAROUND_4799) |
| 88 | # eg: ${CMAKE_PREFIX_PATH} could be /usr/local/opt/llvm/ | 94 | # eg: ${CMAKE_PREFIX_PATH} could be /usr/local/opt/llvm/ |
| 89 | list(APPEND LLVM_LIBRARIES "-Wl,${CMAKE_PREFIX_PATH}/lib/libPolly.a" "-Wl,${CMAKE_PREFIX_PATH}/lib/libPollyPPCG.a" "-Wl,${CMAKE_PREFIX_PATH}/lib/libPollyISL.a") | 95 | list(APPEND LLVM_LIBRARIES "-Wl,${CMAKE_PREFIX_PATH}/lib/libPolly.a" "-Wl,${CMAKE_PREFIX_PATH}/lib/libPollyPPCG.a" "-Wl,${CMAKE_PREFIX_PATH}/lib/libPollyISL.a") |
README.md+6-1| ... | @@ -73,7 +73,12 @@ or | ... | @@ -73,7 +73,12 @@ or |
| 73 | [error: unable to create target: 'Unable to find target for this triple (no targets are registered)'](https://github.com/ziglang/zig/issues/5055), | 73 | [error: unable to create target: 'Unable to find target for this triple (no targets are registered)'](https://github.com/ziglang/zig/issues/5055), |
| 74 | in which case try `-DZIG_WORKAROUND_4799=ON` | 74 | in which case try `-DZIG_WORKAROUND_4799=ON` |
| 75 | 75 | ||
| 76 | Hopefully this will be fixed upstream with LLVM 10.0.1. | 76 | This has been fixed upstream with LLVM 10.0.1. |
| 77 | |||
| 78 | Building with LLVM 10.0.1 you might run into this problem: | ||
| 79 | `ld: library not found for -llibxml2.tbd` | ||
| 80 | [Building with LLVM 10.0.1 installed via Homebrew fails](https://github.com/ziglang/zig/issues/6087), | ||
| 81 | in which case you can try `-DZIG_WORKAROUND_6087=ON`. | ||
| 77 | 82 | ||
| 78 | ##### Windows | 83 | ##### Windows |
| 79 | 84 |
doc/langref.html.in+9-16| ... | @@ -1841,7 +1841,7 @@ const Point = struct { | ... | @@ -1841,7 +1841,7 @@ const Point = struct { |
| 1841 | y: i32, | 1841 | y: i32, |
| 1842 | }; | 1842 | }; |
| 1843 | 1843 | ||
| 1844 | test "compile-time array initalization" { | 1844 | test "compile-time array initialization" { |
| 1845 | assert(fancy_array[4].x == 4); | 1845 | assert(fancy_array[4].x == 4); |
| 1846 | assert(fancy_array[4].y == 8); | 1846 | assert(fancy_array[4].y == 8); |
| 1847 | } | 1847 | } |
| ... | @@ -8468,30 +8468,23 @@ test "integer truncation" { | ... | @@ -8468,30 +8468,23 @@ test "integer truncation" { |
| 8468 | <li>{#syntax#}@TypeOf(null){#endsyntax#}</li> | 8468 | <li>{#syntax#}@TypeOf(null){#endsyntax#}</li> |
| 8469 | <li>{#link|Arrays#}</li> | 8469 | <li>{#link|Arrays#}</li> |
| 8470 | <li>{#link|Optionals#}</li> | 8470 | <li>{#link|Optionals#}</li> |
| 8471 | <li>{#link|Error Set Type#}</li> | ||
| 8471 | <li>{#link|Error Union Type#}</li> | 8472 | <li>{#link|Error Union Type#}</li> |
| 8472 | <li>{#link|Vectors#}</li> | 8473 | <li>{#link|Vectors#}</li> |
| 8473 | <li>{#link|Opaque Types#}</li> | 8474 | <li>{#link|Opaque Types#}</li> |
| 8474 | <li>AnyFrame</li> | 8475 | <li>{#link|@Frame#}</li> |
| 8475 | </ul> | 8476 | <li>{#syntax#}anyframe{#endsyntax#}</li> |
| 8476 | <p> | 8477 | <li>{#link|struct#}</li> |
| 8477 | For these types it is a | 8478 | <li>{#link|enum#}</li> |
| 8478 | <a href="https://github.com/ziglang/zig/issues/2907">TODO in the compiler to implement</a>: | 8479 | <li>{#link|Enum Literals#}</li> |
| 8479 | </p> | 8480 | <li>{#link|union#}</li> |
| 8480 | <ul> | ||
| 8481 | <li>ErrorSet</li> | ||
| 8482 | <li>Enum</li> | ||
| 8483 | <li>FnFrame</li> | ||
| 8484 | <li>EnumLiteral</li> | ||
| 8485 | </ul> | 8481 | </ul> |
| 8486 | <p> | 8482 | <p> |
| 8487 | For these types, {#syntax#}@Type{#endsyntax#} is not available. | 8483 | For these types, {#syntax#}@Type{#endsyntax#} is not available: |
| 8488 | <a href="https://github.com/ziglang/zig/issues/383">There is an open proposal to allow unions and structs</a>. | ||
| 8489 | </p> | 8484 | </p> |
| 8490 | <ul> | 8485 | <ul> |
| 8491 | <li>{#link|union#}</li> | ||
| 8492 | <li>{#link|Functions#}</li> | 8486 | <li>{#link|Functions#}</li> |
| 8493 | <li>BoundFn</li> | 8487 | <li>BoundFn</li> |
| 8494 | <li>{#link|struct#}</li> | ||
| 8495 | </ul> | 8488 | </ul> |
| 8496 | {#header_close#} | 8489 | {#header_close#} |
| 8497 | {#header_open|@typeInfo#} | 8490 | {#header_open|@typeInfo#} |
lib/std/build.zig+23-1| ... | @@ -1165,6 +1165,11 @@ pub const FileSource = union(enum) { | ... | @@ -1165,6 +1165,11 @@ pub const FileSource = union(enum) { |
| 1165 | } | 1165 | } |
| 1166 | }; | 1166 | }; |
| 1167 | 1167 | ||
| 1168 | const BuildOptionArtifactArg = struct { | ||
| 1169 | name: []const u8, | ||
| 1170 | artifact: *LibExeObjStep, | ||
| 1171 | }; | ||
| 1172 | |||
| 1168 | pub const LibExeObjStep = struct { | 1173 | pub const LibExeObjStep = struct { |
| 1169 | step: Step, | 1174 | step: Step, |
| 1170 | builder: *Builder, | 1175 | builder: *Builder, |
| ... | @@ -1210,6 +1215,7 @@ pub const LibExeObjStep = struct { | ... | @@ -1210,6 +1215,7 @@ pub const LibExeObjStep = struct { |
| 1210 | out_pdb_filename: []const u8, | 1215 | out_pdb_filename: []const u8, |
| 1211 | packages: ArrayList(Pkg), | 1216 | packages: ArrayList(Pkg), |
| 1212 | build_options_contents: std.ArrayList(u8), | 1217 | build_options_contents: std.ArrayList(u8), |
| 1218 | build_options_artifact_args: std.ArrayList(BuildOptionArtifactArg), | ||
| 1213 | system_linker_hack: bool = false, | 1219 | system_linker_hack: bool = false, |
| 1214 | 1220 | ||
| 1215 | object_src: []const u8, | 1221 | object_src: []const u8, |
| ... | @@ -1355,6 +1361,7 @@ pub const LibExeObjStep = struct { | ... | @@ -1355,6 +1361,7 @@ pub const LibExeObjStep = struct { |
| 1355 | .framework_dirs = ArrayList([]const u8).init(builder.allocator), | 1361 | .framework_dirs = ArrayList([]const u8).init(builder.allocator), |
| 1356 | .object_src = undefined, | 1362 | .object_src = undefined, |
| 1357 | .build_options_contents = std.ArrayList(u8).init(builder.allocator), | 1363 | .build_options_contents = std.ArrayList(u8).init(builder.allocator), |
| 1364 | .build_options_artifact_args = std.ArrayList(BuildOptionArtifactArg).init(builder.allocator), | ||
| 1358 | .c_std = Builder.CStd.C99, | 1365 | .c_std = Builder.CStd.C99, |
| 1359 | .override_lib_dir = null, | 1366 | .override_lib_dir = null, |
| 1360 | .main_pkg_path = null, | 1367 | .main_pkg_path = null, |
| ... | @@ -1810,6 +1817,13 @@ pub const LibExeObjStep = struct { | ... | @@ -1810,6 +1817,13 @@ pub const LibExeObjStep = struct { |
| 1810 | out.print("pub const {} = {};\n", .{ name, value }) catch unreachable; | 1817 | out.print("pub const {} = {};\n", .{ name, value }) catch unreachable; |
| 1811 | } | 1818 | } |
| 1812 | 1819 | ||
| 1820 | /// The value is the path in the cache dir. | ||
| 1821 | /// Adds a dependency automatically. | ||
| 1822 | pub fn addBuildOptionArtifact(self: *LibExeObjStep, name: []const u8, artifact: *LibExeObjStep) void { | ||
| 1823 | self.build_options_artifact_args.append(.{ .name = name, .artifact = artifact }) catch unreachable; | ||
| 1824 | self.step.dependOn(&artifact.step); | ||
| 1825 | } | ||
| 1826 | |||
| 1813 | pub fn addSystemIncludeDir(self: *LibExeObjStep, path: []const u8) void { | 1827 | pub fn addSystemIncludeDir(self: *LibExeObjStep, path: []const u8) void { |
| 1814 | self.include_dirs.append(IncludeDir{ .RawPathSystem = self.builder.dupe(path) }) catch unreachable; | 1828 | self.include_dirs.append(IncludeDir{ .RawPathSystem = self.builder.dupe(path) }) catch unreachable; |
| 1815 | } | 1829 | } |
| ... | @@ -2004,7 +2018,15 @@ pub const LibExeObjStep = struct { | ... | @@ -2004,7 +2018,15 @@ pub const LibExeObjStep = struct { |
| 2004 | } | 2018 | } |
| 2005 | } | 2019 | } |
| 2006 | 2020 | ||
| 2007 | if (self.build_options_contents.items.len > 0) { | 2021 | if (self.build_options_contents.items.len > 0 or self.build_options_artifact_args.items.len > 0) { |
| 2022 | // Render build artifact options at the last minute, now that the path is known. | ||
| 2023 | for (self.build_options_artifact_args.items) |item| { | ||
| 2024 | const out = self.build_options_contents.writer(); | ||
| 2025 | out.print("pub const {}: []const u8 = ", .{item.name}) catch unreachable; | ||
| 2026 | std.zig.renderStringLiteral(item.artifact.getOutputPath(), out) catch unreachable; | ||
| 2027 | out.writeAll(";\n") catch unreachable; | ||
| 2028 | } | ||
| 2029 | |||
| 2008 | const build_options_file = try fs.path.join( | 2030 | const build_options_file = try fs.path.join( |
| 2009 | builder.allocator, | 2031 | builder.allocator, |
| 2010 | &[_][]const u8{ builder.cache_root, builder.fmt("{}_build_options.zig", .{self.name}) }, | 2032 | &[_][]const u8{ builder.cache_root, builder.fmt("{}_build_options.zig", .{self.name}) }, |
lib/std/crypto.zig+25-6| ... | @@ -35,12 +35,23 @@ pub const onetimeauth = struct { | ... | @@ -35,12 +35,23 @@ pub const onetimeauth = struct { |
| 35 | pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305; | 35 | pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305; |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | /// A Key Derivation Function (KDF) is intended to turn a weak, human generated password into a | 38 | /// A password hashing function derives a uniform key from low-entropy input material such as passwords. |
| 39 | /// strong key, suitable for cryptographic uses. It does this by salting and stretching the | 39 | /// It is intentionally slow or expensive. |
| 40 | /// password. Salting injects non-secret random data, so that identical passwords will be converted | 40 | /// |
| 41 | /// into unique keys. Stretching applies a deliberately slow hashing function to frustrate | 41 | /// With the standard definition of a key derivation function, if a key space is small, an exhaustive search may be practical. |
| 42 | /// brute-force guessing. | 42 | /// Password hashing functions make exhaustive searches way slower or way more expensive, even when implemented on GPUs and ASICs, by using different, optionally combined strategies: |
| 43 | pub const kdf = struct { | 43 | /// |
| 44 | /// - Requiring a lot of computation cycles to complete | ||
| 45 | /// - Requiring a lot of memory to complete | ||
| 46 | /// - Requiring multiple CPU cores to complete | ||
| 47 | /// - Requiring cache-local data to complete in reasonable time | ||
| 48 | /// - Requiring large static tables | ||
| 49 | /// - Avoiding precomputations and time/memory tradeoffs | ||
| 50 | /// - Requiring multi-party computations | ||
| 51 | /// - Combining the input material with random per-entry data (salts), application-specific contexts and keys | ||
| 52 | /// | ||
| 53 | /// Password hashing functions must be used whenever sensitive data has to be directly derived from a password. | ||
| 54 | pub const pwhash = struct { | ||
| 44 | pub const pbkdf2 = @import("crypto/pbkdf2.zig").pbkdf2; | 55 | pub const pbkdf2 = @import("crypto/pbkdf2.zig").pbkdf2; |
| 45 | }; | 56 | }; |
| 46 | 57 | ||
| ... | @@ -48,6 +59,13 @@ pub const kdf = struct { | ... | @@ -48,6 +59,13 @@ pub const kdf = struct { |
| 48 | pub const core = struct { | 59 | pub const core = struct { |
| 49 | pub const aes = @import("crypto/aes.zig"); | 60 | pub const aes = @import("crypto/aes.zig"); |
| 50 | pub const Gimli = @import("crypto/gimli.zig").State; | 61 | pub const Gimli = @import("crypto/gimli.zig").State; |
| 62 | |||
| 63 | /// Modes are generic compositions to construct encryption/decryption functions from block ciphers and permutations. | ||
| 64 | /// | ||
| 65 | /// These modes are designed to be building blocks for higher-level constructions, and should generally not be used directly by applications, as they may not provide the expected properties and security guarantees. | ||
| 66 | /// | ||
| 67 | /// Most applications may want to use AEADs instead. | ||
| 68 | pub const modes = @import("crypto/modes.zig"); | ||
| 51 | }; | 69 | }; |
| 52 | 70 | ||
| 53 | /// Elliptic-curve arithmetic. | 71 | /// Elliptic-curve arithmetic. |
| ... | @@ -100,6 +118,7 @@ test "crypto" { | ... | @@ -100,6 +118,7 @@ test "crypto" { |
| 100 | _ = @import("crypto/gimli.zig"); | 118 | _ = @import("crypto/gimli.zig"); |
| 101 | _ = @import("crypto/hmac.zig"); | 119 | _ = @import("crypto/hmac.zig"); |
| 102 | _ = @import("crypto/md5.zig"); | 120 | _ = @import("crypto/md5.zig"); |
| 121 | _ = @import("crypto/modes.zig"); | ||
| 103 | _ = @import("crypto/pbkdf2.zig"); | 122 | _ = @import("crypto/pbkdf2.zig"); |
| 104 | _ = @import("crypto/poly1305.zig"); | 123 | _ = @import("crypto/poly1305.zig"); |
| 105 | _ = @import("crypto/sha1.zig"); | 124 | _ = @import("crypto/sha1.zig"); |
lib/std/crypto/aes.zig+72-638| ... | @@ -3,249 +3,44 @@ | ... | @@ -3,249 +3,44 @@ |
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. |
| 4 | // The MIT license requires this copyright notice to be included in all copies | 4 | // The MIT license requires this copyright notice to be included in all copies |
| 5 | // and substantial portions of the software. | 5 | // and substantial portions of the software. |
| 6 | // Based on Go stdlib implementation | ||
| 7 | 6 | ||
| 8 | const std = @import("../std.zig"); | 7 | const std = @import("../std.zig"); |
| 9 | const mem = std.mem; | ||
| 10 | const testing = std.testing; | 8 | const testing = std.testing; |
| 9 | const builtin = std.builtin; | ||
| 11 | 10 | ||
| 12 | // Apply sbox0 to each byte in w. | 11 | const has_aesni = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .aes); |
| 13 | fn subw(w: u32) u32 { | 12 | const has_avx = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .avx); |
| 14 | return @as(u32, sbox0[w >> 24]) << 24 | @as(u32, sbox0[w >> 16 & 0xff]) << 16 | @as(u32, sbox0[w >> 8 & 0xff]) << 8 | @as(u32, sbox0[w & 0xff]); | 13 | const impl = if (std.Target.current.cpu.arch == .x86_64 and has_aesni and has_avx) @import("aes/aesni.zig") else @import("aes/soft.zig"); |
| 15 | } | ||
| 16 | |||
| 17 | fn rotw(w: u32) u32 { | ||
| 18 | return w << 8 | w >> 24; | ||
| 19 | } | ||
| 20 | |||
| 21 | // Encrypt one block from src into dst, using the expanded key xk. | ||
| 22 | fn encryptBlock(xk: []const u32, dst: []u8, src: []const u8) void { | ||
| 23 | var s0 = mem.readIntBig(u32, src[0..4]); | ||
| 24 | var s1 = mem.readIntBig(u32, src[4..8]); | ||
| 25 | var s2 = mem.readIntBig(u32, src[8..12]); | ||
| 26 | var s3 = mem.readIntBig(u32, src[12..16]); | ||
| 27 | |||
| 28 | // First round just XORs input with key. | ||
| 29 | s0 ^= xk[0]; | ||
| 30 | s1 ^= xk[1]; | ||
| 31 | s2 ^= xk[2]; | ||
| 32 | s3 ^= xk[3]; | ||
| 33 | |||
| 34 | // Middle rounds shuffle using tables. | ||
| 35 | // Number of rounds is set by length of expanded key. | ||
| 36 | var nr = xk.len / 4 - 2; // - 2: one above, one more below | ||
| 37 | var k: usize = 4; | ||
| 38 | var t0: u32 = undefined; | ||
| 39 | var t1: u32 = undefined; | ||
| 40 | var t2: u32 = undefined; | ||
| 41 | var t3: u32 = undefined; | ||
| 42 | var r: usize = 0; | ||
| 43 | while (r < nr) : (r += 1) { | ||
| 44 | t0 = xk[k + 0] ^ te0[@truncate(u8, s0 >> 24)] ^ te1[@truncate(u8, s1 >> 16)] ^ te2[@truncate(u8, s2 >> 8)] ^ te3[@truncate(u8, s3)]; | ||
| 45 | t1 = xk[k + 1] ^ te0[@truncate(u8, s1 >> 24)] ^ te1[@truncate(u8, s2 >> 16)] ^ te2[@truncate(u8, s3 >> 8)] ^ te3[@truncate(u8, s0)]; | ||
| 46 | t2 = xk[k + 2] ^ te0[@truncate(u8, s2 >> 24)] ^ te1[@truncate(u8, s3 >> 16)] ^ te2[@truncate(u8, s0 >> 8)] ^ te3[@truncate(u8, s1)]; | ||
| 47 | t3 = xk[k + 3] ^ te0[@truncate(u8, s3 >> 24)] ^ te1[@truncate(u8, s0 >> 16)] ^ te2[@truncate(u8, s1 >> 8)] ^ te3[@truncate(u8, s2)]; | ||
| 48 | k += 4; | ||
| 49 | s0 = t0; | ||
| 50 | s1 = t1; | ||
| 51 | s2 = t2; | ||
| 52 | s3 = t3; | ||
| 53 | } | ||
| 54 | |||
| 55 | // Last round uses s-box directly and XORs to produce output. | ||
| 56 | s0 = @as(u32, sbox0[t0 >> 24]) << 24 | @as(u32, sbox0[t1 >> 16 & 0xff]) << 16 | @as(u32, sbox0[t2 >> 8 & 0xff]) << 8 | @as(u32, sbox0[t3 & 0xff]); | ||
| 57 | s1 = @as(u32, sbox0[t1 >> 24]) << 24 | @as(u32, sbox0[t2 >> 16 & 0xff]) << 16 | @as(u32, sbox0[t3 >> 8 & 0xff]) << 8 | @as(u32, sbox0[t0 & 0xff]); | ||
| 58 | s2 = @as(u32, sbox0[t2 >> 24]) << 24 | @as(u32, sbox0[t3 >> 16 & 0xff]) << 16 | @as(u32, sbox0[t0 >> 8 & 0xff]) << 8 | @as(u32, sbox0[t1 & 0xff]); | ||
| 59 | s3 = @as(u32, sbox0[t3 >> 24]) << 24 | @as(u32, sbox0[t0 >> 16 & 0xff]) << 16 | @as(u32, sbox0[t1 >> 8 & 0xff]) << 8 | @as(u32, sbox0[t2 & 0xff]); | ||
| 60 | |||
| 61 | s0 ^= xk[k + 0]; | ||
| 62 | s1 ^= xk[k + 1]; | ||
| 63 | s2 ^= xk[k + 2]; | ||
| 64 | s3 ^= xk[k + 3]; | ||
| 65 | |||
| 66 | mem.writeIntBig(u32, dst[0..4], s0); | ||
| 67 | mem.writeIntBig(u32, dst[4..8], s1); | ||
| 68 | mem.writeIntBig(u32, dst[8..12], s2); | ||
| 69 | mem.writeIntBig(u32, dst[12..16], s3); | ||
| 70 | } | ||
| 71 | |||
| 72 | // Decrypt one block from src into dst, using the expanded key xk. | ||
| 73 | pub fn decryptBlock(xk: []const u32, dst: []u8, src: []const u8) void { | ||
| 74 | var s0 = mem.readIntBig(u32, src[0..4]); | ||
| 75 | var s1 = mem.readIntBig(u32, src[4..8]); | ||
| 76 | var s2 = mem.readIntBig(u32, src[8..12]); | ||
| 77 | var s3 = mem.readIntBig(u32, src[12..16]); | ||
| 78 | |||
| 79 | // First round just XORs input with key. | ||
| 80 | s0 ^= xk[0]; | ||
| 81 | s1 ^= xk[1]; | ||
| 82 | s2 ^= xk[2]; | ||
| 83 | s3 ^= xk[3]; | ||
| 84 | |||
| 85 | // Middle rounds shuffle using tables. | ||
| 86 | // Number of rounds is set by length of expanded key. | ||
| 87 | var nr = xk.len / 4 - 2; // - 2: one above, one more below | ||
| 88 | var k: usize = 4; | ||
| 89 | var t0: u32 = undefined; | ||
| 90 | var t1: u32 = undefined; | ||
| 91 | var t2: u32 = undefined; | ||
| 92 | var t3: u32 = undefined; | ||
| 93 | var r: usize = 0; | ||
| 94 | while (r < nr) : (r += 1) { | ||
| 95 | t0 = xk[k + 0] ^ td0[@truncate(u8, s0 >> 24)] ^ td1[@truncate(u8, s3 >> 16)] ^ td2[@truncate(u8, s2 >> 8)] ^ td3[@truncate(u8, s1)]; | ||
| 96 | t1 = xk[k + 1] ^ td0[@truncate(u8, s1 >> 24)] ^ td1[@truncate(u8, s0 >> 16)] ^ td2[@truncate(u8, s3 >> 8)] ^ td3[@truncate(u8, s2)]; | ||
| 97 | t2 = xk[k + 2] ^ td0[@truncate(u8, s2 >> 24)] ^ td1[@truncate(u8, s1 >> 16)] ^ td2[@truncate(u8, s0 >> 8)] ^ td3[@truncate(u8, s3)]; | ||
| 98 | t3 = xk[k + 3] ^ td0[@truncate(u8, s3 >> 24)] ^ td1[@truncate(u8, s2 >> 16)] ^ td2[@truncate(u8, s1 >> 8)] ^ td3[@truncate(u8, s0)]; | ||
| 99 | k += 4; | ||
| 100 | s0 = t0; | ||
| 101 | s1 = t1; | ||
| 102 | s2 = t2; | ||
| 103 | s3 = t3; | ||
| 104 | } | ||
| 105 | |||
| 106 | // Last round uses s-box directly and XORs to produce output. | ||
| 107 | s0 = @as(u32, sbox1[t0 >> 24]) << 24 | @as(u32, sbox1[t3 >> 16 & 0xff]) << 16 | @as(u32, sbox1[t2 >> 8 & 0xff]) << 8 | @as(u32, sbox1[t1 & 0xff]); | ||
| 108 | s1 = @as(u32, sbox1[t1 >> 24]) << 24 | @as(u32, sbox1[t0 >> 16 & 0xff]) << 16 | @as(u32, sbox1[t3 >> 8 & 0xff]) << 8 | @as(u32, sbox1[t2 & 0xff]); | ||
| 109 | s2 = @as(u32, sbox1[t2 >> 24]) << 24 | @as(u32, sbox1[t1 >> 16 & 0xff]) << 16 | @as(u32, sbox1[t0 >> 8 & 0xff]) << 8 | @as(u32, sbox1[t3 & 0xff]); | ||
| 110 | s3 = @as(u32, sbox1[t3 >> 24]) << 24 | @as(u32, sbox1[t2 >> 16 & 0xff]) << 16 | @as(u32, sbox1[t1 >> 8 & 0xff]) << 8 | @as(u32, sbox1[t0 & 0xff]); | ||
| 111 | |||
| 112 | s0 ^= xk[k + 0]; | ||
| 113 | s1 ^= xk[k + 1]; | ||
| 114 | s2 ^= xk[k + 2]; | ||
| 115 | s3 ^= xk[k + 3]; | ||
| 116 | |||
| 117 | mem.writeIntBig(u32, dst[0..4], s0); | ||
| 118 | mem.writeIntBig(u32, dst[4..8], s1); | ||
| 119 | mem.writeIntBig(u32, dst[8..12], s2); | ||
| 120 | mem.writeIntBig(u32, dst[12..16], s3); | ||
| 121 | } | ||
| 122 | |||
| 123 | fn xorBytes(dst: []u8, a: []const u8, b: []const u8) usize { | ||
| 124 | var n = std.math.min(dst.len, std.math.min(a.len, b.len)); | ||
| 125 | for (dst[0..n]) |_, i| { | ||
| 126 | dst[i] = a[i] ^ b[i]; | ||
| 127 | } | ||
| 128 | return n; | ||
| 129 | } | ||
| 130 | |||
| 131 | pub const AES128 = AES(128); | ||
| 132 | pub const AES256 = AES(256); | ||
| 133 | |||
| 134 | fn AES(comptime keysize: usize) type { | ||
| 135 | return struct { | ||
| 136 | const Self = @This(); | ||
| 137 | |||
| 138 | pub const Encrypt = AESEncrypt(keysize); | ||
| 139 | pub const Decrypt = AESDecrypt(keysize); | ||
| 140 | |||
| 141 | const nn = (keysize / 8) + 28; | ||
| 142 | enc: Encrypt, | ||
| 143 | dec: Decrypt, | ||
| 144 | |||
| 145 | pub fn init(key: [keysize / 8]u8) Self { | ||
| 146 | var ctx: Self = undefined; | ||
| 147 | ctx.enc = Encrypt.init(key); | ||
| 148 | ctx.dec = ctx.enc.toDecrypt(); | ||
| 149 | return ctx; | ||
| 150 | } | ||
| 151 | 14 | ||
| 152 | pub fn encrypt(ctx: Self, dst: []u8, src: []const u8) void { | 15 | pub const Block = impl.Block; |
| 153 | ctx.enc.encrypt(dst, src); | 16 | pub const AESEncryptCtx = impl.AESEncryptCtx; |
| 154 | } | 17 | pub const AESDecryptCtx = impl.AESDecryptCtx; |
| 155 | pub fn decrypt(ctx: Self, dst: []u8, src: []const u8) void { | 18 | pub const AES128 = impl.AES128; |
| 156 | ctx.dec.decrypt(dst, src); | 19 | pub const AES256 = impl.AES256; |
| 157 | } | ||
| 158 | pub fn ctr(ctx: Self, dst: []u8, src: []const u8, iv: [16]u8) void { | ||
| 159 | ctx.enc.ctr(dst, src, iv); | ||
| 160 | } | ||
| 161 | }; | ||
| 162 | } | ||
| 163 | |||
| 164 | fn AESEncrypt(comptime keysize: usize) type { | ||
| 165 | return struct { | ||
| 166 | const Self = @This(); | ||
| 167 | |||
| 168 | const Decrypt = AESDecrypt(keysize); | ||
| 169 | |||
| 170 | const nn = (keysize / 8) + 28; | ||
| 171 | enc: [nn]u32, | ||
| 172 | 20 | ||
| 173 | pub fn init(key: [keysize / 8]u8) Self { | 21 | test "ctr" { |
| 174 | var ctx: Self = undefined; | 22 | // NIST SP 800-38A pp 55-58 |
| 175 | expandKeyEncrypt(&key, ctx.enc[0..]); | 23 | const ctr = @import("modes.zig").ctr; |
| 176 | return ctx; | ||
| 177 | } | ||
| 178 | |||
| 179 | pub fn toDecrypt(ctx: Self) Decrypt { | ||
| 180 | var dec: Decrypt = undefined; | ||
| 181 | expandKeyDecrypt(ctx.enc[0..], dec.dec[0..]); | ||
| 182 | return dec; | ||
| 183 | } | ||
| 184 | |||
| 185 | pub fn encrypt(ctx: Self, dst: []u8, src: []const u8) void { | ||
| 186 | encryptBlock(ctx.enc[0..], dst, src); | ||
| 187 | } | ||
| 188 | pub fn ctr(ctx: Self, dst: []u8, src: []const u8, iv: [16]u8) void { | ||
| 189 | std.debug.assert(dst.len >= src.len); | ||
| 190 | |||
| 191 | var keystream: [16]u8 = undefined; | ||
| 192 | var ctrbuf = iv; | ||
| 193 | var n: usize = 0; | ||
| 194 | while (n < src.len) { | ||
| 195 | ctx.encrypt(keystream[0..], ctrbuf[0..]); | ||
| 196 | var ctr_i = std.mem.readIntBig(u128, ctrbuf[0..]); | ||
| 197 | std.mem.writeIntBig(u128, ctrbuf[0..], ctr_i +% 1); | ||
| 198 | 24 | ||
| 199 | n += xorBytes(dst[n..], src[n..], &keystream); | 25 | const key = [_]u8{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; |
| 200 | } | 26 | const iv = [_]u8{ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; |
| 201 | } | 27 | const in = [_]u8{ |
| 28 | 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, | ||
| 29 | 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, | ||
| 30 | 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, | ||
| 31 | 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, | ||
| 202 | }; | 32 | }; |
| 203 | } | 33 | const exp_out = [_]u8{ |
| 204 | 34 | 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, | |
| 205 | fn AESDecrypt(comptime keysize: usize) type { | 35 | 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff, |
| 206 | return struct { | 36 | 0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab, |
| 207 | const Self = @This(); | 37 | 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee, |
| 208 | |||
| 209 | const nn = (keysize / 8) + 28; | ||
| 210 | dec: [nn]u32, | ||
| 211 | |||
| 212 | pub fn init(key: [keysize / 8]u8) Self { | ||
| 213 | var ctx: Self = undefined; | ||
| 214 | var enc: [nn]u32 = undefined; | ||
| 215 | expandKeyEncrypt(key[0..], enc[0..]); | ||
| 216 | expandKeyDecrypt(enc[0..], ctx.dec[0..]); | ||
| 217 | return ctx; | ||
| 218 | } | ||
| 219 | |||
| 220 | pub fn decrypt(ctx: Self, dst: []u8, src: []const u8) void { | ||
| 221 | decryptBlock(ctx.dec[0..], dst, src); | ||
| 222 | } | ||
| 223 | }; | 38 | }; |
| 224 | } | ||
| 225 | |||
| 226 | test "ctr" { | ||
| 227 | // NIST SP 800-38A pp 55-58 | ||
| 228 | { | ||
| 229 | const key = [_]u8{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; | ||
| 230 | const iv = [_]u8{ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; | ||
| 231 | const in = [_]u8{ | ||
| 232 | 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, | ||
| 233 | 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, | ||
| 234 | 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, | ||
| 235 | 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, | ||
| 236 | }; | ||
| 237 | const exp_out = [_]u8{ | ||
| 238 | 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, | ||
| 239 | 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff, | ||
| 240 | 0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab, | ||
| 241 | 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee, | ||
| 242 | }; | ||
| 243 | 39 | ||
| 244 | var out: [exp_out.len]u8 = undefined; | 40 | var out: [exp_out.len]u8 = undefined; |
| 245 | var aes = AES128.init(key); | 41 | var ctx = AES128.initEnc(key); |
| 246 | aes.ctr(out[0..], in[0..], iv); | 42 | ctr(AESEncryptCtx(AES128), ctx, out[0..], in[0..], iv, builtin.Endian.Big); |
| 247 | testing.expectEqualSlices(u8, exp_out[0..], out[0..]); | 43 | testing.expectEqualSlices(u8, exp_out[0..], out[0..]); |
| 248 | } | ||
| 249 | } | 44 | } |
| 250 | 45 | ||
| 251 | test "encrypt" { | 46 | test "encrypt" { |
| ... | @@ -256,8 +51,8 @@ test "encrypt" { | ... | @@ -256,8 +51,8 @@ test "encrypt" { |
| 256 | const exp_out = [_]u8{ 0x39, 0x25, 0x84, 0x1d, 0x02, 0xdc, 0x09, 0xfb, 0xdc, 0x11, 0x85, 0x97, 0x19, 0x6a, 0x0b, 0x32 }; | 51 | const exp_out = [_]u8{ 0x39, 0x25, 0x84, 0x1d, 0x02, 0xdc, 0x09, 0xfb, 0xdc, 0x11, 0x85, 0x97, 0x19, 0x6a, 0x0b, 0x32 }; |
| 257 | 52 | ||
| 258 | var out: [exp_out.len]u8 = undefined; | 53 | var out: [exp_out.len]u8 = undefined; |
| 259 | var aes = AES128.init(key); | 54 | var ctx = AES128.initEnc(key); |
| 260 | aes.encrypt(out[0..], in[0..]); | 55 | ctx.encrypt(out[0..], in[0..]); |
| 261 | testing.expectEqualSlices(u8, exp_out[0..], out[0..]); | 56 | testing.expectEqualSlices(u8, exp_out[0..], out[0..]); |
| 262 | } | 57 | } |
| 263 | 58 | ||
| ... | @@ -271,8 +66,8 @@ test "encrypt" { | ... | @@ -271,8 +66,8 @@ test "encrypt" { |
| 271 | const exp_out = [_]u8{ 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }; | 66 | const exp_out = [_]u8{ 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }; |
| 272 | 67 | ||
| 273 | var out: [exp_out.len]u8 = undefined; | 68 | var out: [exp_out.len]u8 = undefined; |
| 274 | var aes = AES256.init(key); | 69 | var ctx = AES256.initEnc(key); |
| 275 | aes.encrypt(out[0..], in[0..]); | 70 | ctx.encrypt(out[0..], in[0..]); |
| 276 | testing.expectEqualSlices(u8, exp_out[0..], out[0..]); | 71 | testing.expectEqualSlices(u8, exp_out[0..], out[0..]); |
| 277 | } | 72 | } |
| 278 | } | 73 | } |
| ... | @@ -285,8 +80,8 @@ test "decrypt" { | ... | @@ -285,8 +80,8 @@ test "decrypt" { |
| 285 | const exp_out = [_]u8{ 0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34 }; | 80 | const exp_out = [_]u8{ 0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34 }; |
| 286 | 81 | ||
| 287 | var out: [exp_out.len]u8 = undefined; | 82 | var out: [exp_out.len]u8 = undefined; |
| 288 | var aes = AES128.init(key); | 83 | var ctx = AES128.initDec(key); |
| 289 | aes.decrypt(out[0..], in[0..]); | 84 | ctx.decrypt(out[0..], in[0..]); |
| 290 | testing.expectEqualSlices(u8, exp_out[0..], out[0..]); | 85 | testing.expectEqualSlices(u8, exp_out[0..], out[0..]); |
| 291 | } | 86 | } |
| 292 | 87 | ||
| ... | @@ -300,413 +95,52 @@ test "decrypt" { | ... | @@ -300,413 +95,52 @@ test "decrypt" { |
| 300 | const exp_out = [_]u8{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; | 95 | const exp_out = [_]u8{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; |
| 301 | 96 | ||
| 302 | var out: [exp_out.len]u8 = undefined; | 97 | var out: [exp_out.len]u8 = undefined; |
| 303 | var aes = AES256.init(key); | 98 | var ctx = AES256.initDec(key); |
| 304 | aes.decrypt(out[0..], in[0..]); | 99 | ctx.decrypt(out[0..], in[0..]); |
| 305 | testing.expectEqualSlices(u8, exp_out[0..], out[0..]); | 100 | testing.expectEqualSlices(u8, exp_out[0..], out[0..]); |
| 306 | } | 101 | } |
| 307 | } | 102 | } |
| 308 | 103 | ||
| 309 | // Key expansion algorithm. See FIPS-197, Figure 11. | 104 | test "expand 128-bit key" { |
| 310 | fn expandKeyEncrypt(key: []const u8, enc: []u32) void { | 105 | const key = [_]u8{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; |
| 311 | var i: usize = 0; | 106 | const exp_enc = [_]*const [32:0]u8{ |
| 312 | var nk = key.len / 4; | 107 | "2b7e151628aed2a6abf7158809cf4f3c", "a0fafe1788542cb123a339392a6c7605", "f2c295f27a96b9435935807a7359f67f", "3d80477d4716fe3e1e237e446d7a883b", "ef44a541a8525b7fb671253bdb0bad00", "d4d1c6f87c839d87caf2b8bc11f915bc", "6d88a37a110b3efddbf98641ca0093fd", "4e54f70e5f5fc9f384a64fb24ea6dc4f", "ead27321b58dbad2312bf5607f8d292f", "ac7766f319fadc2128d12941575c006e", "d014f9a8c9ee2589e13f0cc8b6630ca6", |
| 313 | while (i < nk) : (i += 1) { | 108 | }; |
| 314 | enc[i] = mem.readIntBig(u32, key[4 * i ..][0..4]); | 109 | const exp_dec = [_]*const [32:0]u8{ |
| 315 | } | 110 | "2b7e151628aed2a6abf7158809cf4f3c", "a0fafe1788542cb123a339392a6c7605", "f2c295f27a96b9435935807a7359f67f", "3d80477d4716fe3e1e237e446d7a883b", "ef44a541a8525b7fb671253bdb0bad00", "d4d1c6f87c839d87caf2b8bc11f915bc", "6d88a37a110b3efddbf98641ca0093fd", "4e54f70e5f5fc9f384a64fb24ea6dc4f", "ead27321b58dbad2312bf5607f8d292f", "ac7766f319fadc2128d12941575c006e", "d014f9a8c9ee2589e13f0cc8b6630ca6", |
| 316 | while (i < enc.len) : (i += 1) { | 111 | }; |
| 317 | var t = enc[i - 1]; | 112 | const enc = AES128.initEnc(key); |
| 318 | if (i % nk == 0) { | 113 | const dec = AES128.initDec(key); |
| 319 | t = subw(rotw(t)) ^ (@as(u32, powx[i / nk - 1]) << 24); | 114 | var exp: [16]u8 = undefined; |
| 320 | } else if (nk > 6 and i % nk == 4) { | ||
| 321 | t = subw(t); | ||
| 322 | } | ||
| 323 | enc[i] = enc[i - nk] ^ t; | ||
| 324 | } | ||
| 325 | } | ||
| 326 | 115 | ||
| 327 | fn expandKeyDecrypt(enc: []const u32, dec: []u32) void { | 116 | for (enc.key_schedule.round_keys) |round_key, i| { |
| 328 | var i: usize = 0; | 117 | try std.fmt.hexToBytes(&exp, exp_enc[i]); |
| 329 | var n = enc.len; | 118 | testing.expectEqualSlices(u8, &exp, &round_key.toBytes()); |
| 330 | while (i < n) : (i += 4) { | 119 | } |
| 331 | var ei = n - i - 4; | 120 | for (enc.key_schedule.round_keys) |round_key, i| { |
| 332 | var j: usize = 0; | 121 | try std.fmt.hexToBytes(&exp, exp_dec[i]); |
| 333 | while (j < 4) : (j += 1) { | 122 | testing.expectEqualSlices(u8, &exp, &round_key.toBytes()); |
| 334 | var x = enc[ei + j]; | ||
| 335 | if (i > 0 and i + 4 < n) { | ||
| 336 | x = td0[sbox0[x >> 24]] ^ td1[sbox0[x >> 16 & 0xff]] ^ td2[sbox0[x >> 8 & 0xff]] ^ td3[sbox0[x & 0xff]]; | ||
| 337 | } | ||
| 338 | dec[i + j] = x; | ||
| 339 | } | ||
| 340 | } | 123 | } |
| 341 | } | 124 | } |
| 342 | 125 | ||
| 343 | test "expand key" { | 126 | test "expand 256-bit key" { |
| 344 | const key = [_]u8{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; | 127 | const key = [_]u8{ 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 }; |
| 345 | const exp_enc = [_]u32{ | 128 | const exp_enc = [_]*const [32:0]u8{ |
| 346 | 0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c, | 129 | "603deb1015ca71be2b73aef0857d7781", "1f352c073b6108d72d9810a30914dff4", "9ba354118e6925afa51a8b5f2067fcde", "a8b09c1a93d194cdbe49846eb75d5b9a", "d59aecb85bf3c917fee94248de8ebe96", "b5a9328a2678a647983122292f6c79b3", "812c81addadf48ba24360af2fab8b464", "98c5bfc9bebd198e268c3ba709e04214", "68007bacb2df331696e939e46c518d80", "c814e20476a9fb8a5025c02d59c58239", "de1369676ccc5a71fa2563959674ee15", "5886ca5d2e2f31d77e0af1fa27cf73c3", "749c47ab18501ddae2757e4f7401905a", "cafaaae3e4d59b349adf6acebd10190d", "fe4890d1e6188d0b046df344706c631e", |
| 347 | 0xa0fafe17, 0x88542cb1, 0x23a33939, 0x2a6c7605, | ||
| 348 | 0xf2c295f2, 0x7a96b943, 0x5935807a, 0x7359f67f, | ||
| 349 | 0x3d80477d, 0x4716fe3e, 0x1e237e44, 0x6d7a883b, | ||
| 350 | 0xef44a541, 0xa8525b7f, 0xb671253b, 0xdb0bad00, | ||
| 351 | 0xd4d1c6f8, 0x7c839d87, 0xcaf2b8bc, 0x11f915bc, | ||
| 352 | 0x6d88a37a, 0x110b3efd, 0xdbf98641, 0xca0093fd, | ||
| 353 | 0x4e54f70e, 0x5f5fc9f3, 0x84a64fb2, 0x4ea6dc4f, | ||
| 354 | 0xead27321, 0xb58dbad2, 0x312bf560, 0x7f8d292f, | ||
| 355 | 0xac7766f3, 0x19fadc21, 0x28d12941, 0x575c006e, | ||
| 356 | 0xd014f9a8, 0xc9ee2589, 0xe13f0cc8, 0xb6630ca6, | ||
| 357 | }; | 130 | }; |
| 358 | const exp_dec = [_]u32{ | 131 | const exp_dec = [_]*const [32:0]u8{ |
| 359 | 0xd014f9a8, 0xc9ee2589, 0xe13f0cc8, 0xb6630ca6, | 132 | "fe4890d1e6188d0b046df344706c631e", "ada23f4963e23b2455427c8a5c709104", "57c96cf6074f07c0706abb07137f9241", "b668b621ce40046d36a047ae0932ed8e", "34ad1e4450866b367725bcc763152946", "32526c367828b24cf8e043c33f92aa20", "c440b289642b757227a3d7f114309581", "d669a7334a7ade7a80c8f18fc772e9e3", "25ba3c22a06bc7fb4388a28333934270", "54fb808b9c137949cab22ff547ba186c", "6c3d632985d1fbd9e3e36578701be0f3", "4a7459f9c8e8f9c256a156bc8d083799", "42107758e9ec98f066329ea193f8858b", "8ec6bff6829ca03b9e49af7edba96125", "603deb1015ca71be2b73aef0857d7781", |
| 360 | 0xc7b5a63, 0x1319eafe, 0xb0398890, 0x664cfbb4, | ||
| 361 | 0xdf7d925a, 0x1f62b09d, 0xa320626e, 0xd6757324, | ||
| 362 | 0x12c07647, 0xc01f22c7, 0xbc42d2f3, 0x7555114a, | ||
| 363 | 0x6efcd876, 0xd2df5480, 0x7c5df034, 0xc917c3b9, | ||
| 364 | 0x6ea30afc, 0xbc238cf6, 0xae82a4b4, 0xb54a338d, | ||
| 365 | 0x90884413, 0xd280860a, 0x12a12842, 0x1bc89739, | ||
| 366 | 0x7c1f13f7, 0x4208c219, 0xc021ae48, 0x969bf7b, | ||
| 367 | 0xcc7505eb, 0x3e17d1ee, 0x82296c51, 0xc9481133, | ||
| 368 | 0x2b3708a7, 0xf262d405, 0xbc3ebdbf, 0x4b617d62, | ||
| 369 | 0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x9cf4f3c, | ||
| 370 | }; | 133 | }; |
| 371 | var enc: [exp_enc.len]u32 = undefined; | 134 | const enc = AES256.initEnc(key); |
| 372 | var dec: [exp_dec.len]u32 = undefined; | 135 | const dec = AES256.initDec(key); |
| 373 | expandKeyEncrypt(key[0..], enc[0..]); | 136 | var exp: [16]u8 = undefined; |
| 374 | expandKeyDecrypt(enc[0..], dec[0..]); | ||
| 375 | testing.expectEqualSlices(u32, exp_enc[0..], enc[0..]); | ||
| 376 | testing.expectEqualSlices(u32, exp_dec[0..], dec[0..]); | ||
| 377 | } | ||
| 378 | 137 | ||
| 379 | // constants | 138 | for (enc.key_schedule.round_keys) |round_key, i| { |
| 380 | 139 | try std.fmt.hexToBytes(&exp, exp_enc[i]); | |
| 381 | const poly = 1 << 8 | 1 << 4 | 1 << 3 | 1 << 1 | 1 << 0; | 140 | testing.expectEqualSlices(u8, &exp, &round_key.toBytes()); |
| 382 | 141 | } | |
| 383 | const powx = [16]u8{ | 142 | for (dec.key_schedule.round_keys) |round_key, i| { |
| 384 | 0x01, | 143 | try std.fmt.hexToBytes(&exp, exp_dec[i]); |
| 385 | 0x02, | 144 | testing.expectEqualSlices(u8, &exp, &round_key.toBytes()); |
| 386 | 0x04, | 145 | } |
| 387 | 0x08, | 146 | } |
| 388 | 0x10, | ||
| 389 | 0x20, | ||
| 390 | 0x40, | ||
| 391 | 0x80, | ||
| 392 | 0x1b, | ||
| 393 | 0x36, | ||
| 394 | 0x6c, | ||
| 395 | 0xd8, | ||
| 396 | 0xab, | ||
| 397 | 0x4d, | ||
| 398 | 0x9a, | ||
| 399 | 0x2f, | ||
| 400 | }; | ||
| 401 | |||
| 402 | const sbox0 = [256]u8{ | ||
| 403 | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, | ||
| 404 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, | ||
| 405 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, | ||
| 406 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, | ||
| 407 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, | ||
| 408 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, | ||
| 409 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, | ||
| 410 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, | ||
| 411 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, | ||
| 412 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, | ||
| 413 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, | ||
| 414 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, | ||
| 415 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, | ||
| 416 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, | ||
| 417 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, | ||
| 418 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, | ||
| 419 | }; | ||
| 420 | |||
| 421 | const sbox1 = [256]u8{ | ||
| 422 | 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, | ||
| 423 | 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, | ||
| 424 | 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, | ||
| 425 | 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, | ||
| 426 | 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, | ||
| 427 | 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, | ||
| 428 | 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, | ||
| 429 | 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, | ||
| 430 | 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, | ||
| 431 | 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, | ||
| 432 | 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, | ||
| 433 | 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, | ||
| 434 | 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, | ||
| 435 | 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, | ||
| 436 | 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, | ||
| 437 | 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, | ||
| 438 | }; | ||
| 439 | |||
| 440 | const te0 = [256]u32{ | ||
| 441 | 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, | ||
| 442 | 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, | ||
| 443 | 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, | ||
| 444 | 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, | ||
| 445 | 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, | ||
| 446 | 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, | ||
| 447 | 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, | ||
| 448 | 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, | ||
| 449 | 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, | ||
| 450 | 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, | ||
| 451 | 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, | ||
| 452 | 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, | ||
| 453 | 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, | ||
| 454 | 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, | ||
| 455 | 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, | ||
| 456 | 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, | ||
| 457 | 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, | ||
| 458 | 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, | ||
| 459 | 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, | ||
| 460 | 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, | ||
| 461 | 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, | ||
| 462 | 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, | ||
| 463 | 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, | ||
| 464 | 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, | ||
| 465 | 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, | ||
| 466 | 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, | ||
| 467 | 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, | ||
| 468 | 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, | ||
| 469 | 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, | ||
| 470 | 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, | ||
| 471 | 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, | ||
| 472 | 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a, | ||
| 473 | }; | ||
| 474 | const te1 = [256]u32{ | ||
| 475 | 0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, | ||
| 476 | 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, | ||
| 477 | 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, | ||
| 478 | 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, | ||
| 479 | 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, | ||
| 480 | 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, | ||
| 481 | 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, | ||
| 482 | 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, | ||
| 483 | 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, | ||
| 484 | 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, | ||
| 485 | 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, | ||
| 486 | 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, | ||
| 487 | 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, | ||
| 488 | 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, | ||
| 489 | 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, | ||
| 490 | 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, | ||
| 491 | 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, | ||
| 492 | 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, | ||
| 493 | 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, | ||
| 494 | 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, | ||
| 495 | 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, | ||
| 496 | 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, | ||
| 497 | 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, | ||
| 498 | 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, | ||
| 499 | 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, | ||
| 500 | 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, | ||
| 501 | 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, | ||
| 502 | 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, | ||
| 503 | 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, | ||
| 504 | 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, | ||
| 505 | 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, | ||
| 506 | 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616, | ||
| 507 | }; | ||
| 508 | const te2 = [256]u32{ | ||
| 509 | 0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, | ||
| 510 | 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, | ||
| 511 | 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, | ||
| 512 | 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, | ||
| 513 | 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, | ||
| 514 | 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, | ||
| 515 | 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, | ||
| 516 | 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, | ||
| 517 | 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, | ||
| 518 | 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, | ||
| 519 | 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, | ||
| 520 | 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, | ||
| 521 | 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, | ||
| 522 | 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, | ||
| 523 | 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, | ||
| 524 | 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, | ||
| 525 | 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, | ||
| 526 | 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, | ||
| 527 | 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, | ||
| 528 | 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, | ||
| 529 | 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, | ||
| 530 | 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, | ||
| 531 | 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, | ||
| 532 | 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, | ||
| 533 | 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, | ||
| 534 | 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, | ||
| 535 | 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, | ||
| 536 | 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, | ||
| 537 | 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, | ||
| 538 | 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, | ||
| 539 | 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, | ||
| 540 | 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16, | ||
| 541 | }; | ||
| 542 | const te3 = [256]u32{ | ||
| 543 | 0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, | ||
| 544 | 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, | ||
| 545 | 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, | ||
| 546 | 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, | ||
| 547 | 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, | ||
| 548 | 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, | ||
| 549 | 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, | ||
| 550 | 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, | ||
| 551 | 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, | ||
| 552 | 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, | ||
| 553 | 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, | ||
| 554 | 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, | ||
| 555 | 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, | ||
| 556 | 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, | ||
| 557 | 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, | ||
| 558 | 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, | ||
| 559 | 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, | ||
| 560 | 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, | ||
| 561 | 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, | ||
| 562 | 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, | ||
| 563 | 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, | ||
| 564 | 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, | ||
| 565 | 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, | ||
| 566 | 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, | ||
| 567 | 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, | ||
| 568 | 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, | ||
| 569 | 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, | ||
| 570 | 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, | ||
| 571 | 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, | ||
| 572 | 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, | ||
| 573 | 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, | ||
| 574 | 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c, | ||
| 575 | }; | ||
| 576 | |||
| 577 | const td0 = [256]u32{ | ||
| 578 | 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, | ||
| 579 | 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, | ||
| 580 | 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, | ||
| 581 | 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, | ||
| 582 | 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, | ||
| 583 | 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, | ||
| 584 | 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, | ||
| 585 | 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, | ||
| 586 | 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, | ||
| 587 | 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, | ||
| 588 | 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, | ||
| 589 | 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, | ||
| 590 | 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, | ||
| 591 | 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, | ||
| 592 | 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, | ||
| 593 | 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, | ||
| 594 | 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, | ||
| 595 | 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, | ||
| 596 | 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, | ||
| 597 | 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, | ||
| 598 | 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, | ||
| 599 | 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, | ||
| 600 | 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, | ||
| 601 | 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, | ||
| 602 | 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, | ||
| 603 | 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, | ||
| 604 | 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, | ||
| 605 | 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, | ||
| 606 | 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, | ||
| 607 | 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, | ||
| 608 | 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, | ||
| 609 | 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742, | ||
| 610 | }; | ||
| 611 | const td1 = [256]u32{ | ||
| 612 | 0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, | ||
| 613 | 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, | ||
| 614 | 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, | ||
| 615 | 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, | ||
| 616 | 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, | ||
| 617 | 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, | ||
| 618 | 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, | ||
| 619 | 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, | ||
| 620 | 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, | ||
| 621 | 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, | ||
| 622 | 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, | ||
| 623 | 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, | ||
| 624 | 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, | ||
| 625 | 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, | ||
| 626 | 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, | ||
| 627 | 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, | ||
| 628 | 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, | ||
| 629 | 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, | ||
| 630 | 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, | ||
| 631 | 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, | ||
| 632 | 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, | ||
| 633 | 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, | ||
| 634 | 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, | ||
| 635 | 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, | ||
| 636 | 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, | ||
| 637 | 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, | ||
| 638 | 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, | ||
| 639 | 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, | ||
| 640 | 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, | ||
| 641 | 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, | ||
| 642 | 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, | ||
| 643 | 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857, | ||
| 644 | }; | ||
| 645 | const td2 = [256]u32{ | ||
| 646 | 0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, | ||
| 647 | 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, | ||
| 648 | 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, | ||
| 649 | 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, | ||
| 650 | 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, | ||
| 651 | 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, | ||
| 652 | 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, | ||
| 653 | 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, | ||
| 654 | 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, | ||
| 655 | 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, | ||
| 656 | 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, | ||
| 657 | 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, | ||
| 658 | 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, | ||
| 659 | 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, | ||
| 660 | 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, | ||
| 661 | 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, | ||
| 662 | 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, | ||
| 663 | 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, | ||
| 664 | 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, | ||
| 665 | 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, | ||
| 666 | 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, | ||
| 667 | 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, | ||
| 668 | 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, | ||
| 669 | 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, | ||
| 670 | 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, | ||
| 671 | 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, | ||
| 672 | 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, | ||
| 673 | 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, | ||
| 674 | 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, | ||
| 675 | 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, | ||
| 676 | 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, | ||
| 677 | 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8, | ||
| 678 | }; | ||
| 679 | const td3 = [256]u32{ | ||
| 680 | 0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, | ||
| 681 | 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, | ||
| 682 | 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, | ||
| 683 | 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, | ||
| 684 | 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, | ||
| 685 | 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, | ||
| 686 | 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, | ||
| 687 | 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, | ||
| 688 | 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, | ||
| 689 | 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, | ||
| 690 | 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, | ||
| 691 | 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, | ||
| 692 | 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, | ||
| 693 | 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, | ||
| 694 | 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, | ||
| 695 | 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, | ||
| 696 | 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, | ||
| 697 | 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, | ||
| 698 | 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, | ||
| 699 | 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, | ||
| 700 | 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, | ||
| 701 | 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, | ||
| 702 | 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, | ||
| 703 | 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, | ||
| 704 | 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, | ||
| 705 | 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, | ||
| 706 | 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, | ||
| 707 | 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, | ||
| 708 | 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, | ||
| 709 | 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, | ||
| 710 | 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, | ||
| 711 | 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0, | ||
| 712 | }; |
lib/std/crypto/aes/aesni.zig created+420| ... | @@ -0,0 +1,420 @@ | ||
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 6 | // Based on Go stdlib implementation | ||
| 7 | |||
| 8 | const std = @import("../../std.zig"); | ||
| 9 | const mem = std.mem; | ||
| 10 | const debug = std.debug; | ||
| 11 | const Vector = std.meta.Vector; | ||
| 12 | |||
| 13 | const BlockVec = Vector(2, u64); | ||
| 14 | |||
| 15 | /// A single AES block. | ||
| 16 | pub const Block = struct { | ||
| 17 | pub const block_size: usize = 16; | ||
| 18 | |||
| 19 | /// Internal representation of a block. | ||
| 20 | repr: BlockVec, | ||
| 21 | |||
| 22 | /// Convert a byte sequence into an internal representation. | ||
| 23 | pub inline fn fromBytes(bytes: *const [16]u8) Block { | ||
| 24 | const repr = mem.bytesToValue(BlockVec, bytes); | ||
| 25 | return Block{ .repr = repr }; | ||
| 26 | } | ||
| 27 | |||
| 28 | /// Convert the internal representation of a block into a byte sequence. | ||
| 29 | pub inline fn toBytes(block: Block) [16]u8 { | ||
| 30 | return mem.toBytes(block.repr); | ||
| 31 | } | ||
| 32 | |||
| 33 | /// XOR the block with a byte sequence. | ||
| 34 | pub inline fn xorBytes(block: Block, bytes: *const [16]u8) [16]u8 { | ||
| 35 | const x = block.repr ^ fromBytes(bytes).repr; | ||
| 36 | return mem.toBytes(x); | ||
| 37 | } | ||
| 38 | |||
| 39 | /// Encrypt a block with a round key. | ||
| 40 | pub inline fn encrypt(block: Block, round_key: Block) Block { | ||
| 41 | return Block{ | ||
| 42 | .repr = asm ( | ||
| 43 | \\ vaesenc %[rk], %[in], %[out] | ||
| 44 | : [out] "=x" (-> BlockVec) | ||
| 45 | : [in] "x" (block.repr), | ||
| 46 | [rk] "x" (round_key.repr) | ||
| 47 | ), | ||
| 48 | }; | ||
| 49 | } | ||
| 50 | |||
| 51 | /// Encrypt a block with the last round key. | ||
| 52 | pub inline fn encryptLast(block: Block, round_key: Block) Block { | ||
| 53 | return Block{ | ||
| 54 | .repr = asm ( | ||
| 55 | \\ vaesenclast %[rk], %[in], %[out] | ||
| 56 | : [out] "=x" (-> BlockVec) | ||
| 57 | : [in] "x" (block.repr), | ||
| 58 | [rk] "x" (round_key.repr) | ||
| 59 | ), | ||
| 60 | }; | ||
| 61 | } | ||
| 62 | |||
| 63 | /// Decrypt a block with a round key. | ||
| 64 | pub inline fn decrypt(block: Block, inv_round_key: Block) Block { | ||
| 65 | return Block{ | ||
| 66 | .repr = asm ( | ||
| 67 | \\ vaesdec %[rk], %[in], %[out] | ||
| 68 | : [out] "=x" (-> BlockVec) | ||
| 69 | : [in] "x" (block.repr), | ||
| 70 | [rk] "x" (inv_round_key.repr) | ||
| 71 | ), | ||
| 72 | }; | ||
| 73 | } | ||
| 74 | |||
| 75 | /// Decrypt a block with the last round key. | ||
| 76 | pub inline fn decryptLast(block: Block, inv_round_key: Block) Block { | ||
| 77 | return Block{ | ||
| 78 | .repr = asm ( | ||
| 79 | \\ vaesdeclast %[rk], %[in], %[out] | ||
| 80 | : [out] "=x" (-> BlockVec) | ||
| 81 | : [in] "x" (block.repr), | ||
| 82 | [rk] "x" (inv_round_key.repr) | ||
| 83 | ), | ||
| 84 | }; | ||
| 85 | } | ||
| 86 | |||
| 87 | /// XOR the content of two blocks. | ||
| 88 | pub inline fn xor(block1: Block, block2: Block) Block { | ||
| 89 | return Block{ .repr = block1.repr ^ block2.repr }; | ||
| 90 | } | ||
| 91 | |||
| 92 | /// Perform operations on multiple blocks in parallel. | ||
| 93 | pub const parallel = struct { | ||
| 94 | /// The recommended number of AES encryption/decryption to perform in parallel for the chosen implementation. | ||
| 95 | pub const optimal_parallel_blocks = 8; | ||
| 96 | |||
| 97 | /// Encrypt multiple blocks in parallel, each their own round key. | ||
| 98 | pub inline fn encryptParallel(comptime count: usize, blocks: [count]Block, round_keys: [count]Block) [count]Block { | ||
| 99 | comptime var i = 0; | ||
| 100 | var out: [count]Block = undefined; | ||
| 101 | inline while (i < count) : (i += 1) { | ||
| 102 | out[i] = blocks[i].encrypt(round_keys[i]); | ||
| 103 | } | ||
| 104 | return out; | ||
| 105 | } | ||
| 106 | |||
| 107 | /// Decrypt multiple blocks in parallel, each their own round key. | ||
| 108 | pub inline fn decryptParallel(comptime count: usize, blocks: [count]Block, round_keys: [count]Block) [count]Block { | ||
| 109 | comptime var i = 0; | ||
| 110 | var out: [count]Block = undefined; | ||
| 111 | inline while (i < count) : (i += 1) { | ||
| 112 | out[i] = blocks[i].decrypt(round_keys[i]); | ||
| 113 | } | ||
| 114 | return out; | ||
| 115 | } | ||
| 116 | |||
| 117 | /// Encrypt multple blocks in parallel with the same round key. | ||
| 118 | pub inline fn encryptWide(comptime count: usize, blocks: [count]Block, round_key: Block) [count]Block { | ||
| 119 | comptime var i = 0; | ||
| 120 | var out: [count]Block = undefined; | ||
| 121 | inline while (i < count) : (i += 1) { | ||
| 122 | out[i] = blocks[i].encrypt(round_key); | ||
| 123 | } | ||
| 124 | return out; | ||
| 125 | } | ||
| 126 | |||
| 127 | /// Decrypt multple blocks in parallel with the same round key. | ||
| 128 | pub inline fn decryptWide(comptime count: usize, blocks: [count]Block, round_key: Block) [count]Block { | ||
| 129 | comptime var i = 0; | ||
| 130 | var out: [count]Block = undefined; | ||
| 131 | inline while (i < count) : (i += 1) { | ||
| 132 | out[i] = blocks[i].decrypt(round_key); | ||
| 133 | } | ||
| 134 | return out; | ||
| 135 | } | ||
| 136 | |||
| 137 | /// Encrypt multple blocks in parallel with the same last round key. | ||
| 138 | pub inline fn encryptLastWide(comptime count: usize, blocks: [count]Block, round_key: Block) [count]Block { | ||
| 139 | comptime var i = 0; | ||
| 140 | var out: [count]Block = undefined; | ||
| 141 | inline while (i < count) : (i += 1) { | ||
| 142 | out[i] = blocks[i].encryptLast(round_key); | ||
| 143 | } | ||
| 144 | return out; | ||
| 145 | } | ||
| 146 | |||
| 147 | /// Decrypt multple blocks in parallel with the same last round key. | ||
| 148 | pub inline fn decryptLastWide(comptime count: usize, blocks: [count]Block, round_key: Block) [count]Block { | ||
| 149 | comptime var i = 0; | ||
| 150 | var out: [count]Block = undefined; | ||
| 151 | inline while (i < count) : (i += 1) { | ||
| 152 | out[i] = blocks[i].decryptLast(round_key); | ||
| 153 | } | ||
| 154 | return out; | ||
| 155 | } | ||
| 156 | }; | ||
| 157 | }; | ||
| 158 | |||
| 159 | fn KeySchedule(comptime AES: type) type { | ||
| 160 | std.debug.assert(AES.rounds == 10 or AES.rounds == 14); | ||
| 161 | const rounds = AES.rounds; | ||
| 162 | |||
| 163 | return struct { | ||
| 164 | const Self = @This(); | ||
| 165 | round_keys: [rounds + 1]Block, | ||
| 166 | |||
| 167 | fn drc(comptime second: bool, comptime rc: u8, t: BlockVec, tx: BlockVec) BlockVec { | ||
| 168 | var s: BlockVec = undefined; | ||
| 169 | var ts: BlockVec = undefined; | ||
| 170 | return asm ( | ||
| 171 | \\ vaeskeygenassist %[rc], %[t], %[s] | ||
| 172 | \\ vpslldq $4, %[tx], %[ts] | ||
| 173 | \\ vpxor %[ts], %[tx], %[r] | ||
| 174 | \\ vpslldq $8, %[r], %[ts] | ||
| 175 | \\ vpxor %[ts], %[r], %[r] | ||
| 176 | \\ vpshufd %[mask], %[s], %[ts] | ||
| 177 | \\ vpxor %[ts], %[r], %[r] | ||
| 178 | : [r] "=&x" (-> BlockVec), | ||
| 179 | [s] "=&x" (s), | ||
| 180 | [ts] "=&x" (ts) | ||
| 181 | : [rc] "n" (rc), | ||
| 182 | [t] "x" (t), | ||
| 183 | [tx] "x" (tx), | ||
| 184 | [mask] "n" (@as(u8, if (second) 0xaa else 0xff)) | ||
| 185 | ); | ||
| 186 | } | ||
| 187 | |||
| 188 | fn expand128(t1: *Block) Self { | ||
| 189 | var round_keys: [11]Block = undefined; | ||
| 190 | const rcs = [_]u8{ 1, 2, 4, 8, 16, 32, 64, 128, 27, 54 }; | ||
| 191 | inline for (rcs) |rc, round| { | ||
| 192 | round_keys[round] = t1.*; | ||
| 193 | t1.repr = drc(false, rc, t1.repr, t1.repr); | ||
| 194 | } | ||
| 195 | round_keys[rcs.len] = t1.*; | ||
| 196 | return Self{ .round_keys = round_keys }; | ||
| 197 | } | ||
| 198 | |||
| 199 | fn expand256(t1: *Block, t2: *Block) Self { | ||
| 200 | var round_keys: [15]Block = undefined; | ||
| 201 | const rcs = [_]u8{ 1, 2, 4, 8, 16, 32 }; | ||
| 202 | round_keys[0] = t1.*; | ||
| 203 | inline for (rcs) |rc, round| { | ||
| 204 | round_keys[round * 2 + 1] = t2.*; | ||
| 205 | t1.repr = drc(false, rc, t2.repr, t1.repr); | ||
| 206 | round_keys[round * 2 + 2] = t1.*; | ||
| 207 | t2.repr = drc(true, rc, t1.repr, t2.repr); | ||
| 208 | } | ||
| 209 | round_keys[rcs.len * 2 + 1] = t2.*; | ||
| 210 | t1.repr = drc(false, 64, t2.repr, t1.repr); | ||
| 211 | round_keys[rcs.len * 2 + 2] = t1.*; | ||
| 212 | return Self{ .round_keys = round_keys }; | ||
| 213 | } | ||
| 214 | |||
| 215 | /// Invert the key schedule. | ||
| 216 | pub fn invert(key_schedule: Self) Self { | ||
| 217 | const round_keys = &key_schedule.round_keys; | ||
| 218 | var inv_round_keys: [rounds + 1]Block = undefined; | ||
| 219 | inv_round_keys[0] = round_keys[rounds]; | ||
| 220 | comptime var i = 1; | ||
| 221 | inline while (i < rounds) : (i += 1) { | ||
| 222 | inv_round_keys[i] = Block{ | ||
| 223 | .repr = asm ( | ||
| 224 | \\ vaesimc %[rk], %[inv_rk] | ||
| 225 | : [inv_rk] "=x" (-> BlockVec) | ||
| 226 | : [rk] "x" (round_keys[rounds - i].repr) | ||
| 227 | ), | ||
| 228 | }; | ||
| 229 | } | ||
| 230 | inv_round_keys[rounds] = round_keys[0]; | ||
| 231 | return Self{ .round_keys = inv_round_keys }; | ||
| 232 | } | ||
| 233 | }; | ||
| 234 | } | ||
| 235 | |||
| 236 | /// A context to perform encryption using the standard AES key schedule. | ||
| 237 | pub fn AESEncryptCtx(comptime AES: type) type { | ||
| 238 | std.debug.assert(AES.key_bits == 128 or AES.key_bits == 256); | ||
| 239 | const rounds = AES.rounds; | ||
| 240 | |||
| 241 | return struct { | ||
| 242 | const Self = @This(); | ||
| 243 | pub const block = AES.block; | ||
| 244 | pub const block_size = block.block_size; | ||
| 245 | key_schedule: KeySchedule(AES), | ||
| 246 | |||
| 247 | /// Create a new encryption context with the given key. | ||
| 248 | pub fn init(key: [AES.key_bits / 8]u8) Self { | ||
| 249 | var t1 = Block.fromBytes(key[0..16]); | ||
| 250 | const key_schedule = if (AES.key_bits == 128) ks: { | ||
| 251 | break :ks KeySchedule(AES).expand128(&t1); | ||
| 252 | } else ks: { | ||
| 253 | var t2 = Block.fromBytes(key[16..32]); | ||
| 254 | break :ks KeySchedule(AES).expand256(&t1, &t2); | ||
| 255 | }; | ||
| 256 | return Self{ | ||
| 257 | .key_schedule = key_schedule, | ||
| 258 | }; | ||
| 259 | } | ||
| 260 | |||
| 261 | /// Encrypt a single block. | ||
| 262 | pub fn encrypt(ctx: Self, dst: *[16]u8, src: *const [16]u8) void { | ||
| 263 | const round_keys = ctx.key_schedule.round_keys; | ||
| 264 | var t = Block.fromBytes(src).xor(round_keys[0]); | ||
| 265 | comptime var i = 1; | ||
| 266 | inline while (i < rounds) : (i += 1) { | ||
| 267 | t = t.encrypt(round_keys[i]); | ||
| 268 | } | ||
| 269 | t = t.encryptLast(round_keys[rounds]); | ||
| 270 | dst.* = t.toBytes(); | ||
| 271 | } | ||
| 272 | |||
| 273 | /// Encrypt+XOR a single block. | ||
| 274 | pub fn xor(ctx: Self, dst: *[16]u8, src: *const [16]u8, counter: [16]u8) void { | ||
| 275 | const round_keys = ctx.key_schedule.round_keys; | ||
| 276 | var t = Block.fromBytes(&counter).xor(round_keys[0]); | ||
| 277 | comptime var i = 1; | ||
| 278 | inline while (i < rounds) : (i += 1) { | ||
| 279 | t = t.encrypt(round_keys[i]); | ||
| 280 | } | ||
| 281 | t = t.encryptLast(round_keys[rounds]); | ||
| 282 | dst.* = t.xorBytes(src); | ||
| 283 | } | ||
| 284 | |||
| 285 | /// Encrypt multiple blocks, possibly leveraging parallelization. | ||
| 286 | pub fn encryptWide(ctx: Self, comptime count: usize, dst: *[16 * count]u8, src: *const [16 * count]u8) void { | ||
| 287 | const round_keys = ctx.key_schedule.round_keys; | ||
| 288 | var ts: [count]Block = undefined; | ||
| 289 | comptime var j = 0; | ||
| 290 | inline while (j < count) : (j += 1) { | ||
| 291 | ts[j] = Block.fromBytes(src[j * 16 .. j * 16 + 16][0..16]).xor(round_keys[0]); | ||
| 292 | } | ||
| 293 | comptime var i = 1; | ||
| 294 | inline while (i < rounds) : (i += 1) { | ||
| 295 | ts = Block.parallel.encryptWide(count, ts, round_keys[i]); | ||
| 296 | } | ||
| 297 | i = 1; | ||
| 298 | inline while (i < count) : (i += 1) { | ||
| 299 | ts = Block.parallel.encryptLastWide(count, ts, round_keys[i]); | ||
| 300 | } | ||
| 301 | j = 0; | ||
| 302 | inline while (j < count) : (j += 1) { | ||
| 303 | dst[16 * j .. 16 * j + 16].* = ts[j].toBytes(); | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | /// Encrypt+XOR multiple blocks, possibly leveraging parallelization. | ||
| 308 | pub fn xorWide(ctx: Self, comptime count: usize, dst: *[16 * count]u8, src: *const [16 * count]u8, counters: [16 * count]u8) void { | ||
| 309 | const round_keys = ctx.key_schedule.round_keys; | ||
| 310 | var ts: [count]Block = undefined; | ||
| 311 | comptime var j = 0; | ||
| 312 | inline while (j < count) : (j += 1) { | ||
| 313 | ts[j] = Block.fromBytes(counters[j * 16 .. j * 16 + 16][0..16]).xor(round_keys[0]); | ||
| 314 | } | ||
| 315 | comptime var i = 1; | ||
| 316 | inline while (i < rounds) : (i += 1) { | ||
| 317 | ts = Block.parallel.encryptWide(count, ts, round_keys[i]); | ||
| 318 | } | ||
| 319 | ts = Block.parallel.encryptLastWide(count, ts, round_keys[i]); | ||
| 320 | j = 0; | ||
| 321 | inline while (j < count) : (j += 1) { | ||
| 322 | dst[16 * j .. 16 * j + 16].* = ts[j].xorBytes(src[16 * j .. 16 * j + 16]); | ||
| 323 | } | ||
| 324 | } | ||
| 325 | }; | ||
| 326 | } | ||
| 327 | |||
| 328 | /// A context to perform decryption using the standard AES key schedule. | ||
| 329 | pub fn AESDecryptCtx(comptime AES: type) type { | ||
| 330 | std.debug.assert(AES.key_bits == 128 or AES.key_bits == 256); | ||
| 331 | const rounds = AES.rounds; | ||
| 332 | |||
| 333 | return struct { | ||
| 334 | const Self = @This(); | ||
| 335 | pub const block = AES.block; | ||
| 336 | pub const block_size = block.block_size; | ||
| 337 | key_schedule: KeySchedule(AES), | ||
| 338 | |||
| 339 | /// Create a decryption context from an existing encryption context. | ||
| 340 | pub fn initFromEnc(ctx: AESEncryptCtx(AES)) Self { | ||
| 341 | return Self{ | ||
| 342 | .key_schedule = ctx.key_schedule.invert(), | ||
| 343 | }; | ||
| 344 | } | ||
| 345 | |||
| 346 | /// Create a new decryption context with the given key. | ||
| 347 | pub fn init(key: [AES.key_bits / 8]u8) Self { | ||
| 348 | const enc_ctx = AESEncryptCtx(AES).init(key); | ||
| 349 | return initFromEnc(enc_ctx); | ||
| 350 | } | ||
| 351 | |||
| 352 | /// Decrypt a single block. | ||
| 353 | pub fn decrypt(ctx: Self, dst: *[16]u8, src: *const [16]u8) void { | ||
| 354 | const inv_round_keys = ctx.key_schedule.round_keys; | ||
| 355 | var t = Block.fromBytes(src).xor(inv_round_keys[0]); | ||
| 356 | comptime var i = 1; | ||
| 357 | inline while (i < rounds) : (i += 1) { | ||
| 358 | t = t.decrypt(inv_round_keys[i]); | ||
| 359 | } | ||
| 360 | t = t.decryptLast(inv_round_keys[rounds]); | ||
| 361 | dst.* = t.toBytes(); | ||
| 362 | } | ||
| 363 | |||
| 364 | /// Decrypt multiple blocks, possibly leveraging parallelization. | ||
| 365 | pub fn decryptWide(ctx: Self, comptime count: usize, dst: *[16 * count]u8, src: *const [16 * count]u8) void { | ||
| 366 | const inv_round_keys = ctx.key_schedule.round_keys; | ||
| 367 | var ts: [count]Block = undefined; | ||
| 368 | comptime var j = 0; | ||
| 369 | inline while (j < count) : (j += 1) { | ||
| 370 | ts[j] = Block.fromBytes(src[j * 16 .. j * 16 + 16][0..16]).xor(inv_round_keys[0]); | ||
| 371 | } | ||
| 372 | comptime var i = 1; | ||
| 373 | inline while (i < rounds) : (i += 1) { | ||
| 374 | ts = Block.parallel.decryptWide(count, ts, inv_round_keys[i]); | ||
| 375 | } | ||
| 376 | i = 1; | ||
| 377 | inline while (i < count) : (i += 1) { | ||
| 378 | ts = Block.parallel.decryptLastWide(count, ts, inv_round_keys[i]); | ||
| 379 | } | ||
| 380 | j = 0; | ||
| 381 | inline while (j < count) : (j += 1) { | ||
| 382 | dst[16 * j .. 16 * j + 16].* = ts[j].toBytes(); | ||
| 383 | } | ||
| 384 | } | ||
| 385 | }; | ||
| 386 | } | ||
| 387 | |||
| 388 | /// AES-128 with the standard key schedule. | ||
| 389 | pub const AES128 = struct { | ||
| 390 | pub const key_bits: usize = 128; | ||
| 391 | pub const rounds = ((key_bits - 64) / 32 + 8); | ||
| 392 | pub const block = Block; | ||
| 393 | |||
| 394 | /// Create a new context for encryption. | ||
| 395 | pub fn initEnc(key: [key_bits / 8]u8) AESEncryptCtx(AES128) { | ||
| 396 | return AESEncryptCtx(AES128).init(key); | ||
| 397 | } | ||
| 398 | |||
| 399 | /// Create a new context for decryption. | ||
| 400 | pub fn initDec(key: [key_bits / 8]u8) AESDecryptCtx(AES128) { | ||
| 401 | return AESDecryptCtx(AES128).init(key); | ||
| 402 | } | ||
| 403 | }; | ||
| 404 | |||
| 405 | /// AES-256 with the standard key schedule. | ||
| 406 | pub const AES256 = struct { | ||
| 407 | pub const key_bits: usize = 256; | ||
| 408 | pub const rounds = ((key_bits - 64) / 32 + 8); | ||
| 409 | pub const block = Block; | ||
| 410 | |||
| 411 | /// Create a new context for encryption. | ||
| 412 | pub fn initEnc(key: [key_bits / 8]u8) AESEncryptCtx(AES256) { | ||
| 413 | return AESEncryptCtx(AES256).init(key); | ||
| 414 | } | ||
| 415 | |||
| 416 | /// Create a new context for decryption. | ||
| 417 | pub fn initDec(key: [key_bits / 8]u8) AESDecryptCtx(AES256) { | ||
| 418 | return AESDecryptCtx(AES256).init(key); | ||
| 419 | } | ||
| 420 | }; | ||
lib/std/crypto/aes/soft.zig created+735| ... | @@ -0,0 +1,735 @@ | ||
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 6 | // Based on Go stdlib implementation | ||
| 7 | |||
| 8 | const std = @import("../../std.zig"); | ||
| 9 | const mem = std.mem; | ||
| 10 | |||
| 11 | const BlockVec = [4]u32; | ||
| 12 | |||
| 13 | /// A single AES block. | ||
| 14 | pub const Block = struct { | ||
| 15 | pub const block_size: usize = 16; | ||
| 16 | |||
| 17 | /// Internal representation of a block. | ||
| 18 | repr: BlockVec align(16), | ||
| 19 | |||
| 20 | /// Convert a byte sequence into an internal representation. | ||
| 21 | pub inline fn fromBytes(bytes: *const [16]u8) Block { | ||
| 22 | const s0 = mem.readIntBig(u32, bytes[0..4]); | ||
| 23 | const s1 = mem.readIntBig(u32, bytes[4..8]); | ||
| 24 | const s2 = mem.readIntBig(u32, bytes[8..12]); | ||
| 25 | const s3 = mem.readIntBig(u32, bytes[12..16]); | ||
| 26 | return Block{ .repr = BlockVec{ s0, s1, s2, s3 } }; | ||
| 27 | } | ||
| 28 | |||
| 29 | /// Convert the internal representation of a block into a byte sequence. | ||
| 30 | pub inline fn toBytes(block: Block) [16]u8 { | ||
| 31 | var bytes: [16]u8 = undefined; | ||
| 32 | mem.writeIntBig(u32, bytes[0..4], block.repr[0]); | ||
| 33 | mem.writeIntBig(u32, bytes[4..8], block.repr[1]); | ||
| 34 | mem.writeIntBig(u32, bytes[8..12], block.repr[2]); | ||
| 35 | mem.writeIntBig(u32, bytes[12..16], block.repr[3]); | ||
| 36 | return bytes; | ||
| 37 | } | ||
| 38 | |||
| 39 | /// XOR the block with a byte sequence. | ||
| 40 | pub inline fn xorBytes(block: Block, bytes: *const [16]u8) [16]u8 { | ||
| 41 | const block_bytes = block.toBytes(); | ||
| 42 | var x: [16]u8 = undefined; | ||
| 43 | comptime var i: usize = 0; | ||
| 44 | inline while (i < 16) : (i += 1) { | ||
| 45 | x[i] = block_bytes[i] ^ bytes[i]; | ||
| 46 | } | ||
| 47 | return x; | ||
| 48 | } | ||
| 49 | |||
| 50 | /// Encrypt a block with a round key. | ||
| 51 | pub inline fn encrypt(block: Block, round_key: Block) Block { | ||
| 52 | const src = &block.repr; | ||
| 53 | |||
| 54 | const s0 = block.repr[0]; | ||
| 55 | const s1 = block.repr[1]; | ||
| 56 | const s2 = block.repr[2]; | ||
| 57 | const s3 = block.repr[3]; | ||
| 58 | |||
| 59 | const t0 = round_key.repr[0] ^ te0[@truncate(u8, s0 >> 24)] ^ te1[@truncate(u8, s1 >> 16)] ^ te2[@truncate(u8, s2 >> 8)] ^ te3[@truncate(u8, s3)]; | ||
| 60 | const t1 = round_key.repr[1] ^ te0[@truncate(u8, s1 >> 24)] ^ te1[@truncate(u8, s2 >> 16)] ^ te2[@truncate(u8, s3 >> 8)] ^ te3[@truncate(u8, s0)]; | ||
| 61 | const t2 = round_key.repr[2] ^ te0[@truncate(u8, s2 >> 24)] ^ te1[@truncate(u8, s3 >> 16)] ^ te2[@truncate(u8, s0 >> 8)] ^ te3[@truncate(u8, s1)]; | ||
| 62 | const t3 = round_key.repr[3] ^ te0[@truncate(u8, s3 >> 24)] ^ te1[@truncate(u8, s0 >> 16)] ^ te2[@truncate(u8, s1 >> 8)] ^ te3[@truncate(u8, s2)]; | ||
| 63 | |||
| 64 | return Block{ .repr = BlockVec{ t0, t1, t2, t3 } }; | ||
| 65 | } | ||
| 66 | |||
| 67 | /// Encrypt a block with the last round key. | ||
| 68 | pub inline fn encryptLast(block: Block, round_key: Block) Block { | ||
| 69 | const src = &block.repr; | ||
| 70 | |||
| 71 | const t0 = block.repr[0]; | ||
| 72 | const t1 = block.repr[1]; | ||
| 73 | const t2 = block.repr[2]; | ||
| 74 | const t3 = block.repr[3]; | ||
| 75 | |||
| 76 | // Last round uses s-box directly and XORs to produce output. | ||
| 77 | var s0 = @as(u32, sbox0[t0 >> 24]) << 24 | @as(u32, sbox0[t1 >> 16 & 0xff]) << 16 | @as(u32, sbox0[t2 >> 8 & 0xff]) << 8 | @as(u32, sbox0[t3 & 0xff]); | ||
| 78 | var s1 = @as(u32, sbox0[t1 >> 24]) << 24 | @as(u32, sbox0[t2 >> 16 & 0xff]) << 16 | @as(u32, sbox0[t3 >> 8 & 0xff]) << 8 | @as(u32, sbox0[t0 & 0xff]); | ||
| 79 | var s2 = @as(u32, sbox0[t2 >> 24]) << 24 | @as(u32, sbox0[t3 >> 16 & 0xff]) << 16 | @as(u32, sbox0[t0 >> 8 & 0xff]) << 8 | @as(u32, sbox0[t1 & 0xff]); | ||
| 80 | var s3 = @as(u32, sbox0[t3 >> 24]) << 24 | @as(u32, sbox0[t0 >> 16 & 0xff]) << 16 | @as(u32, sbox0[t1 >> 8 & 0xff]) << 8 | @as(u32, sbox0[t2 & 0xff]); | ||
| 81 | s0 ^= round_key.repr[0]; | ||
| 82 | s1 ^= round_key.repr[1]; | ||
| 83 | s2 ^= round_key.repr[2]; | ||
| 84 | s3 ^= round_key.repr[3]; | ||
| 85 | |||
| 86 | return Block{ .repr = BlockVec{ s0, s1, s2, s3 } }; | ||
| 87 | } | ||
| 88 | |||
| 89 | /// Decrypt a block with a round key. | ||
| 90 | pub inline fn decrypt(block: Block, round_key: Block) Block { | ||
| 91 | const src = &block.repr; | ||
| 92 | |||
| 93 | const s0 = block.repr[0]; | ||
| 94 | const s1 = block.repr[1]; | ||
| 95 | const s2 = block.repr[2]; | ||
| 96 | const s3 = block.repr[3]; | ||
| 97 | |||
| 98 | const t0 = round_key.repr[0] ^ td0[@truncate(u8, s0 >> 24)] ^ td1[@truncate(u8, s3 >> 16)] ^ td2[@truncate(u8, s2 >> 8)] ^ td3[@truncate(u8, s1)]; | ||
| 99 | const t1 = round_key.repr[1] ^ td0[@truncate(u8, s1 >> 24)] ^ td1[@truncate(u8, s0 >> 16)] ^ td2[@truncate(u8, s3 >> 8)] ^ td3[@truncate(u8, s2)]; | ||
| 100 | const t2 = round_key.repr[2] ^ td0[@truncate(u8, s2 >> 24)] ^ td1[@truncate(u8, s1 >> 16)] ^ td2[@truncate(u8, s0 >> 8)] ^ td3[@truncate(u8, s3)]; | ||
| 101 | const t3 = round_key.repr[3] ^ td0[@truncate(u8, s3 >> 24)] ^ td1[@truncate(u8, s2 >> 16)] ^ td2[@truncate(u8, s1 >> 8)] ^ td3[@truncate(u8, s0)]; | ||
| 102 | |||
| 103 | return Block{ .repr = BlockVec{ t0, t1, t2, t3 } }; | ||
| 104 | } | ||
| 105 | |||
| 106 | /// Decrypt a block with the last round key. | ||
| 107 | pub inline fn decryptLast(block: Block, round_key: Block) Block { | ||
| 108 | const src = &block.repr; | ||
| 109 | |||
| 110 | const t0 = block.repr[0]; | ||
| 111 | const t1 = block.repr[1]; | ||
| 112 | const t2 = block.repr[2]; | ||
| 113 | const t3 = block.repr[3]; | ||
| 114 | |||
| 115 | // Last round uses s-box directly and XORs to produce output. | ||
| 116 | var s0 = @as(u32, sbox1[t0 >> 24]) << 24 | @as(u32, sbox1[t3 >> 16 & 0xff]) << 16 | @as(u32, sbox1[t2 >> 8 & 0xff]) << 8 | @as(u32, sbox1[t1 & 0xff]); | ||
| 117 | var s1 = @as(u32, sbox1[t1 >> 24]) << 24 | @as(u32, sbox1[t0 >> 16 & 0xff]) << 16 | @as(u32, sbox1[t3 >> 8 & 0xff]) << 8 | @as(u32, sbox1[t2 & 0xff]); | ||
| 118 | var s2 = @as(u32, sbox1[t2 >> 24]) << 24 | @as(u32, sbox1[t1 >> 16 & 0xff]) << 16 | @as(u32, sbox1[t0 >> 8 & 0xff]) << 8 | @as(u32, sbox1[t3 & 0xff]); | ||
| 119 | var s3 = @as(u32, sbox1[t3 >> 24]) << 24 | @as(u32, sbox1[t2 >> 16 & 0xff]) << 16 | @as(u32, sbox1[t1 >> 8 & 0xff]) << 8 | @as(u32, sbox1[t0 & 0xff]); | ||
| 120 | s0 ^= round_key.repr[0]; | ||
| 121 | s1 ^= round_key.repr[1]; | ||
| 122 | s2 ^= round_key.repr[2]; | ||
| 123 | s3 ^= round_key.repr[3]; | ||
| 124 | |||
| 125 | return Block{ .repr = BlockVec{ s0, s1, s2, s3 } }; | ||
| 126 | } | ||
| 127 | |||
| 128 | /// XOR the content of two blocks. | ||
| 129 | pub inline fn xor(block1: Block, block2: Block) Block { | ||
| 130 | var x: BlockVec = undefined; | ||
| 131 | comptime var i = 0; | ||
| 132 | inline while (i < 4) : (i += 1) { | ||
| 133 | x[i] = block1.repr[i] ^ block2.repr[i]; | ||
| 134 | } | ||
| 135 | return Block{ .repr = x }; | ||
| 136 | } | ||
| 137 | |||
| 138 | /// Perform operations on multiple blocks in parallel. | ||
| 139 | pub const parallel = struct { | ||
| 140 | /// The recommended number of AES encryption/decryption to perform in parallel for the chosen implementation. | ||
| 141 | pub const optimal_parallel_blocks = 1; | ||
| 142 | |||
| 143 | /// Encrypt multiple blocks in parallel, each their own round key. | ||
| 144 | pub fn encryptParallel(comptime count: usize, blocks: [count]Block, round_keys: [count]Block) [count]Block { | ||
| 145 | var i = 0; | ||
| 146 | var out: [count]Block = undefined; | ||
| 147 | while (i < count) : (i += 1) { | ||
| 148 | out[i] = blocks[i].encrypt(round_keys[i]); | ||
| 149 | } | ||
| 150 | return out; | ||
| 151 | } | ||
| 152 | |||
| 153 | /// Decrypt multiple blocks in parallel, each their own round key. | ||
| 154 | pub fn decryptParallel(comptime count: usize, blocks: [count]Block, round_keys: [count]Block) [count]Block { | ||
| 155 | var i = 0; | ||
| 156 | var out: [count]Block = undefined; | ||
| 157 | while (i < count) : (i += 1) { | ||
| 158 | out[i] = blocks[i].decrypt(round_keys[i]); | ||
| 159 | } | ||
| 160 | return out; | ||
| 161 | } | ||
| 162 | |||
| 163 | /// Encrypt multple blocks in parallel with the same round key. | ||
| 164 | pub fn encryptWide(comptime count: usize, blocks: [count]Block, round_key: Block) [count]Block { | ||
| 165 | var i = 0; | ||
| 166 | var out: [count]Block = undefined; | ||
| 167 | while (i < count) : (i += 1) { | ||
| 168 | out[i] = blocks[i].encrypt(round_key); | ||
| 169 | } | ||
| 170 | return out; | ||
| 171 | } | ||
| 172 | |||
| 173 | /// Decrypt multple blocks in parallel with the same round key. | ||
| 174 | pub fn decryptWide(comptime count: usize, blocks: [count]Block, round_key: Block) [count]Block { | ||
| 175 | var i = 0; | ||
| 176 | var out: [count]Block = undefined; | ||
| 177 | while (i < count) : (i += 1) { | ||
| 178 | out[i] = blocks[i].decrypt(round_key); | ||
| 179 | } | ||
| 180 | return out; | ||
| 181 | } | ||
| 182 | |||
| 183 | /// Encrypt multple blocks in parallel with the same last round key. | ||
| 184 | pub fn encryptLastWide(comptime count: usize, blocks: [count]Block, round_key: Block) [count]Block { | ||
| 185 | var i = 0; | ||
| 186 | var out: [count]Block = undefined; | ||
| 187 | while (i < count) : (i += 1) { | ||
| 188 | out[i] = blocks[i].encryptLast(round_key); | ||
| 189 | } | ||
| 190 | return out; | ||
| 191 | } | ||
| 192 | |||
| 193 | /// Decrypt multple blocks in parallel with the same last round key. | ||
| 194 | pub fn decryptLastWide(comptime count: usize, blocks: [count]Block, round_key: Block) [count]Block { | ||
| 195 | var i = 0; | ||
| 196 | var out: [count]Block = undefined; | ||
| 197 | while (i < count) : (i += 1) { | ||
| 198 | out[i] = blocks[i].decryptLast(round_key); | ||
| 199 | } | ||
| 200 | return out; | ||
| 201 | } | ||
| 202 | }; | ||
| 203 | }; | ||
| 204 | |||
| 205 | fn KeySchedule(comptime AES: type) type { | ||
| 206 | std.debug.assert(AES.rounds == 10 or AES.rounds == 14); | ||
| 207 | const key_size = AES.key_bits / 8; | ||
| 208 | const rounds = AES.rounds; | ||
| 209 | |||
| 210 | return struct { | ||
| 211 | const Self = @This(); | ||
| 212 | const words_in_key = key_size / 4; | ||
| 213 | |||
| 214 | round_keys: [rounds + 1]Block, | ||
| 215 | |||
| 216 | // Key expansion algorithm. See FIPS-197, Figure 11. | ||
| 217 | fn expandKey(key: [key_size]u8) Self { | ||
| 218 | const subw = struct { | ||
| 219 | // Apply sbox0 to each byte in w. | ||
| 220 | fn func(w: u32) u32 { | ||
| 221 | return @as(u32, sbox0[w >> 24]) << 24 | @as(u32, sbox0[w >> 16 & 0xff]) << 16 | @as(u32, sbox0[w >> 8 & 0xff]) << 8 | @as(u32, sbox0[w & 0xff]); | ||
| 222 | } | ||
| 223 | }.func; | ||
| 224 | |||
| 225 | var round_keys: [rounds + 1]Block = undefined; | ||
| 226 | comptime var i: usize = 0; | ||
| 227 | inline while (i < words_in_key) : (i += 1) { | ||
| 228 | round_keys[i / 4].repr[i % 4] = mem.readIntBig(u32, key[4 * i ..][0..4]); | ||
| 229 | } | ||
| 230 | inline while (i < round_keys.len * 4) : (i += 1) { | ||
| 231 | var t = round_keys[(i - 1) / 4].repr[(i - 1) % 4]; | ||
| 232 | if (i % words_in_key == 0) { | ||
| 233 | t = subw(std.math.rotl(u32, t, 8)) ^ (@as(u32, powx[i / words_in_key - 1]) << 24); | ||
| 234 | } else if (words_in_key > 6 and i % words_in_key == 4) { | ||
| 235 | t = subw(t); | ||
| 236 | } | ||
| 237 | round_keys[i / 4].repr[i % 4] = round_keys[(i - words_in_key) / 4].repr[(i - words_in_key) % 4] ^ t; | ||
| 238 | } | ||
| 239 | return Self{ .round_keys = round_keys }; | ||
| 240 | } | ||
| 241 | |||
| 242 | /// Invert the key schedule. | ||
| 243 | pub fn invert(key_schedule: Self) Self { | ||
| 244 | const round_keys = &key_schedule.round_keys; | ||
| 245 | var inv_round_keys: [rounds + 1]Block = undefined; | ||
| 246 | const total_words = 4 * round_keys.len; | ||
| 247 | var i: usize = 0; | ||
| 248 | while (i < total_words) : (i += 4) { | ||
| 249 | const ei = total_words - i - 4; | ||
| 250 | comptime var j: usize = 0; | ||
| 251 | inline while (j < 4) : (j += 1) { | ||
| 252 | var x = round_keys[(ei + j) / 4].repr[(ei + j) % 4]; | ||
| 253 | if (i > 0 and i + 4 < total_words) { | ||
| 254 | x = td0[sbox0[x >> 24]] ^ td1[sbox0[x >> 16 & 0xff]] ^ td2[sbox0[x >> 8 & 0xff]] ^ td3[sbox0[x & 0xff]]; | ||
| 255 | } | ||
| 256 | inv_round_keys[(i + j) / 4].repr[(i + j) % 4] = x; | ||
| 257 | } | ||
| 258 | } | ||
| 259 | return Self{ .round_keys = inv_round_keys }; | ||
| 260 | } | ||
| 261 | }; | ||
| 262 | } | ||
| 263 | |||
| 264 | /// A context to perform encryption using the standard AES key schedule. | ||
| 265 | pub fn AESEncryptCtx(comptime AES: type) type { | ||
| 266 | std.debug.assert(AES.key_bits == 128 or AES.key_bits == 256); | ||
| 267 | const rounds = AES.rounds; | ||
| 268 | |||
| 269 | return struct { | ||
| 270 | const Self = @This(); | ||
| 271 | pub const block = AES.block; | ||
| 272 | pub const block_size = block.block_size; | ||
| 273 | key_schedule: KeySchedule(AES), | ||
| 274 | |||
| 275 | /// Create a new encryption context with the given key. | ||
| 276 | pub fn init(key: [AES.key_bits / 8]u8) Self { | ||
| 277 | const key_schedule = KeySchedule(AES).expandKey(key); | ||
| 278 | return Self{ | ||
| 279 | .key_schedule = key_schedule, | ||
| 280 | }; | ||
| 281 | } | ||
| 282 | |||
| 283 | /// Encrypt a single block. | ||
| 284 | pub fn encrypt(ctx: Self, dst: *[16]u8, src: *const [16]u8) void { | ||
| 285 | const round_keys = ctx.key_schedule.round_keys; | ||
| 286 | var t = Block.fromBytes(src).xor(round_keys[0]); | ||
| 287 | comptime var i = 1; | ||
| 288 | inline while (i < rounds) : (i += 1) { | ||
| 289 | t = t.encrypt(round_keys[i]); | ||
| 290 | } | ||
| 291 | t = t.encryptLast(round_keys[rounds]); | ||
| 292 | dst.* = t.toBytes(); | ||
| 293 | } | ||
| 294 | |||
| 295 | /// Encrypt+XOR a single block. | ||
| 296 | pub fn xor(ctx: Self, dst: *[16]u8, src: *const [16]u8, counter: [16]u8) void { | ||
| 297 | const round_keys = ctx.key_schedule.round_keys; | ||
| 298 | var t = Block.fromBytes(&counter).xor(round_keys[0]); | ||
| 299 | comptime var i = 1; | ||
| 300 | inline while (i < rounds) : (i += 1) { | ||
| 301 | t = t.encrypt(round_keys[i]); | ||
| 302 | } | ||
| 303 | t = t.encryptLast(round_keys[rounds]); | ||
| 304 | dst.* = t.xorBytes(src); | ||
| 305 | } | ||
| 306 | |||
| 307 | /// Encrypt multiple blocks, possibly leveraging parallelization. | ||
| 308 | pub fn encryptWide(ctx: Self, comptime count: usize, dst: *[16 * count]u8, src: *const [16 * count]u8) void { | ||
| 309 | var i: usize = 0; | ||
| 310 | while (i < count) : (i += 1) { | ||
| 311 | ctx.encrypt(dst[16 * i .. 16 * i + 16][0..16], src[16 * i .. 16 * i + 16][0..16]); | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | /// Encrypt+XOR multiple blocks, possibly leveraging parallelization. | ||
| 316 | pub fn xorWide(ctx: Self, comptime count: usize, dst: *[16 * count]u8, src: *const [16 * count]u8, counters: [16 * count]u8) void { | ||
| 317 | var i: usize = 0; | ||
| 318 | while (i < count) : (i += 1) { | ||
| 319 | ctx.xor(dst[16 * i .. 16 * i + 16][0..16], src[16 * i .. 16 * i + 16][0..16], counters[16 * i .. 16 * i + 16][0..16].*); | ||
| 320 | } | ||
| 321 | } | ||
| 322 | }; | ||
| 323 | } | ||
| 324 | |||
| 325 | /// A context to perform decryption using the standard AES key schedule. | ||
| 326 | pub fn AESDecryptCtx(comptime AES: type) type { | ||
| 327 | std.debug.assert(AES.key_bits == 128 or AES.key_bits == 256); | ||
| 328 | const rounds = AES.rounds; | ||
| 329 | |||
| 330 | return struct { | ||
| 331 | const Self = @This(); | ||
| 332 | pub const block = AES.block; | ||
| 333 | pub const block_size = block.block_size; | ||
| 334 | key_schedule: KeySchedule(AES), | ||
| 335 | |||
| 336 | /// Create a decryption context from an existing encryption context. | ||
| 337 | pub fn initFromEnc(ctx: AESEncryptCtx(AES)) Self { | ||
| 338 | return Self{ | ||
| 339 | .key_schedule = ctx.key_schedule.invert(), | ||
| 340 | }; | ||
| 341 | } | ||
| 342 | |||
| 343 | /// Create a new decryption context with the given key. | ||
| 344 | pub fn init(key: [AES.key_bits / 8]u8) Self { | ||
| 345 | const enc_ctx = AESEncryptCtx(AES).init(key); | ||
| 346 | return initFromEnc(enc_ctx); | ||
| 347 | } | ||
| 348 | |||
| 349 | /// Decrypt a single block. | ||
| 350 | pub fn decrypt(ctx: Self, dst: *[16]u8, src: *const [16]u8) void { | ||
| 351 | const inv_round_keys = ctx.key_schedule.round_keys; | ||
| 352 | var t = Block.fromBytes(src).xor(inv_round_keys[0]); | ||
| 353 | comptime var i = 1; | ||
| 354 | inline while (i < rounds) : (i += 1) { | ||
| 355 | t = t.decrypt(inv_round_keys[i]); | ||
| 356 | } | ||
| 357 | t = t.decryptLast(inv_round_keys[rounds]); | ||
| 358 | dst.* = t.toBytes(); | ||
| 359 | } | ||
| 360 | |||
| 361 | /// Decrypt multiple blocks, possibly leveraging parallelization. | ||
| 362 | pub fn decryptWide(ctx: Self, comptime count: usize, dst: *[16 * count]u8, src: *const [16 * count]u8) void { | ||
| 363 | var i: usize = 0; | ||
| 364 | while (i < count) : (i += 1) { | ||
| 365 | ctx.decrypt(dst[16 * i .. 16 * i + 16][0..16], src[16 * i .. 16 * i + 16][0..16]); | ||
| 366 | } | ||
| 367 | } | ||
| 368 | }; | ||
| 369 | } | ||
| 370 | |||
| 371 | /// AES-128 with the standard key schedule. | ||
| 372 | pub const AES128 = struct { | ||
| 373 | pub const key_bits: usize = 128; | ||
| 374 | pub const rounds = ((key_bits - 64) / 32 + 8); | ||
| 375 | pub const block = Block; | ||
| 376 | |||
| 377 | /// Create a new context for encryption. | ||
| 378 | pub fn initEnc(key: [key_bits / 8]u8) AESEncryptCtx(AES128) { | ||
| 379 | return AESEncryptCtx(AES128).init(key); | ||
| 380 | } | ||
| 381 | |||
| 382 | /// Create a new context for decryption. | ||
| 383 | pub fn initDec(key: [key_bits / 8]u8) AESDecryptCtx(AES128) { | ||
| 384 | return AESDecryptCtx(AES128).init(key); | ||
| 385 | } | ||
| 386 | }; | ||
| 387 | |||
| 388 | /// AES-256 with the standard key schedule. | ||
| 389 | pub const AES256 = struct { | ||
| 390 | pub const key_bits: usize = 256; | ||
| 391 | pub const rounds = ((key_bits - 64) / 32 + 8); | ||
| 392 | pub const block = Block; | ||
| 393 | |||
| 394 | /// Create a new context for encryption. | ||
| 395 | pub fn initEnc(key: [key_bits / 8]u8) AESEncryptCtx(AES256) { | ||
| 396 | return AESEncryptCtx(AES256).init(key); | ||
| 397 | } | ||
| 398 | |||
| 399 | /// Create a new context for decryption. | ||
| 400 | pub fn initDec(key: [key_bits / 8]u8) AESDecryptCtx(AES256) { | ||
| 401 | return AESDecryptCtx(AES256).init(key); | ||
| 402 | } | ||
| 403 | }; | ||
| 404 | |||
| 405 | // constants | ||
| 406 | const powx = [16]u8{ | ||
| 407 | 0x01, | ||
| 408 | 0x02, | ||
| 409 | 0x04, | ||
| 410 | 0x08, | ||
| 411 | 0x10, | ||
| 412 | 0x20, | ||
| 413 | 0x40, | ||
| 414 | 0x80, | ||
| 415 | 0x1b, | ||
| 416 | 0x36, | ||
| 417 | 0x6c, | ||
| 418 | 0xd8, | ||
| 419 | 0xab, | ||
| 420 | 0x4d, | ||
| 421 | 0x9a, | ||
| 422 | 0x2f, | ||
| 423 | }; | ||
| 424 | |||
| 425 | const sbox0 align(64) = [256]u8{ | ||
| 426 | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, | ||
| 427 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, | ||
| 428 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, | ||
| 429 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, | ||
| 430 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, | ||
| 431 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, | ||
| 432 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, | ||
| 433 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, | ||
| 434 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, | ||
| 435 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, | ||
| 436 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, | ||
| 437 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, | ||
| 438 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, | ||
| 439 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, | ||
| 440 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, | ||
| 441 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, | ||
| 442 | }; | ||
| 443 | |||
| 444 | const sbox1 align(64) = [256]u8{ | ||
| 445 | 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, | ||
| 446 | 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, | ||
| 447 | 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, | ||
| 448 | 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, | ||
| 449 | 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, | ||
| 450 | 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, | ||
| 451 | 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, | ||
| 452 | 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, | ||
| 453 | 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, | ||
| 454 | 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, | ||
| 455 | 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, | ||
| 456 | 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, | ||
| 457 | 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, | ||
| 458 | 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, | ||
| 459 | 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, | ||
| 460 | 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, | ||
| 461 | }; | ||
| 462 | |||
| 463 | const te0 align(64) = [256]u32{ | ||
| 464 | 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, | ||
| 465 | 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, | ||
| 466 | 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, | ||
| 467 | 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, | ||
| 468 | 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, | ||
| 469 | 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, | ||
| 470 | 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, | ||
| 471 | 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, | ||
| 472 | 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, | ||
| 473 | 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, | ||
| 474 | 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, | ||
| 475 | 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, | ||
| 476 | 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, | ||
| 477 | 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, | ||
| 478 | 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, | ||
| 479 | 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, | ||
| 480 | 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, | ||
| 481 | 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, | ||
| 482 | 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, | ||
| 483 | 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, | ||
| 484 | 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, | ||
| 485 | 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, | ||
| 486 | 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, | ||
| 487 | 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, | ||
| 488 | 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, | ||
| 489 | 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, | ||
| 490 | 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, | ||
| 491 | 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, | ||
| 492 | 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, | ||
| 493 | 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, | ||
| 494 | 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, | ||
| 495 | 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a, | ||
| 496 | }; | ||
| 497 | const te1 align(64) = [256]u32{ | ||
| 498 | 0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, | ||
| 499 | 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, | ||
| 500 | 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, | ||
| 501 | 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, | ||
| 502 | 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, | ||
| 503 | 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, | ||
| 504 | 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, | ||
| 505 | 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, | ||
| 506 | 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, | ||
| 507 | 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, | ||
| 508 | 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, | ||
| 509 | 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, | ||
| 510 | 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, | ||
| 511 | 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, | ||
| 512 | 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, | ||
| 513 | 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, | ||
| 514 | 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, | ||
| 515 | 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, | ||
| 516 | 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, | ||
| 517 | 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, | ||
| 518 | 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, | ||
| 519 | 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, | ||
| 520 | 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, | ||
| 521 | 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, | ||
| 522 | 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, | ||
| 523 | 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, | ||
| 524 | 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, | ||
| 525 | 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, | ||
| 526 | 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, | ||
| 527 | 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, | ||
| 528 | 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, | ||
| 529 | 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616, | ||
| 530 | }; | ||
| 531 | const te2 align(64) = [256]u32{ | ||
| 532 | 0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, | ||
| 533 | 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, | ||
| 534 | 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, | ||
| 535 | 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, | ||
| 536 | 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, | ||
| 537 | 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, | ||
| 538 | 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, | ||
| 539 | 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, | ||
| 540 | 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, | ||
| 541 | 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, | ||
| 542 | 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, | ||
| 543 | 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, | ||
| 544 | 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, | ||
| 545 | 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, | ||
| 546 | 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, | ||
| 547 | 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, | ||
| 548 | 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, | ||
| 549 | 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, | ||
| 550 | 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, | ||
| 551 | 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, | ||
| 552 | 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, | ||
| 553 | 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, | ||
| 554 | 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, | ||
| 555 | 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, | ||
| 556 | 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, | ||
| 557 | 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, | ||
| 558 | 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, | ||
| 559 | 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, | ||
| 560 | 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, | ||
| 561 | 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, | ||
| 562 | 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, | ||
| 563 | 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16, | ||
| 564 | }; | ||
| 565 | const te3 align(64) = [256]u32{ | ||
| 566 | 0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, | ||
| 567 | 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, | ||
| 568 | 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, | ||
| 569 | 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, | ||
| 570 | 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, | ||
| 571 | 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, | ||
| 572 | 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, | ||
| 573 | 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, | ||
| 574 | 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, | ||
| 575 | 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, | ||
| 576 | 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, | ||
| 577 | 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, | ||
| 578 | 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, | ||
| 579 | 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, | ||
| 580 | 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, | ||
| 581 | 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, | ||
| 582 | 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, | ||
| 583 | 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, | ||
| 584 | 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, | ||
| 585 | 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, | ||
| 586 | 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, | ||
| 587 | 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, | ||
| 588 | 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, | ||
| 589 | 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, | ||
| 590 | 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, | ||
| 591 | 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, | ||
| 592 | 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, | ||
| 593 | 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, | ||
| 594 | 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, | ||
| 595 | 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, | ||
| 596 | 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, | ||
| 597 | 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c, | ||
| 598 | }; | ||
| 599 | |||
| 600 | const td0 align(64) = [256]u32{ | ||
| 601 | 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, | ||
| 602 | 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, | ||
| 603 | 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, | ||
| 604 | 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, | ||
| 605 | 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, | ||
| 606 | 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, | ||
| 607 | 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, | ||
| 608 | 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, | ||
| 609 | 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, | ||
| 610 | 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, | ||
| 611 | 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, | ||
| 612 | 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, | ||
| 613 | 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, | ||
| 614 | 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, | ||
| 615 | 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, | ||
| 616 | 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, | ||
| 617 | 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, | ||
| 618 | 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, | ||
| 619 | 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, | ||
| 620 | 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, | ||
| 621 | 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, | ||
| 622 | 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, | ||
| 623 | 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, | ||
| 624 | 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, | ||
| 625 | 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, | ||
| 626 | 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, | ||
| 627 | 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, | ||
| 628 | 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, | ||
| 629 | 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, | ||
| 630 | 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, | ||
| 631 | 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, | ||
| 632 | 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742, | ||
| 633 | }; | ||
| 634 | const td1 align(64) = [256]u32{ | ||
| 635 | 0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, | ||
| 636 | 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, | ||
| 637 | 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, | ||
| 638 | 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, | ||
| 639 | 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, | ||
| 640 | 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, | ||
| 641 | 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, | ||
| 642 | 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, | ||
| 643 | 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, | ||
| 644 | 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, | ||
| 645 | 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, | ||
| 646 | 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, | ||
| 647 | 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, | ||
| 648 | 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, | ||
| 649 | 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, | ||
| 650 | 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, | ||
| 651 | 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, | ||
| 652 | 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, | ||
| 653 | 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, | ||
| 654 | 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, | ||
| 655 | 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, | ||
| 656 | 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, | ||
| 657 | 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, | ||
| 658 | 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, | ||
| 659 | 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, | ||
| 660 | 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, | ||
| 661 | 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, | ||
| 662 | 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, | ||
| 663 | 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, | ||
| 664 | 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, | ||
| 665 | 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, | ||
| 666 | 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857, | ||
| 667 | }; | ||
| 668 | const td2 align(64) = [256]u32{ | ||
| 669 | 0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, | ||
| 670 | 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, | ||
| 671 | 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, | ||
| 672 | 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, | ||
| 673 | 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, | ||
| 674 | 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, | ||
| 675 | 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, | ||
| 676 | 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, | ||
| 677 | 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, | ||
| 678 | 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, | ||
| 679 | 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, | ||
| 680 | 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, | ||
| 681 | 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, | ||
| 682 | 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, | ||
| 683 | 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, | ||
| 684 | 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, | ||
| 685 | 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, | ||
| 686 | 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, | ||
| 687 | 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, | ||
| 688 | 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, | ||
| 689 | 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, | ||
| 690 | 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, | ||
| 691 | 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, | ||
| 692 | 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, | ||
| 693 | 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, | ||
| 694 | 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, | ||
| 695 | 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, | ||
| 696 | 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, | ||
| 697 | 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, | ||
| 698 | 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, | ||
| 699 | 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, | ||
| 700 | 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8, | ||
| 701 | }; | ||
| 702 | const td3 align(64) = [256]u32{ | ||
| 703 | 0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, | ||
| 704 | 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, | ||
| 705 | 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, | ||
| 706 | 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, | ||
| 707 | 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, | ||
| 708 | 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, | ||
| 709 | 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, | ||
| 710 | 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, | ||
| 711 | 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, | ||
| 712 | 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, | ||
| 713 | 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, | ||
| 714 | 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, | ||
| 715 | 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, | ||
| 716 | 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, | ||
| 717 | 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, | ||
| 718 | 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, | ||
| 719 | 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, | ||
| 720 | 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, | ||
| 721 | 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, | ||
| 722 | 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, | ||
| 723 | 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, | ||
| 724 | 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, | ||
| 725 | 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, | ||
| 726 | 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, | ||
| 727 | 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, | ||
| 728 | 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, | ||
| 729 | 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, | ||
| 730 | 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, | ||
| 731 | 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, | ||
| 732 | 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, | ||
| 733 | 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, | ||
| 734 | 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0, | ||
| 735 | }; | ||
lib/std/crypto/benchmark.zig+77-5| ... | @@ -179,6 +179,64 @@ pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int) !u64 | ... | @@ -179,6 +179,64 @@ pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int) !u64 |
| 179 | return throughput; | 179 | return throughput; |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | const aes = [_]Crypto{ | ||
| 183 | Crypto{ .ty = crypto.core.aes.AES128, .name = "aes128-single" }, | ||
| 184 | Crypto{ .ty = crypto.core.aes.AES256, .name = "aes256-single" }, | ||
| 185 | }; | ||
| 186 | |||
| 187 | pub fn benchmarkAES(comptime AES: anytype, comptime count: comptime_int) !u64 { | ||
| 188 | var key: [AES.key_bits / 8]u8 = undefined; | ||
| 189 | prng.random.bytes(key[0..]); | ||
| 190 | const ctx = AES.initEnc(key); | ||
| 191 | |||
| 192 | var in = [_]u8{0} ** 16; | ||
| 193 | |||
| 194 | var timer = try Timer.start(); | ||
| 195 | const start = timer.lap(); | ||
| 196 | { | ||
| 197 | var i: usize = 0; | ||
| 198 | while (i < count) : (i += 1) { | ||
| 199 | ctx.encrypt(&in, &in); | ||
| 200 | } | ||
| 201 | } | ||
| 202 | mem.doNotOptimizeAway(&in); | ||
| 203 | const end = timer.read(); | ||
| 204 | |||
| 205 | const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s; | ||
| 206 | const throughput = @floatToInt(u64, count / elapsed_s); | ||
| 207 | |||
| 208 | return throughput; | ||
| 209 | } | ||
| 210 | |||
| 211 | const aes8 = [_]Crypto{ | ||
| 212 | Crypto{ .ty = crypto.core.aes.AES128, .name = "aes128-8" }, | ||
| 213 | Crypto{ .ty = crypto.core.aes.AES256, .name = "aes256-8" }, | ||
| 214 | }; | ||
| 215 | |||
| 216 | pub fn benchmarkAES8(comptime AES: anytype, comptime count: comptime_int) !u64 { | ||
| 217 | var key: [AES.key_bits / 8]u8 = undefined; | ||
| 218 | prng.random.bytes(key[0..]); | ||
| 219 | const ctx = AES.initEnc(key); | ||
| 220 | |||
| 221 | var in = [_]u8{0} ** (8 * 16); | ||
| 222 | |||
| 223 | var timer = try Timer.start(); | ||
| 224 | const start = timer.lap(); | ||
| 225 | { | ||
| 226 | var i: usize = 0; | ||
| 227 | while (i < count) : (i += 1) { | ||
| 228 | ctx.encryptWide(8, &in, &in); | ||
| 229 | } | ||
| 230 | } | ||
| 231 | mem.doNotOptimizeAway(&in); | ||
| 232 | const end = timer.read(); | ||
| 233 | |||
| 234 | const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s; | ||
| 235 | const throughput = @floatToInt(u64, 8 * count / elapsed_s); | ||
| 236 | |||
| 237 | return throughput; | ||
| 238 | } | ||
| 239 | |||
| 182 | fn usage() void { | 240 | fn usage() void { |
| 183 | std.debug.warn( | 241 | std.debug.warn( |
| 184 | \\throughput_test [options] | 242 | \\throughput_test [options] |
| ... | @@ -238,35 +296,49 @@ pub fn main() !void { | ... | @@ -238,35 +296,49 @@ pub fn main() !void { |
| 238 | inline for (hashes) |H| { | 296 | inline for (hashes) |H| { |
| 239 | if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) { | 297 | if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) { |
| 240 | const throughput = try benchmarkHash(H.ty, mode(128 * MiB)); | 298 | const throughput = try benchmarkHash(H.ty, mode(128 * MiB)); |
| 241 | try stdout.print("{:>17}: {:7} MiB/s\n", .{ H.name, throughput / (1 * MiB) }); | 299 | try stdout.print("{:>17}: {:10} MiB/s\n", .{ H.name, throughput / (1 * MiB) }); |
| 242 | } | 300 | } |
| 243 | } | 301 | } |
| 244 | 302 | ||
| 245 | inline for (macs) |M| { | 303 | inline for (macs) |M| { |
| 246 | if (filter == null or std.mem.indexOf(u8, M.name, filter.?) != null) { | 304 | if (filter == null or std.mem.indexOf(u8, M.name, filter.?) != null) { |
| 247 | const throughput = try benchmarkMac(M.ty, mode(128 * MiB)); | 305 | const throughput = try benchmarkMac(M.ty, mode(128 * MiB)); |
| 248 | try stdout.print("{:>17}: {:7} MiB/s\n", .{ M.name, throughput / (1 * MiB) }); | 306 | try stdout.print("{:>17}: {:10} MiB/s\n", .{ M.name, throughput / (1 * MiB) }); |
| 249 | } | 307 | } |
| 250 | } | 308 | } |
| 251 | 309 | ||
| 252 | inline for (exchanges) |E| { | 310 | inline for (exchanges) |E| { |
| 253 | if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { | 311 | if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { |
| 254 | const throughput = try benchmarkKeyExchange(E.ty, mode(1000)); | 312 | const throughput = try benchmarkKeyExchange(E.ty, mode(1000)); |
| 255 | try stdout.print("{:>17}: {:7} exchanges/s\n", .{ E.name, throughput }); | 313 | try stdout.print("{:>17}: {:10} exchanges/s\n", .{ E.name, throughput }); |
| 256 | } | 314 | } |
| 257 | } | 315 | } |
| 258 | 316 | ||
| 259 | inline for (signatures) |E| { | 317 | inline for (signatures) |E| { |
| 260 | if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { | 318 | if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { |
| 261 | const throughput = try benchmarkSignature(E.ty, mode(1000)); | 319 | const throughput = try benchmarkSignature(E.ty, mode(1000)); |
| 262 | try stdout.print("{:>17}: {:7} signatures/s\n", .{ E.name, throughput }); | 320 | try stdout.print("{:>17}: {:10} signatures/s\n", .{ E.name, throughput }); |
| 263 | } | 321 | } |
| 264 | } | 322 | } |
| 265 | 323 | ||
| 266 | inline for (aeads) |E| { | 324 | inline for (aeads) |E| { |
| 267 | if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { | 325 | if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { |
| 268 | const throughput = try benchmarkAead(E.ty, mode(128 * MiB)); | 326 | const throughput = try benchmarkAead(E.ty, mode(128 * MiB)); |
| 269 | try stdout.print("{:>17}: {:7} MiB/s\n", .{ E.name, throughput / (1 * MiB) }); | 327 | try stdout.print("{:>17}: {:10} MiB/s\n", .{ E.name, throughput / (1 * MiB) }); |
| 328 | } | ||
| 329 | } | ||
| 330 | |||
| 331 | inline for (aes) |E| { | ||
| 332 | if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { | ||
| 333 | const throughput = try benchmarkAES(E.ty, mode(100000000)); | ||
| 334 | try stdout.print("{:>17}: {:10} ops/s\n", .{ E.name, throughput }); | ||
| 335 | } | ||
| 336 | } | ||
| 337 | |||
| 338 | inline for (aes8) |E| { | ||
| 339 | if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { | ||
| 340 | const throughput = try benchmarkAES8(E.ty, mode(10000000)); | ||
| 341 | try stdout.print("{:>17}: {:10} ops/s\n", .{ E.name, throughput }); | ||
| 270 | } | 342 | } |
| 271 | } | 343 | } |
| 272 | } | 344 | } |
lib/std/crypto/modes.zig created+51| ... | @@ -0,0 +1,51 @@ | ||
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 6 | // Based on Go stdlib implementation | ||
| 7 | |||
| 8 | const std = @import("../std.zig"); | ||
| 9 | const builtin = std.builtin; | ||
| 10 | const mem = std.mem; | ||
| 11 | const debug = std.debug; | ||
| 12 | |||
| 13 | /// Counter mode. | ||
| 14 | /// | ||
| 15 | /// This mode creates a key stream by encrypting an incrementing counter using a block cipher, and adding it to the source material. | ||
| 16 | /// | ||
| 17 | /// Important: the counter mode doesn't provide authenticated encryption: the ciphertext can be trivially modified without this being detected. | ||
| 18 | /// As a result, applications should generally never use it directly, but only in a construction that includes a MAC. | ||
| 19 | pub fn ctr(comptime BlockCipher: anytype, block_cipher: BlockCipher, dst: []u8, src: []const u8, iv: [BlockCipher.block_size]u8, endian: comptime builtin.Endian) void { | ||
| 20 | debug.assert(dst.len >= src.len); | ||
| 21 | const block_size = BlockCipher.block_size; | ||
| 22 | var counter: [BlockCipher.block_size]u8 = undefined; | ||
| 23 | var counterInt = mem.readInt(u128, &iv, endian); | ||
| 24 | var i: usize = 0; | ||
| 25 | |||
| 26 | const parallel_count = BlockCipher.block.parallel.optimal_parallel_blocks; | ||
| 27 | const wide_block_size = parallel_count * 16; | ||
| 28 | if (src.len >= wide_block_size) { | ||
| 29 | var counters: [parallel_count * 16]u8 = undefined; | ||
| 30 | while (i + wide_block_size <= src.len) : (i += wide_block_size) { | ||
| 31 | comptime var j = 0; | ||
| 32 | inline while (j < parallel_count) : (j += 1) { | ||
| 33 | mem.writeInt(u128, counters[j * 16 .. j * 16 + 16], counterInt, endian); | ||
| 34 | counterInt +%= 1; | ||
| 35 | } | ||
| 36 | block_cipher.xorWide(parallel_count, dst[i .. i + wide_block_size][0..wide_block_size], src[i .. i + wide_block_size][0..wide_block_size], counters); | ||
| 37 | } | ||
| 38 | } | ||
| 39 | while (i + block_size <= src.len) : (i += block_size) { | ||
| 40 | mem.writeInt(u128, &counter, counterInt, endian); | ||
| 41 | counterInt +%= 1; | ||
| 42 | block_cipher.xor(dst[i .. i + block_size][0..block_size], src[i .. i + block_size][0..block_size], counter); | ||
| 43 | } | ||
| 44 | if (i < src.len) { | ||
| 45 | mem.writeInt(u128, &counter, counterInt, endian); | ||
| 46 | var pad = [_]u8{0} ** block_size; | ||
| 47 | mem.copy(u8, &pad, src[i..]); | ||
| 48 | block_cipher.xor(&pad, &pad, counter); | ||
| 49 | mem.copy(u8, dst[i..], pad[0 .. src.len - i]); | ||
| 50 | } | ||
| 51 | } | ||
lib/std/event/lock.zig+90-115| ... | @@ -16,107 +16,107 @@ const Loop = std.event.Loop; | ... | @@ -16,107 +16,107 @@ const Loop = std.event.Loop; |
| 16 | /// Allows only one actor to hold the lock. | 16 | /// Allows only one actor to hold the lock. |
| 17 | /// TODO: make this API also work in blocking I/O mode. | 17 | /// TODO: make this API also work in blocking I/O mode. |
| 18 | pub const Lock = struct { | 18 | pub const Lock = struct { |
| 19 | shared: bool, | 19 | mutex: std.Mutex = std.Mutex{}, |
| 20 | queue: Queue, | 20 | head: usize = UNLOCKED, |
| 21 | queue_empty: bool, | ||
| 22 | 21 | ||
| 23 | const Queue = std.atomic.Queue(anyframe); | 22 | const UNLOCKED = 0; |
| 23 | const LOCKED = 1; | ||
| 24 | 24 | ||
| 25 | const global_event_loop = Loop.instance orelse | 25 | const global_event_loop = Loop.instance orelse |
| 26 | @compileError("std.event.Lock currently only works with event-based I/O"); | 26 | @compileError("std.event.Lock currently only works with event-based I/O"); |
| 27 | 27 | ||
| 28 | pub const Held = struct { | 28 | const Waiter = struct { |
| 29 | lock: *Lock, | 29 | // forced Waiter alignment to ensure it doesn't clash with LOCKED |
| 30 | 30 | next: ?*Waiter align(2), | |
| 31 | pub fn release(self: Held) void { | 31 | tail: *Waiter, |
| 32 | // Resume the next item from the queue. | 32 | node: Loop.NextTickNode, |
| 33 | if (self.lock.queue.get()) |node| { | 33 | }; |
| 34 | global_event_loop.onNextTick(node); | ||
| 35 | return; | ||
| 36 | } | ||
| 37 | |||
| 38 | // We need to release the lock. | ||
| 39 | @atomicStore(bool, &self.lock.queue_empty, true, .SeqCst); | ||
| 40 | @atomicStore(bool, &self.lock.shared, false, .SeqCst); | ||
| 41 | |||
| 42 | // There might be a queue item. If we know the queue is empty, we can be done, | ||
| 43 | // because the other actor will try to obtain the lock. | ||
| 44 | // But if there's a queue item, we are the actor which must loop and attempt | ||
| 45 | // to grab the lock again. | ||
| 46 | if (@atomicLoad(bool, &self.lock.queue_empty, .SeqCst)) { | ||
| 47 | return; | ||
| 48 | } | ||
| 49 | |||
| 50 | while (true) { | ||
| 51 | if (@atomicRmw(bool, &self.lock.shared, .Xchg, true, .SeqCst)) { | ||
| 52 | // We did not obtain the lock. Great, the queue is someone else's problem. | ||
| 53 | return; | ||
| 54 | } | ||
| 55 | |||
| 56 | // Resume the next item from the queue. | ||
| 57 | if (self.lock.queue.get()) |node| { | ||
| 58 | global_event_loop.onNextTick(node); | ||
| 59 | return; | ||
| 60 | } | ||
| 61 | |||
| 62 | // Release the lock again. | ||
| 63 | @atomicStore(bool, &self.lock.queue_empty, true, .SeqCst); | ||
| 64 | @atomicStore(bool, &self.lock.shared, false, .SeqCst); | ||
| 65 | 34 | ||
| 66 | // Find out if we can be done. | 35 | pub fn acquire(self: *Lock) Held { |
| 67 | if (@atomicLoad(bool, &self.lock.queue_empty, .SeqCst)) { | 36 | const held = self.mutex.acquire(); |
| 68 | return; | 37 | |
| 69 | } | 38 | // self.head transitions from multiple stages depending on the value: |
| 70 | } | 39 | // UNLOCKED -> LOCKED: |
| 40 | // acquire Lock ownership when theres no waiters | ||
| 41 | // LOCKED -> <Waiter head ptr>: | ||
| 42 | // Lock is already owned, enqueue first Waiter | ||
| 43 | // <head ptr> -> <head ptr>: | ||
| 44 | // Lock is owned with pending waiters. Push our waiter to the queue. | ||
| 45 | |||
| 46 | if (self.head == UNLOCKED) { | ||
| 47 | self.head = LOCKED; | ||
| 48 | held.release(); | ||
| 49 | return Held{ .lock = self }; | ||
| 71 | } | 50 | } |
| 72 | }; | ||
| 73 | 51 | ||
| 74 | pub fn init() Lock { | 52 | var waiter: Waiter = undefined; |
| 75 | return Lock{ | 53 | waiter.next = null; |
| 76 | .shared = false, | 54 | waiter.tail = &waiter; |
| 77 | .queue = Queue.init(), | ||
| 78 | .queue_empty = true, | ||
| 79 | }; | ||
| 80 | } | ||
| 81 | 55 | ||
| 82 | pub fn initLocked() Lock { | 56 | const head = switch (self.head) { |
| 83 | return Lock{ | 57 | UNLOCKED => unreachable, |
| 84 | .shared = true, | 58 | LOCKED => null, |
| 85 | .queue = Queue.init(), | 59 | else => @intToPtr(*Waiter, self.head), |
| 86 | .queue_empty = true, | ||
| 87 | }; | 60 | }; |
| 88 | } | ||
| 89 | |||
| 90 | /// Must be called when not locked. Not thread safe. | ||
| 91 | /// All calls to acquire() and release() must complete before calling deinit(). | ||
| 92 | pub fn deinit(self: *Lock) void { | ||
| 93 | assert(!self.shared); | ||
| 94 | while (self.queue.get()) |node| resume node.data; | ||
| 95 | } | ||
| 96 | 61 | ||
| 97 | pub fn acquire(self: *Lock) callconv(.Async) Held { | 62 | if (head) |h| { |
| 98 | var my_tick_node = Loop.NextTickNode.init(@frame()); | 63 | h.tail.next = &waiter; |
| 64 | h.tail = &waiter; | ||
| 65 | } else { | ||
| 66 | self.head = @ptrToInt(&waiter); | ||
| 67 | } | ||
| 99 | 68 | ||
| 100 | errdefer _ = self.queue.remove(&my_tick_node); // TODO test canceling an acquire | ||
| 101 | suspend { | 69 | suspend { |
| 102 | self.queue.put(&my_tick_node); | 70 | waiter.node = Loop.NextTickNode{ |
| 103 | 71 | .prev = undefined, | |
| 104 | // At this point, we are in the queue, so we might have already been resumed. | 72 | .next = undefined, |
| 73 | .data = @frame(), | ||
| 74 | }; | ||
| 75 | held.release(); | ||
| 76 | } | ||
| 105 | 77 | ||
| 106 | // We set this bit so that later we can rely on the fact, that if queue_empty == true, some actor | 78 | return Held{ .lock = self }; |
| 107 | // will attempt to grab the lock. | 79 | } |
| 108 | @atomicStore(bool, &self.queue_empty, false, .SeqCst); | ||
| 109 | 80 | ||
| 110 | if (!@atomicRmw(bool, &self.shared, .Xchg, true, .SeqCst)) { | 81 | pub const Held = struct { |
| 111 | if (self.queue.get()) |node| { | 82 | lock: *Lock, |
| 112 | // Whether this node is us or someone else, we tail resume it. | 83 | |
| 113 | resume node.data; | 84 | pub fn release(self: Held) void { |
| 85 | const waiter = blk: { | ||
| 86 | const held = self.lock.mutex.acquire(); | ||
| 87 | defer held.release(); | ||
| 88 | |||
| 89 | // self.head goes through the reverse transition from acquire(): | ||
| 90 | // <head ptr> -> <new head ptr>: | ||
| 91 | // pop a waiter from the queue to give Lock ownership when theres still others pending | ||
| 92 | // <head ptr> -> LOCKED: | ||
| 93 | // pop the laster waiter from the queue, while also giving it lock ownership when awaken | ||
| 94 | // LOCKED -> UNLOCKED: | ||
| 95 | // last lock owner releases lock while no one else is waiting for it | ||
| 96 | |||
| 97 | switch (self.lock.head) { | ||
| 98 | UNLOCKED => { | ||
| 99 | unreachable; // Lock unlocked while unlocking | ||
| 100 | }, | ||
| 101 | LOCKED => { | ||
| 102 | self.lock.head = UNLOCKED; | ||
| 103 | break :blk null; | ||
| 104 | }, | ||
| 105 | else => { | ||
| 106 | const waiter = @intToPtr(*Waiter, self.lock.head); | ||
| 107 | self.lock.head = if (waiter.next == null) LOCKED else @ptrToInt(waiter.next); | ||
| 108 | if (waiter.next) |next| | ||
| 109 | next.tail = waiter.tail; | ||
| 110 | break :blk waiter; | ||
| 111 | }, | ||
| 114 | } | 112 | } |
| 113 | }; | ||
| 114 | |||
| 115 | if (waiter) |w| { | ||
| 116 | global_event_loop.onNextTick(&w.node); | ||
| 115 | } | 117 | } |
| 116 | } | 118 | } |
| 117 | 119 | }; | |
| 118 | return Held{ .lock = self }; | ||
| 119 | } | ||
| 120 | }; | 120 | }; |
| 121 | 121 | ||
| 122 | test "std.event.Lock" { | 122 | test "std.event.Lock" { |
| ... | @@ -128,41 +128,16 @@ test "std.event.Lock" { | ... | @@ -128,41 +128,16 @@ test "std.event.Lock" { |
| 128 | // TODO https://github.com/ziglang/zig/issues/3251 | 128 | // TODO https://github.com/ziglang/zig/issues/3251 |
| 129 | if (builtin.os.tag == .freebsd) return error.SkipZigTest; | 129 | if (builtin.os.tag == .freebsd) return error.SkipZigTest; |
| 130 | 130 | ||
| 131 | // TODO this file has bit-rotted. repair it | 131 | var lock = Lock{}; |
| 132 | if (true) return error.SkipZigTest; | 132 | testLock(&lock); |
| 133 | |||
| 134 | var lock = Lock.init(); | ||
| 135 | defer lock.deinit(); | ||
| 136 | |||
| 137 | _ = async testLock(&lock); | ||
| 138 | 133 | ||
| 139 | const expected_result = [1]i32{3 * @intCast(i32, shared_test_data.len)} ** shared_test_data.len; | 134 | const expected_result = [1]i32{3 * @intCast(i32, shared_test_data.len)} ** shared_test_data.len; |
| 140 | testing.expectEqualSlices(i32, &expected_result, &shared_test_data); | 135 | testing.expectEqualSlices(i32, &expected_result, &shared_test_data); |
| 141 | } | 136 | } |
| 142 | fn testLock(lock: *Lock) callconv(.Async) void { | 137 | fn testLock(lock: *Lock) void { |
| 143 | var handle1 = async lockRunner(lock); | 138 | var handle1 = async lockRunner(lock); |
| 144 | var tick_node1 = Loop.NextTickNode{ | ||
| 145 | .prev = undefined, | ||
| 146 | .next = undefined, | ||
| 147 | .data = &handle1, | ||
| 148 | }; | ||
| 149 | Loop.instance.?.onNextTick(&tick_node1); | ||
| 150 | |||
| 151 | var handle2 = async lockRunner(lock); | 139 | var handle2 = async lockRunner(lock); |
| 152 | var tick_node2 = Loop.NextTickNode{ | ||
| 153 | .prev = undefined, | ||
| 154 | .next = undefined, | ||
| 155 | .data = &handle2, | ||
| 156 | }; | ||
| 157 | Loop.instance.?.onNextTick(&tick_node2); | ||
| 158 | |||
| 159 | var handle3 = async lockRunner(lock); | 140 | var handle3 = async lockRunner(lock); |
| 160 | var tick_node3 = Loop.NextTickNode{ | ||
| 161 | .prev = undefined, | ||
| 162 | .next = undefined, | ||
| 163 | .data = &handle3, | ||
| 164 | }; | ||
| 165 | Loop.instance.?.onNextTick(&tick_node3); | ||
| 166 | 141 | ||
| 167 | await handle1; | 142 | await handle1; |
| 168 | await handle2; | 143 | await handle2; |
| ... | @@ -171,13 +146,13 @@ fn testLock(lock: *Lock) callconv(.Async) void { | ... | @@ -171,13 +146,13 @@ fn testLock(lock: *Lock) callconv(.Async) void { |
| 171 | 146 | ||
| 172 | var shared_test_data = [1]i32{0} ** 10; | 147 | var shared_test_data = [1]i32{0} ** 10; |
| 173 | var shared_test_index: usize = 0; | 148 | var shared_test_index: usize = 0; |
| 174 | fn lockRunner(lock: *Lock) callconv(.Async) void { | 149 | |
| 175 | suspend; // resumed by onNextTick | 150 | fn lockRunner(lock: *Lock) void { |
| 151 | Lock.global_event_loop.yield(); | ||
| 176 | 152 | ||
| 177 | var i: usize = 0; | 153 | var i: usize = 0; |
| 178 | while (i < shared_test_data.len) : (i += 1) { | 154 | while (i < shared_test_data.len) : (i += 1) { |
| 179 | var lock_frame = async lock.acquire(); | 155 | const handle = lock.acquire(); |
| 180 | const handle = await lock_frame; | ||
| 181 | defer handle.release(); | 156 | defer handle.release(); |
| 182 | 157 | ||
| 183 | shared_test_index = 0; | 158 | shared_test_index = 0; |
lib/std/event/loop.zig+326-106| ... | @@ -112,8 +112,9 @@ pub const Loop = struct { | ... | @@ -112,8 +112,9 @@ pub const Loop = struct { |
| 112 | /// have the correct pointer value. | 112 | /// have the correct pointer value. |
| 113 | /// https://github.com/ziglang/zig/issues/2761 and https://github.com/ziglang/zig/issues/2765 | 113 | /// https://github.com/ziglang/zig/issues/2761 and https://github.com/ziglang/zig/issues/2765 |
| 114 | pub fn init(self: *Loop) !void { | 114 | pub fn init(self: *Loop) !void { |
| 115 | if (builtin.single_threaded | 115 | if (builtin.single_threaded or |
| 116 | or (@hasDecl(root, "event_loop_mode") and root.event_loop_mode == .single_threaded)) { | 116 | (@hasDecl(root, "event_loop_mode") and root.event_loop_mode == .single_threaded)) |
| 117 | { | ||
| 117 | return self.initSingleThreaded(); | 118 | return self.initSingleThreaded(); |
| 118 | } else { | 119 | } else { |
| 119 | return self.initMultiThreaded(); | 120 | return self.initMultiThreaded(); |
| ... | @@ -687,9 +688,14 @@ pub const Loop = struct { | ... | @@ -687,9 +688,14 @@ pub const Loop = struct { |
| 687 | 688 | ||
| 688 | switch (builtin.os.tag) { | 689 | switch (builtin.os.tag) { |
| 689 | .linux => { | 690 | .linux => { |
| 690 | // writing 8 bytes to an eventfd cannot fail | 691 | // writing to the eventfd will only wake up one thread, thus multiple writes |
| 691 | const amt = os.write(self.os_data.final_eventfd, &wakeup_bytes) catch unreachable; | 692 | // are needed to wakeup all the threads |
| 692 | assert(amt == wakeup_bytes.len); | 693 | var i: usize = 0; |
| 694 | while (i < self.extra_threads.len + 1) : (i += 1) { | ||
| 695 | // writing 8 bytes to an eventfd cannot fail | ||
| 696 | const amt = os.write(self.os_data.final_eventfd, &wakeup_bytes) catch unreachable; | ||
| 697 | assert(amt == wakeup_bytes.len); | ||
| 698 | } | ||
| 693 | return; | 699 | return; |
| 694 | }, | 700 | }, |
| 695 | .macosx, .freebsd, .netbsd, .dragonfly => { | 701 | .macosx, .freebsd, .netbsd, .dragonfly => { |
| ... | @@ -715,6 +721,50 @@ pub const Loop = struct { | ... | @@ -715,6 +721,50 @@ pub const Loop = struct { |
| 715 | } | 721 | } |
| 716 | } | 722 | } |
| 717 | 723 | ||
| 724 | /// ------- I/0 APIs ------- | ||
| 725 | pub fn accept( | ||
| 726 | self: *Loop, | ||
| 727 | /// This argument is a socket that has been created with `socket`, bound to a local address | ||
| 728 | /// with `bind`, and is listening for connections after a `listen`. | ||
| 729 | sockfd: os.fd_t, | ||
| 730 | /// This argument is a pointer to a sockaddr structure. This structure is filled in with the | ||
| 731 | /// address of the peer socket, as known to the communications layer. The exact format of the | ||
| 732 | /// address returned addr is determined by the socket's address family (see `socket` and the | ||
| 733 | /// respective protocol man pages). | ||
| 734 | addr: *os.sockaddr, | ||
| 735 | /// This argument is a value-result argument: the caller must initialize it to contain the | ||
| 736 | /// size (in bytes) of the structure pointed to by addr; on return it will contain the actual size | ||
| 737 | /// of the peer address. | ||
| 738 | /// | ||
| 739 | /// The returned address is truncated if the buffer provided is too small; in this case, `addr_size` | ||
| 740 | /// will return a value greater than was supplied to the call. | ||
| 741 | addr_size: *os.socklen_t, | ||
| 742 | /// The following values can be bitwise ORed in flags to obtain different behavior: | ||
| 743 | /// * `SOCK_CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor. See the | ||
| 744 | /// description of the `O_CLOEXEC` flag in `open` for reasons why this may be useful. | ||
| 745 | flags: u32, | ||
| 746 | ) os.AcceptError!os.fd_t { | ||
| 747 | while (true) { | ||
| 748 | return os.accept(sockfd, addr, addr_size, flags | os.SOCK_NONBLOCK) catch |err| switch (err) { | ||
| 749 | error.WouldBlock => { | ||
| 750 | self.waitUntilFdReadable(sockfd); | ||
| 751 | continue; | ||
| 752 | }, | ||
| 753 | else => return err, | ||
| 754 | }; | ||
| 755 | } | ||
| 756 | } | ||
| 757 | |||
| 758 | pub fn connect(self: *Loop, sockfd: os.socket_t, sock_addr: *const os.sockaddr, len: os.socklen_t) os.ConnectError!void { | ||
| 759 | os.connect(sockfd, sock_addr, len) catch |err| switch (err) { | ||
| 760 | error.WouldBlock => { | ||
| 761 | self.waitUntilFdWritable(sockfd); | ||
| 762 | return os.getsockoptError(sockfd); | ||
| 763 | }, | ||
| 764 | else => return err, | ||
| 765 | }; | ||
| 766 | } | ||
| 767 | |||
| 718 | /// Performs an async `os.open` using a separate thread. | 768 | /// Performs an async `os.open` using a separate thread. |
| 719 | pub fn openZ(self: *Loop, file_path: [*:0]const u8, flags: u32, mode: os.mode_t) os.OpenError!os.fd_t { | 769 | pub fn openZ(self: *Loop, file_path: [*:0]const u8, flags: u32, mode: os.mode_t) os.OpenError!os.fd_t { |
| 720 | var req_node = Request.Node{ | 770 | var req_node = Request.Node{ |
| ... | @@ -773,152 +823,309 @@ pub const Loop = struct { | ... | @@ -773,152 +823,309 @@ pub const Loop = struct { |
| 773 | 823 | ||
| 774 | /// Performs an async `os.read` using a separate thread. | 824 | /// Performs an async `os.read` using a separate thread. |
| 775 | /// `fd` must block and not return EAGAIN. | 825 | /// `fd` must block and not return EAGAIN. |
| 776 | pub fn read(self: *Loop, fd: os.fd_t, buf: []u8) os.ReadError!usize { | 826 | pub fn read(self: *Loop, fd: os.fd_t, buf: []u8, simulate_evented: bool) os.ReadError!usize { |
| 777 | var req_node = Request.Node{ | 827 | if (simulate_evented) { |
| 778 | .data = .{ | 828 | var req_node = Request.Node{ |
| 779 | .msg = .{ | 829 | .data = .{ |
| 780 | .read = .{ | 830 | .msg = .{ |
| 781 | .fd = fd, | 831 | .read = .{ |
| 782 | .buf = buf, | 832 | .fd = fd, |
| 783 | .result = undefined, | 833 | .buf = buf, |
| 834 | .result = undefined, | ||
| 835 | }, | ||
| 784 | }, | 836 | }, |
| 837 | .finish = .{ .TickNode = .{ .data = @frame() } }, | ||
| 785 | }, | 838 | }, |
| 786 | .finish = .{ .TickNode = .{ .data = @frame() } }, | 839 | }; |
| 787 | }, | 840 | suspend { |
| 788 | }; | 841 | self.posixFsRequest(&req_node); |
| 789 | suspend { | 842 | } |
| 790 | self.posixFsRequest(&req_node); | 843 | return req_node.data.msg.read.result; |
| 844 | } else { | ||
| 845 | while (true) { | ||
| 846 | return os.read(fd, buf) catch |err| switch (err) { | ||
| 847 | error.WouldBlock => { | ||
| 848 | self.waitUntilFdReadable(fd); | ||
| 849 | continue; | ||
| 850 | }, | ||
| 851 | else => return err, | ||
| 852 | }; | ||
| 853 | } | ||
| 791 | } | 854 | } |
| 792 | return req_node.data.msg.read.result; | ||
| 793 | } | 855 | } |
| 794 | 856 | ||
| 795 | /// Performs an async `os.readv` using a separate thread. | 857 | /// Performs an async `os.readv` using a separate thread. |
| 796 | /// `fd` must block and not return EAGAIN. | 858 | /// `fd` must block and not return EAGAIN. |
| 797 | pub fn readv(self: *Loop, fd: os.fd_t, iov: []const os.iovec) os.ReadError!usize { | 859 | pub fn readv(self: *Loop, fd: os.fd_t, iov: []const os.iovec, simulate_evented: bool) os.ReadError!usize { |
| 798 | var req_node = Request.Node{ | 860 | if (simulate_evented) { |
| 799 | .data = .{ | 861 | var req_node = Request.Node{ |
| 800 | .msg = .{ | 862 | .data = .{ |
| 801 | .readv = .{ | 863 | .msg = .{ |
| 802 | .fd = fd, | 864 | .readv = .{ |
| 803 | .iov = iov, | 865 | .fd = fd, |
| 804 | .result = undefined, | 866 | .iov = iov, |
| 867 | .result = undefined, | ||
| 868 | }, | ||
| 805 | }, | 869 | }, |
| 870 | .finish = .{ .TickNode = .{ .data = @frame() } }, | ||
| 806 | }, | 871 | }, |
| 807 | .finish = .{ .TickNode = .{ .data = @frame() } }, | 872 | }; |
| 808 | }, | 873 | suspend { |
| 809 | }; | 874 | self.posixFsRequest(&req_node); |
| 810 | suspend { | 875 | } |
| 811 | self.posixFsRequest(&req_node); | 876 | return req_node.data.msg.readv.result; |
| 877 | } else { | ||
| 878 | while (true) { | ||
| 879 | return os.readv(fd, iov) catch |err| switch (err) { | ||
| 880 | error.WouldBlock => { | ||
| 881 | self.waitUntilFdReadable(fd); | ||
| 882 | continue; | ||
| 883 | }, | ||
| 884 | else => return err, | ||
| 885 | }; | ||
| 886 | } | ||
| 812 | } | 887 | } |
| 813 | return req_node.data.msg.readv.result; | ||
| 814 | } | 888 | } |
| 815 | 889 | ||
| 816 | /// Performs an async `os.pread` using a separate thread. | 890 | /// Performs an async `os.pread` using a separate thread. |
| 817 | /// `fd` must block and not return EAGAIN. | 891 | /// `fd` must block and not return EAGAIN. |
| 818 | pub fn pread(self: *Loop, fd: os.fd_t, buf: []u8, offset: u64) os.PReadError!usize { | 892 | pub fn pread(self: *Loop, fd: os.fd_t, buf: []u8, offset: u64, simulate_evented: bool) os.PReadError!usize { |
| 819 | var req_node = Request.Node{ | 893 | if (simulate_evented) { |
| 820 | .data = .{ | 894 | var req_node = Request.Node{ |
| 821 | .msg = .{ | 895 | .data = .{ |
| 822 | .pread = .{ | 896 | .msg = .{ |
| 823 | .fd = fd, | 897 | .pread = .{ |
| 824 | .buf = buf, | 898 | .fd = fd, |
| 825 | .offset = offset, | 899 | .buf = buf, |
| 826 | .result = undefined, | 900 | .offset = offset, |
| 901 | .result = undefined, | ||
| 902 | }, | ||
| 827 | }, | 903 | }, |
| 904 | .finish = .{ .TickNode = .{ .data = @frame() } }, | ||
| 828 | }, | 905 | }, |
| 829 | .finish = .{ .TickNode = .{ .data = @frame() } }, | 906 | }; |
| 830 | }, | 907 | suspend { |
| 831 | }; | 908 | self.posixFsRequest(&req_node); |
| 832 | suspend { | 909 | } |
| 833 | self.posixFsRequest(&req_node); | 910 | return req_node.data.msg.pread.result; |
| 911 | } else { | ||
| 912 | while (true) { | ||
| 913 | return os.pread(fd, buf, offset) catch |err| switch (err) { | ||
| 914 | error.WouldBlock => { | ||
| 915 | self.waitUntilFdReadable(fd); | ||
| 916 | continue; | ||
| 917 | }, | ||
| 918 | else => return err, | ||
| 919 | }; | ||
| 920 | } | ||
| 834 | } | 921 | } |
| 835 | return req_node.data.msg.pread.result; | ||
| 836 | } | 922 | } |
| 837 | 923 | ||
| 838 | /// Performs an async `os.preadv` using a separate thread. | 924 | /// Performs an async `os.preadv` using a separate thread. |
| 839 | /// `fd` must block and not return EAGAIN. | 925 | /// `fd` must block and not return EAGAIN. |
| 840 | pub fn preadv(self: *Loop, fd: os.fd_t, iov: []const os.iovec, offset: u64) os.ReadError!usize { | 926 | pub fn preadv(self: *Loop, fd: os.fd_t, iov: []const os.iovec, offset: u64, simulate_evented: bool) os.ReadError!usize { |
| 841 | var req_node = Request.Node{ | 927 | if (simulate_evented) { |
| 842 | .data = .{ | 928 | var req_node = Request.Node{ |
| 843 | .msg = .{ | 929 | .data = .{ |
| 844 | .preadv = .{ | 930 | .msg = .{ |
| 845 | .fd = fd, | 931 | .preadv = .{ |
| 846 | .iov = iov, | 932 | .fd = fd, |
| 847 | .offset = offset, | 933 | .iov = iov, |
| 848 | .result = undefined, | 934 | .offset = offset, |
| 935 | .result = undefined, | ||
| 936 | }, | ||
| 849 | }, | 937 | }, |
| 938 | .finish = .{ .TickNode = .{ .data = @frame() } }, | ||
| 850 | }, | 939 | }, |
| 851 | .finish = .{ .TickNode = .{ .data = @frame() } }, | 940 | }; |
| 852 | }, | 941 | suspend { |
| 853 | }; | 942 | self.posixFsRequest(&req_node); |
| 854 | suspend { | 943 | } |
| 855 | self.posixFsRequest(&req_node); | 944 | return req_node.data.msg.preadv.result; |
| 945 | } else { | ||
| 946 | while (true) { | ||
| 947 | return os.preadv(fd, iov, offset) catch |err| switch (err) { | ||
| 948 | error.WouldBlock => { | ||
| 949 | self.waitUntilFdReadable(fd); | ||
| 950 | continue; | ||
| 951 | }, | ||
| 952 | else => return err, | ||
| 953 | }; | ||
| 954 | } | ||
| 856 | } | 955 | } |
| 857 | return req_node.data.msg.preadv.result; | ||
| 858 | } | 956 | } |
| 859 | 957 | ||
| 860 | /// Performs an async `os.write` using a separate thread. | 958 | /// Performs an async `os.write` using a separate thread. |
| 861 | /// `fd` must block and not return EAGAIN. | 959 | /// `fd` must block and not return EAGAIN. |
| 862 | pub fn write(self: *Loop, fd: os.fd_t, bytes: []const u8) os.WriteError!usize { | 960 | pub fn write(self: *Loop, fd: os.fd_t, bytes: []const u8, simulate_evented: bool) os.WriteError!usize { |
| 863 | var req_node = Request.Node{ | 961 | if (simulate_evented) { |
| 864 | .data = .{ | 962 | var req_node = Request.Node{ |
| 865 | .msg = .{ | 963 | .data = .{ |
| 866 | .write = .{ | 964 | .msg = .{ |
| 867 | .fd = fd, | 965 | .write = .{ |
| 868 | .bytes = bytes, | 966 | .fd = fd, |
| 869 | .result = undefined, | 967 | .bytes = bytes, |
| 968 | .result = undefined, | ||
| 969 | }, | ||
| 870 | }, | 970 | }, |
| 971 | .finish = .{ .TickNode = .{ .data = @frame() } }, | ||
| 871 | }, | 972 | }, |
| 872 | .finish = .{ .TickNode = .{ .data = @frame() } }, | 973 | }; |
| 873 | }, | 974 | suspend { |
| 874 | }; | 975 | self.posixFsRequest(&req_node); |
| 875 | suspend { | 976 | } |
| 876 | self.posixFsRequest(&req_node); | 977 | return req_node.data.msg.write.result; |
| 978 | } else { | ||
| 979 | while (true) { | ||
| 980 | return os.write(fd, bytes) catch |err| switch (err) { | ||
| 981 | error.WouldBlock => { | ||
| 982 | self.waitUntilFdWritable(fd); | ||
| 983 | continue; | ||
| 984 | }, | ||
| 985 | else => return err, | ||
| 986 | }; | ||
| 987 | } | ||
| 877 | } | 988 | } |
| 878 | return req_node.data.msg.write.result; | ||
| 879 | } | 989 | } |
| 880 | 990 | ||
| 881 | /// Performs an async `os.writev` using a separate thread. | 991 | /// Performs an async `os.writev` using a separate thread. |
| 882 | /// `fd` must block and not return EAGAIN. | 992 | /// `fd` must block and not return EAGAIN. |
| 883 | pub fn writev(self: *Loop, fd: os.fd_t, iov: []const os.iovec_const) os.WriteError!usize { | 993 | pub fn writev(self: *Loop, fd: os.fd_t, iov: []const os.iovec_const, simulate_evented: bool) os.WriteError!usize { |
| 884 | var req_node = Request.Node{ | 994 | if (simulate_evented) { |
| 885 | .data = .{ | 995 | var req_node = Request.Node{ |
| 886 | .msg = .{ | 996 | .data = .{ |
| 887 | .writev = .{ | 997 | .msg = .{ |
| 888 | .fd = fd, | 998 | .writev = .{ |
| 889 | .iov = iov, | 999 | .fd = fd, |
| 890 | .result = undefined, | 1000 | .iov = iov, |
| 1001 | .result = undefined, | ||
| 1002 | }, | ||
| 891 | }, | 1003 | }, |
| 1004 | .finish = .{ .TickNode = .{ .data = @frame() } }, | ||
| 892 | }, | 1005 | }, |
| 893 | .finish = .{ .TickNode = .{ .data = @frame() } }, | 1006 | }; |
| 894 | }, | 1007 | suspend { |
| 895 | }; | 1008 | self.posixFsRequest(&req_node); |
| 896 | suspend { | 1009 | } |
| 897 | self.posixFsRequest(&req_node); | 1010 | return req_node.data.msg.writev.result; |
| 1011 | } else { | ||
| 1012 | while (true) { | ||
| 1013 | return os.writev(fd, iov) catch |err| switch (err) { | ||
| 1014 | error.WouldBlock => { | ||
| 1015 | self.waitUntilFdWritable(fd); | ||
| 1016 | continue; | ||
| 1017 | }, | ||
| 1018 | else => return err, | ||
| 1019 | }; | ||
| 1020 | } | ||
| 1021 | } | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | /// Performs an async `os.pwrite` using a separate thread. | ||
| 1025 | /// `fd` must block and not return EAGAIN. | ||
| 1026 | pub fn pwrite(self: *Loop, fd: os.fd_t, bytes: []const u8, offset: u64, simulate_evented: bool) os.PerformsWriteError!usize { | ||
| 1027 | if (simulate_evented) { | ||
| 1028 | var req_node = Request.Node{ | ||
| 1029 | .data = .{ | ||
| 1030 | .msg = .{ | ||
| 1031 | .pwrite = .{ | ||
| 1032 | .fd = fd, | ||
| 1033 | .bytes = bytes, | ||
| 1034 | .offset = offset, | ||
| 1035 | .result = undefined, | ||
| 1036 | }, | ||
| 1037 | }, | ||
| 1038 | .finish = .{ .TickNode = .{ .data = @frame() } }, | ||
| 1039 | }, | ||
| 1040 | }; | ||
| 1041 | suspend { | ||
| 1042 | self.posixFsRequest(&req_node); | ||
| 1043 | } | ||
| 1044 | return req_node.data.msg.pwrite.result; | ||
| 1045 | } else { | ||
| 1046 | while (true) { | ||
| 1047 | return os.pwrite(fd, bytes, offset) catch |err| switch (err) { | ||
| 1048 | error.WouldBlock => { | ||
| 1049 | self.waitUntilFdWritable(fd); | ||
| 1050 | continue; | ||
| 1051 | }, | ||
| 1052 | else => return err, | ||
| 1053 | }; | ||
| 1054 | } | ||
| 898 | } | 1055 | } |
| 899 | return req_node.data.msg.writev.result; | ||
| 900 | } | 1056 | } |
| 901 | 1057 | ||
| 902 | /// Performs an async `os.pwritev` using a separate thread. | 1058 | /// Performs an async `os.pwritev` using a separate thread. |
| 903 | /// `fd` must block and not return EAGAIN. | 1059 | /// `fd` must block and not return EAGAIN. |
| 904 | pub fn pwritev(self: *Loop, fd: os.fd_t, iov: []const os.iovec_const, offset: u64) os.WriteError!usize { | 1060 | pub fn pwritev(self: *Loop, fd: os.fd_t, iov: []const os.iovec_const, offset: u64, simulate_evented: bool) os.PWriteError!usize { |
| 905 | var req_node = Request.Node{ | 1061 | if (simulate_evented) { |
| 906 | .data = .{ | 1062 | var req_node = Request.Node{ |
| 907 | .msg = .{ | 1063 | .data = .{ |
| 908 | .pwritev = .{ | 1064 | .msg = .{ |
| 909 | .fd = fd, | 1065 | .pwritev = .{ |
| 910 | .iov = iov, | 1066 | .fd = fd, |
| 911 | .offset = offset, | 1067 | .iov = iov, |
| 912 | .result = undefined, | 1068 | .offset = offset, |
| 1069 | .result = undefined, | ||
| 1070 | }, | ||
| 913 | }, | 1071 | }, |
| 1072 | .finish = .{ .TickNode = .{ .data = @frame() } }, | ||
| 914 | }, | 1073 | }, |
| 915 | .finish = .{ .TickNode = .{ .data = @frame() } }, | 1074 | }; |
| 916 | }, | 1075 | suspend { |
| 917 | }; | 1076 | self.posixFsRequest(&req_node); |
| 918 | suspend { | 1077 | } |
| 919 | self.posixFsRequest(&req_node); | 1078 | return req_node.data.msg.pwritev.result; |
| 1079 | } else { | ||
| 1080 | while (true) { | ||
| 1081 | return os.pwritev(fd, iov, offset) catch |err| switch (err) { | ||
| 1082 | error.WouldBlock => { | ||
| 1083 | self.waitUntilFdWritable(fd); | ||
| 1084 | continue; | ||
| 1085 | }, | ||
| 1086 | else => return err, | ||
| 1087 | }; | ||
| 1088 | } | ||
| 1089 | } | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | pub fn sendto( | ||
| 1093 | self: *Loop, | ||
| 1094 | /// The file descriptor of the sending socket. | ||
| 1095 | sockfd: os.fd_t, | ||
| 1096 | /// Message to send. | ||
| 1097 | buf: []const u8, | ||
| 1098 | flags: u32, | ||
| 1099 | dest_addr: ?*const os.sockaddr, | ||
| 1100 | addrlen: os.socklen_t, | ||
| 1101 | ) os.SendError!usize { | ||
| 1102 | while (true) { | ||
| 1103 | return os.sendto(sockfd, buf, flags, dest_addr, addrlen) catch |err| switch (err) { | ||
| 1104 | error.WouldBlock => { | ||
| 1105 | self.waitUntilFdWritable(sockfd); | ||
| 1106 | continue; | ||
| 1107 | }, | ||
| 1108 | else => return err, | ||
| 1109 | }; | ||
| 1110 | } | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | pub fn recvfrom( | ||
| 1114 | sockfd: os.fd_t, | ||
| 1115 | buf: []u8, | ||
| 1116 | flags: u32, | ||
| 1117 | src_addr: ?*os.sockaddr, | ||
| 1118 | addrlen: ?*os.socklen_t, | ||
| 1119 | ) os.RecvFromError!usize { | ||
| 1120 | while (true) { | ||
| 1121 | return os.recvfrom(sockfd, buf, flags, src_addr, addrlen) catch |err| switch (err) { | ||
| 1122 | error.WouldBlock => { | ||
| 1123 | self.waitUntilFdReadable(sockfd); | ||
| 1124 | continue; | ||
| 1125 | }, | ||
| 1126 | else => return err, | ||
| 1127 | }; | ||
| 920 | } | 1128 | } |
| 921 | return req_node.data.msg.pwritev.result; | ||
| 922 | } | 1129 | } |
| 923 | 1130 | ||
| 924 | /// Performs an async `os.faccessatZ` using a separate thread. | 1131 | /// Performs an async `os.faccessatZ` using a separate thread. |
| ... | @@ -1073,6 +1280,9 @@ pub const Loop = struct { | ... | @@ -1073,6 +1280,9 @@ pub const Loop = struct { |
| 1073 | .writev => |*msg| { | 1280 | .writev => |*msg| { |
| 1074 | msg.result = os.writev(msg.fd, msg.iov); | 1281 | msg.result = os.writev(msg.fd, msg.iov); |
| 1075 | }, | 1282 | }, |
| 1283 | .pwrite => |*msg| { | ||
| 1284 | msg.result = os.pwrite(msg.fd, msg.bytes, msg.offset); | ||
| 1285 | }, | ||
| 1076 | .pwritev => |*msg| { | 1286 | .pwritev => |*msg| { |
| 1077 | msg.result = os.pwritev(msg.fd, msg.iov, msg.offset); | 1287 | msg.result = os.pwritev(msg.fd, msg.iov, msg.offset); |
| 1078 | }, | 1288 | }, |
| ... | @@ -1142,6 +1352,7 @@ pub const Loop = struct { | ... | @@ -1142,6 +1352,7 @@ pub const Loop = struct { |
| 1142 | readv: ReadV, | 1352 | readv: ReadV, |
| 1143 | write: Write, | 1353 | write: Write, |
| 1144 | writev: WriteV, | 1354 | writev: WriteV, |
| 1355 | pwrite: PWrite, | ||
| 1145 | pwritev: PWriteV, | 1356 | pwritev: PWriteV, |
| 1146 | pread: PRead, | 1357 | pread: PRead, |
| 1147 | preadv: PReadV, | 1358 | preadv: PReadV, |
| ... | @@ -1185,6 +1396,15 @@ pub const Loop = struct { | ... | @@ -1185,6 +1396,15 @@ pub const Loop = struct { |
| 1185 | pub const Error = os.WriteError; | 1396 | pub const Error = os.WriteError; |
| 1186 | }; | 1397 | }; |
| 1187 | 1398 | ||
| 1399 | pub const PWrite = struct { | ||
| 1400 | fd: os.fd_t, | ||
| 1401 | bytes: []const u8, | ||
| 1402 | offset: usize, | ||
| 1403 | result: Error!usize, | ||
| 1404 | |||
| 1405 | pub const Error = os.PWriteError; | ||
| 1406 | }; | ||
| 1407 | |||
| 1188 | pub const PWriteV = struct { | 1408 | pub const PWriteV = struct { |
| 1189 | fd: os.fd_t, | 1409 | fd: os.fd_t, |
| 1190 | iov: []const os.iovec_const, | 1410 | iov: []const os.iovec_const, |
lib/std/fifo.zig+11-1| ... | @@ -186,7 +186,9 @@ pub fn LinearFifo( | ... | @@ -186,7 +186,9 @@ pub fn LinearFifo( |
| 186 | } else { | 186 | } else { |
| 187 | var head = self.head + count; | 187 | var head = self.head + count; |
| 188 | if (powers_of_two) { | 188 | if (powers_of_two) { |
| 189 | head &= self.buf.len - 1; | 189 | // Note it is safe to do a wrapping subtract as |
| 190 | // bitwise & with all 1s is a noop | ||
| 191 | head &= self.buf.len -% 1; | ||
| 190 | } else { | 192 | } else { |
| 191 | head %= self.buf.len; | 193 | head %= self.buf.len; |
| 192 | } | 194 | } |
| ... | @@ -376,6 +378,14 @@ pub fn LinearFifo( | ... | @@ -376,6 +378,14 @@ pub fn LinearFifo( |
| 376 | }; | 378 | }; |
| 377 | } | 379 | } |
| 378 | 380 | ||
| 381 | test "LinearFifo(u8, .Dynamic) discard(0) from empty buffer should not error on overflow" { | ||
| 382 | var fifo = LinearFifo(u8, .Dynamic).init(testing.allocator); | ||
| 383 | defer fifo.deinit(); | ||
| 384 | |||
| 385 | // If overflow is not explicitly allowed this will crash in debug / safe mode | ||
| 386 | fifo.discard(0); | ||
| 387 | } | ||
| 388 | |||
| 379 | test "LinearFifo(u8, .Dynamic)" { | 389 | test "LinearFifo(u8, .Dynamic)" { |
| 380 | var fifo = LinearFifo(u8, .Dynamic).init(testing.allocator); | 390 | var fifo = LinearFifo(u8, .Dynamic).init(testing.allocator); |
| 381 | defer fifo.deinit(); | 391 | defer fifo.deinit(); |
lib/std/fs/file.zig+40-24| ... | @@ -414,10 +414,12 @@ pub const File = struct { | ... | @@ -414,10 +414,12 @@ pub const File = struct { |
| 414 | pub fn read(self: File, buffer: []u8) ReadError!usize { | 414 | pub fn read(self: File, buffer: []u8) ReadError!usize { |
| 415 | if (is_windows) { | 415 | if (is_windows) { |
| 416 | return windows.ReadFile(self.handle, buffer, null, self.intended_io_mode); | 416 | return windows.ReadFile(self.handle, buffer, null, self.intended_io_mode); |
| 417 | } else if (self.capable_io_mode != self.intended_io_mode) { | 417 | } |
| 418 | return std.event.Loop.instance.?.read(self.handle, buffer); | 418 | |
| 419 | } else { | 419 | if (self.intended_io_mode == .blocking) { |
| 420 | return os.read(self.handle, buffer); | 420 | return os.read(self.handle, buffer); |
| 421 | } else { | ||
| 422 | return std.event.Loop.instance.?.read(self.handle, buffer, self.capable_io_mode != self.intended_io_mode); | ||
| 421 | } | 423 | } |
| 422 | } | 424 | } |
| 423 | 425 | ||
| ... | @@ -436,10 +438,12 @@ pub const File = struct { | ... | @@ -436,10 +438,12 @@ pub const File = struct { |
| 436 | pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize { | 438 | pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize { |
| 437 | if (is_windows) { | 439 | if (is_windows) { |
| 438 | return windows.ReadFile(self.handle, buffer, offset, self.intended_io_mode); | 440 | return windows.ReadFile(self.handle, buffer, offset, self.intended_io_mode); |
| 439 | } else if (self.capable_io_mode != self.intended_io_mode) { | 441 | } |
| 440 | return std.event.Loop.instance.?.pread(self.handle, buffer, offset); | 442 | |
| 441 | } else { | 443 | if (self.intended_io_mode == .blocking) { |
| 442 | return os.pread(self.handle, buffer, offset); | 444 | return os.pread(self.handle, buffer, offset); |
| 445 | } else { | ||
| 446 | return std.event.Loop.instance.?.pread(self.handle, buffer, offset, self.capable_io_mode != self.intended_io_mode); | ||
| 443 | } | 447 | } |
| 444 | } | 448 | } |
| 445 | 449 | ||
| ... | @@ -461,10 +465,12 @@ pub const File = struct { | ... | @@ -461,10 +465,12 @@ pub const File = struct { |
| 461 | if (iovecs.len == 0) return @as(usize, 0); | 465 | if (iovecs.len == 0) return @as(usize, 0); |
| 462 | const first = iovecs[0]; | 466 | const first = iovecs[0]; |
| 463 | return windows.ReadFile(self.handle, first.iov_base[0..first.iov_len], null, self.intended_io_mode); | 467 | return windows.ReadFile(self.handle, first.iov_base[0..first.iov_len], null, self.intended_io_mode); |
| 464 | } else if (self.capable_io_mode != self.intended_io_mode) { | 468 | } |
| 465 | return std.event.Loop.instance.?.readv(self.handle, iovecs); | 469 | |
| 466 | } else { | 470 | if (self.intended_io_mode == .blocking) { |
| 467 | return os.readv(self.handle, iovecs); | 471 | return os.readv(self.handle, iovecs); |
| 472 | } else { | ||
| 473 | return std.event.Loop.instance.?.readv(self.handle, iovecs, self.capable_io_mode != self.intended_io_mode); | ||
| 468 | } | 474 | } |
| 469 | } | 475 | } |
| 470 | 476 | ||
| ... | @@ -500,10 +506,12 @@ pub const File = struct { | ... | @@ -500,10 +506,12 @@ pub const File = struct { |
| 500 | if (iovecs.len == 0) return @as(usize, 0); | 506 | if (iovecs.len == 0) return @as(usize, 0); |
| 501 | const first = iovecs[0]; | 507 | const first = iovecs[0]; |
| 502 | return windows.ReadFile(self.handle, first.iov_base[0..first.iov_len], offset, self.intended_io_mode); | 508 | return windows.ReadFile(self.handle, first.iov_base[0..first.iov_len], offset, self.intended_io_mode); |
| 503 | } else if (self.capable_io_mode != self.intended_io_mode) { | 509 | } |
| 504 | return std.event.Loop.instance.?.preadv(self.handle, iovecs, offset); | 510 | |
| 505 | } else { | 511 | if (self.intended_io_mode == .blocking) { |
| 506 | return os.preadv(self.handle, iovecs, offset); | 512 | return os.preadv(self.handle, iovecs, offset); |
| 513 | } else { | ||
| 514 | return std.event.Loop.instance.?.preadv(self.handle, iovecs, offset, self.capable_io_mode != self.intended_io_mode); | ||
| 507 | } | 515 | } |
| 508 | } | 516 | } |
| 509 | 517 | ||
| ... | @@ -539,10 +547,12 @@ pub const File = struct { | ... | @@ -539,10 +547,12 @@ pub const File = struct { |
| 539 | pub fn write(self: File, bytes: []const u8) WriteError!usize { | 547 | pub fn write(self: File, bytes: []const u8) WriteError!usize { |
| 540 | if (is_windows) { | 548 | if (is_windows) { |
| 541 | return windows.WriteFile(self.handle, bytes, null, self.intended_io_mode); | 549 | return windows.WriteFile(self.handle, bytes, null, self.intended_io_mode); |
| 542 | } else if (self.capable_io_mode != self.intended_io_mode) { | 550 | } |
| 543 | return std.event.Loop.instance.?.write(self.handle, bytes); | 551 | |
| 544 | } else { | 552 | if (self.intended_io_mode == .blocking) { |
| 545 | return os.write(self.handle, bytes); | 553 | return os.write(self.handle, bytes); |
| 554 | } else { | ||
| 555 | return std.event.Loop.instance.?.write(self.handle, bytes, self.capable_io_mode != self.intended_io_mode); | ||
| 546 | } | 556 | } |
| 547 | } | 557 | } |
| 548 | 558 | ||
| ... | @@ -556,10 +566,12 @@ pub const File = struct { | ... | @@ -556,10 +566,12 @@ pub const File = struct { |
| 556 | pub fn pwrite(self: File, bytes: []const u8, offset: u64) PWriteError!usize { | 566 | pub fn pwrite(self: File, bytes: []const u8, offset: u64) PWriteError!usize { |
| 557 | if (is_windows) { | 567 | if (is_windows) { |
| 558 | return windows.WriteFile(self.handle, bytes, offset, self.intended_io_mode); | 568 | return windows.WriteFile(self.handle, bytes, offset, self.intended_io_mode); |
| 559 | } else if (self.capable_io_mode != self.intended_io_mode) { | 569 | } |
| 560 | return std.event.Loop.instance.?.pwrite(self.handle, bytes, offset); | 570 | |
| 561 | } else { | 571 | if (self.intended_io_mode == .blocking) { |
| 562 | return os.pwrite(self.handle, bytes, offset); | 572 | return os.pwrite(self.handle, bytes, offset); |
| 573 | } else { | ||
| 574 | return std.event.Loop.instance.?.pwrite(self.handle, bytes, offset, self.capable_io_mode != self.intended_io_mode); | ||
| 563 | } | 575 | } |
| 564 | } | 576 | } |
| 565 | 577 | ||
| ... | @@ -576,10 +588,12 @@ pub const File = struct { | ... | @@ -576,10 +588,12 @@ pub const File = struct { |
| 576 | if (iovecs.len == 0) return @as(usize, 0); | 588 | if (iovecs.len == 0) return @as(usize, 0); |
| 577 | const first = iovecs[0]; | 589 | const first = iovecs[0]; |
| 578 | return windows.WriteFile(self.handle, first.iov_base[0..first.iov_len], null, self.intended_io_mode); | 590 | return windows.WriteFile(self.handle, first.iov_base[0..first.iov_len], null, self.intended_io_mode); |
| 579 | } else if (self.capable_io_mode != self.intended_io_mode) { | 591 | } |
| 580 | return std.event.Loop.instance.?.writev(self.handle, iovecs); | 592 | |
| 581 | } else { | 593 | if (self.intended_io_mode == .blocking) { |
| 582 | return os.writev(self.handle, iovecs); | 594 | return os.writev(self.handle, iovecs); |
| 595 | } else { | ||
| 596 | return std.event.Loop.instance.?.writev(self.handle, iovecs, self.capable_io_mode != self.intended_io_mode); | ||
| 583 | } | 597 | } |
| 584 | } | 598 | } |
| 585 | 599 | ||
| ... | @@ -607,10 +621,12 @@ pub const File = struct { | ... | @@ -607,10 +621,12 @@ pub const File = struct { |
| 607 | if (iovecs.len == 0) return @as(usize, 0); | 621 | if (iovecs.len == 0) return @as(usize, 0); |
| 608 | const first = iovecs[0]; | 622 | const first = iovecs[0]; |
| 609 | return windows.WriteFile(self.handle, first.iov_base[0..first.iov_len], offset, self.intended_io_mode); | 623 | return windows.WriteFile(self.handle, first.iov_base[0..first.iov_len], offset, self.intended_io_mode); |
| 610 | } else if (self.capable_io_mode != self.intended_io_mode) { | 624 | } |
| 611 | return std.event.Loop.instance.?.pwritev(self.handle, iovecs, offset); | 625 | |
| 612 | } else { | 626 | if (self.intended_io_mode == .blocking) { |
| 613 | return os.pwritev(self.handle, iovecs, offset); | 627 | return os.pwritev(self.handle, iovecs, offset); |
| 628 | } else { | ||
| 629 | return std.event.Loop.instance.?.pwritev(self.handle, iovecs, offset, self.capable_io_mode != self.intended_io_mode); | ||
| 614 | } | 630 | } |
| 615 | } | 631 | } |
| 616 | 632 |
lib/std/fs/test.zig+23| ... | @@ -813,3 +813,26 @@ fn run_lock_file_test(contexts: []FileLockTestContext) !void { | ... | @@ -813,3 +813,26 @@ fn run_lock_file_test(contexts: []FileLockTestContext) !void { |
| 813 | try threads.append(try std.Thread.spawn(ctx, FileLockTestContext.run)); | 813 | try threads.append(try std.Thread.spawn(ctx, FileLockTestContext.run)); |
| 814 | } | 814 | } |
| 815 | } | 815 | } |
| 816 | |||
| 817 | test "deleteDir" { | ||
| 818 | var tmp_dir = tmpDir(.{}); | ||
| 819 | defer tmp_dir.cleanup(); | ||
| 820 | |||
| 821 | // deleting a non-existent directory | ||
| 822 | testing.expectError(error.FileNotFound, tmp_dir.dir.deleteDir("test_dir")); | ||
| 823 | |||
| 824 | var dir = try tmp_dir.dir.makeOpenPath("test_dir", .{}); | ||
| 825 | var file = try dir.createFile("test_file", .{}); | ||
| 826 | file.close(); | ||
| 827 | dir.close(); | ||
| 828 | |||
| 829 | // deleting a non-empty directory | ||
| 830 | testing.expectError(error.DirNotEmpty, tmp_dir.dir.deleteDir("test_dir")); | ||
| 831 | |||
| 832 | dir = try tmp_dir.dir.openDir("test_dir", .{}); | ||
| 833 | try dir.deleteFile("test_file"); | ||
| 834 | dir.close(); | ||
| 835 | |||
| 836 | // deleting an empty directory | ||
| 837 | try tmp_dir.dir.deleteDir("test_dir"); | ||
| 838 | } |
lib/std/heap.zig+7| ... | @@ -919,6 +919,13 @@ pub fn testAllocator(base_allocator: *mem.Allocator) !void { | ... | @@ -919,6 +919,13 @@ pub fn testAllocator(base_allocator: *mem.Allocator) !void { |
| 919 | const zero_bit_ptr = try allocator.create(u0); | 919 | const zero_bit_ptr = try allocator.create(u0); |
| 920 | zero_bit_ptr.* = 0; | 920 | zero_bit_ptr.* = 0; |
| 921 | allocator.destroy(zero_bit_ptr); | 921 | allocator.destroy(zero_bit_ptr); |
| 922 | |||
| 923 | const oversize = try allocator.allocAdvanced(u32, null, 5, .at_least); | ||
| 924 | testing.expect(oversize.len >= 5); | ||
| 925 | for (oversize) |*item| { | ||
| 926 | item.* = 0xDEADBEEF; | ||
| 927 | } | ||
| 928 | allocator.free(oversize); | ||
| 922 | } | 929 | } |
| 923 | 930 | ||
| 924 | pub fn testAllocatorAligned(base_allocator: *mem.Allocator, comptime alignment: u29) !void { | 931 | pub fn testAllocatorAligned(base_allocator: *mem.Allocator, comptime alignment: u29) !void { |
lib/std/heap/arena_allocator.zig+15-6| ... | @@ -75,13 +75,22 @@ pub const ArenaAllocator = struct { | ... | @@ -75,13 +75,22 @@ pub const ArenaAllocator = struct { |
| 75 | const adjusted_addr = mem.alignForward(addr, ptr_align); | 75 | const adjusted_addr = mem.alignForward(addr, ptr_align); |
| 76 | const adjusted_index = self.state.end_index + (adjusted_addr - addr); | 76 | const adjusted_index = self.state.end_index + (adjusted_addr - addr); |
| 77 | const new_end_index = adjusted_index + n; | 77 | const new_end_index = adjusted_index + n; |
| 78 | if (new_end_index > cur_buf.len) { | 78 | |
| 79 | cur_node = try self.createNode(cur_buf.len, n + ptr_align); | 79 | if (new_end_index <= cur_buf.len) { |
| 80 | continue; | 80 | const result = cur_buf[adjusted_index..new_end_index]; |
| 81 | self.state.end_index = new_end_index; | ||
| 82 | return result; | ||
| 81 | } | 83 | } |
| 82 | const result = cur_buf[adjusted_index..new_end_index]; | 84 | |
| 83 | self.state.end_index = new_end_index; | 85 | const bigger_buf_size = @sizeOf(BufNode) + new_end_index; |
| 84 | return result; | 86 | // Try to grow the buffer in-place |
| 87 | cur_node.data = self.child_allocator.resize(cur_node.data, bigger_buf_size) catch |err| switch (err) { | ||
| 88 | error.OutOfMemory => { | ||
| 89 | // Allocate a new node if that's not possible | ||
| 90 | cur_node = try self.createNode(cur_buf.len, n + ptr_align); | ||
| 91 | continue; | ||
| 92 | }, | ||
| 93 | }; | ||
| 85 | } | 94 | } |
| 86 | } | 95 | } |
| 87 | 96 |
lib/std/net.zig+36-14| ... | @@ -614,11 +614,11 @@ pub fn connectUnixSocket(path: []const u8) !fs.File { | ... | @@ -614,11 +614,11 @@ pub fn connectUnixSocket(path: []const u8) !fs.File { |
| 614 | 614 | ||
| 615 | var addr = try std.net.Address.initUnix(path); | 615 | var addr = try std.net.Address.initUnix(path); |
| 616 | 616 | ||
| 617 | try os.connect( | 617 | if (std.io.is_async) { |
| 618 | sockfd, | 618 | try loop.connect(sockfd, &addr.any, addr.getOsSockLen()); |
| 619 | &addr.any, | 619 | } else { |
| 620 | addr.getOsSockLen(), | 620 | try os.connect(sockfd, &addr.any, addr.getOsSockLen()); |
| 621 | ); | 621 | } |
| 622 | 622 | ||
| 623 | return fs.File{ | 623 | return fs.File{ |
| 624 | .handle = sockfd, | 624 | .handle = sockfd, |
| ... | @@ -677,7 +677,13 @@ pub fn tcpConnectToAddress(address: Address) !fs.File { | ... | @@ -677,7 +677,13 @@ pub fn tcpConnectToAddress(address: Address) !fs.File { |
| 677 | (if (builtin.os.tag == .windows) 0 else os.SOCK_CLOEXEC); | 677 | (if (builtin.os.tag == .windows) 0 else os.SOCK_CLOEXEC); |
| 678 | const sockfd = try os.socket(address.any.family, sock_flags, os.IPPROTO_TCP); | 678 | const sockfd = try os.socket(address.any.family, sock_flags, os.IPPROTO_TCP); |
| 679 | errdefer os.close(sockfd); | 679 | errdefer os.close(sockfd); |
| 680 | try os.connect(sockfd, &address.any, address.getOsSockLen()); | 680 | |
| 681 | if (std.io.is_async) { | ||
| 682 | const loop = std.event.Loop.instance orelse return error.WouldBlock; | ||
| 683 | try loop.connect(sockfd, &address.any, address.getOsSockLen()); | ||
| 684 | } else { | ||
| 685 | try os.connect(sockfd, &address.any, address.getOsSockLen()); | ||
| 686 | } | ||
| 681 | 687 | ||
| 682 | return fs.File{ .handle = sockfd }; | 688 | return fs.File{ .handle = sockfd }; |
| 683 | } | 689 | } |
| ... | @@ -1429,7 +1435,11 @@ fn resMSendRc( | ... | @@ -1429,7 +1435,11 @@ fn resMSendRc( |
| 1429 | if (answers[i].len == 0) { | 1435 | if (answers[i].len == 0) { |
| 1430 | var j: usize = 0; | 1436 | var j: usize = 0; |
| 1431 | while (j < ns.len) : (j += 1) { | 1437 | while (j < ns.len) : (j += 1) { |
| 1432 | _ = os.sendto(fd, queries[i], os.MSG_NOSIGNAL, &ns[j].any, sl) catch undefined; | 1438 | if (std.io.is_async) { |
| 1439 | _ = std.event.Loop.instance.?.sendto(fd, queries[i], os.MSG_NOSIGNAL, &ns[j].any, sl) catch undefined; | ||
| 1440 | } else { | ||
| 1441 | _ = os.sendto(fd, queries[i], os.MSG_NOSIGNAL, &ns[j].any, sl) catch undefined; | ||
| 1442 | } | ||
| 1433 | } | 1443 | } |
| 1434 | } | 1444 | } |
| 1435 | } | 1445 | } |
| ... | @@ -1444,7 +1454,10 @@ fn resMSendRc( | ... | @@ -1444,7 +1454,10 @@ fn resMSendRc( |
| 1444 | 1454 | ||
| 1445 | while (true) { | 1455 | while (true) { |
| 1446 | var sl_copy = sl; | 1456 | var sl_copy = sl; |
| 1447 | const rlen = os.recvfrom(fd, answer_bufs[next], 0, &sa.any, &sl_copy) catch break; | 1457 | const rlen = if (std.io.is_async) |
| 1458 | std.event.Loop.instance.?.recvfrom(fd, answer_bufs[next], 0, &sa.any, &sl_copy) catch break | ||
| 1459 | else | ||
| 1460 | os.recvfrom(fd, answer_bufs[next], 0, &sa.any, &sl_copy) catch break; | ||
| 1448 | 1461 | ||
| 1449 | // Ignore non-identifiable packets | 1462 | // Ignore non-identifiable packets |
| 1450 | if (rlen < 4) continue; | 1463 | if (rlen < 4) continue; |
| ... | @@ -1470,7 +1483,11 @@ fn resMSendRc( | ... | @@ -1470,7 +1483,11 @@ fn resMSendRc( |
| 1470 | 0, 3 => {}, | 1483 | 0, 3 => {}, |
| 1471 | 2 => if (servfail_retry != 0) { | 1484 | 2 => if (servfail_retry != 0) { |
| 1472 | servfail_retry -= 1; | 1485 | servfail_retry -= 1; |
| 1473 | _ = os.sendto(fd, queries[i], os.MSG_NOSIGNAL, &ns[j].any, sl) catch undefined; | 1486 | if (std.io.is_async) { |
| 1487 | _ = std.event.Loop.instance.?.sendto(fd, queries[i], os.MSG_NOSIGNAL, &ns[j].any, sl) catch undefined; | ||
| 1488 | } else { | ||
| 1489 | _ = os.sendto(fd, queries[i], os.MSG_NOSIGNAL, &ns[j].any, sl) catch undefined; | ||
| 1490 | } | ||
| 1474 | }, | 1491 | }, |
| 1475 | else => continue, | 1492 | else => continue, |
| 1476 | } | 1493 | } |
| ... | @@ -1661,18 +1678,23 @@ pub const StreamServer = struct { | ... | @@ -1661,18 +1678,23 @@ pub const StreamServer = struct { |
| 1661 | 1678 | ||
| 1662 | /// If this function succeeds, the returned `Connection` is a caller-managed resource. | 1679 | /// If this function succeeds, the returned `Connection` is a caller-managed resource. |
| 1663 | pub fn accept(self: *StreamServer) AcceptError!Connection { | 1680 | pub fn accept(self: *StreamServer) AcceptError!Connection { |
| 1664 | const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0; | ||
| 1665 | const accept_flags = nonblock | os.SOCK_CLOEXEC; | ||
| 1666 | var accepted_addr: Address = undefined; | 1681 | var accepted_addr: Address = undefined; |
| 1667 | var adr_len: os.socklen_t = @sizeOf(Address); | 1682 | var adr_len: os.socklen_t = @sizeOf(Address); |
| 1668 | if (os.accept(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| { | 1683 | const accept_result = blk: { |
| 1684 | if (std.io.is_async) { | ||
| 1685 | const loop = std.event.Loop.instance orelse return error.UnexpectedError; | ||
| 1686 | break :blk loop.accept(self.sockfd.?, &accepted_addr.any, &adr_len, os.SOCK_CLOEXEC); | ||
| 1687 | } else { | ||
| 1688 | break :blk os.accept(self.sockfd.?, &accepted_addr.any, &adr_len, os.SOCK_CLOEXEC); | ||
| 1689 | } | ||
| 1690 | }; | ||
| 1691 | |||
| 1692 | if (accept_result) |fd| { | ||
| 1669 | return Connection{ | 1693 | return Connection{ |
| 1670 | .file = fs.File{ .handle = fd }, | 1694 | .file = fs.File{ .handle = fd }, |
| 1671 | .address = accepted_addr, | 1695 | .address = accepted_addr, |
| 1672 | }; | 1696 | }; |
| 1673 | } else |err| switch (err) { | 1697 | } else |err| switch (err) { |
| 1674 | // We only give SOCK_NONBLOCK when I/O mode is async, in which case this error | ||
| 1675 | // is handled by os.accept4. | ||
| 1676 | error.WouldBlock => unreachable, | 1698 | error.WouldBlock => unreachable, |
| 1677 | else => |e| return e, | 1699 | else => |e| return e, |
| 1678 | } | 1700 | } |
lib/std/os.zig+34-90| ... | @@ -314,8 +314,8 @@ pub const ReadError = error{ | ... | @@ -314,8 +314,8 @@ pub const ReadError = error{ |
| 314 | 314 | ||
| 315 | /// Returns the number of bytes that were read, which can be less than | 315 | /// Returns the number of bytes that were read, which can be less than |
| 316 | /// buf.len. If 0 bytes were read, that means EOF. | 316 | /// buf.len. If 0 bytes were read, that means EOF. |
| 317 | /// If the application has a global event loop enabled, EAGAIN is handled | 317 | /// If `fd` is opened in non blocking mode, the function will return error.WouldBlock |
| 318 | /// via the event loop. Otherwise EAGAIN results in error.WouldBlock. | 318 | /// when EAGAIN is received. |
| 319 | /// | 319 | /// |
| 320 | /// Linux has a limit on how many bytes may be transferred in one `read` call, which is `0x7ffff000` | 320 | /// Linux has a limit on how many bytes may be transferred in one `read` call, which is `0x7ffff000` |
| 321 | /// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as | 321 | /// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as |
| ... | @@ -366,12 +366,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { | ... | @@ -366,12 +366,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { |
| 366 | EINTR => continue, | 366 | EINTR => continue, |
| 367 | EINVAL => unreachable, | 367 | EINVAL => unreachable, |
| 368 | EFAULT => unreachable, | 368 | EFAULT => unreachable, |
| 369 | EAGAIN => if (std.event.Loop.instance) |loop| { | 369 | EAGAIN => return error.WouldBlock, |
| 370 | loop.waitUntilFdReadable(fd); | ||
| 371 | continue; | ||
| 372 | } else { | ||
| 373 | return error.WouldBlock; | ||
| 374 | }, | ||
| 375 | EBADF => return error.NotOpenForReading, // Can be a race condition. | 370 | EBADF => return error.NotOpenForReading, // Can be a race condition. |
| 376 | EIO => return error.InputOutput, | 371 | EIO => return error.InputOutput, |
| 377 | EISDIR => return error.IsDir, | 372 | EISDIR => return error.IsDir, |
| ... | @@ -387,8 +382,8 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { | ... | @@ -387,8 +382,8 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { |
| 387 | 382 | ||
| 388 | /// Number of bytes read is returned. Upon reading end-of-file, zero is returned. | 383 | /// Number of bytes read is returned. Upon reading end-of-file, zero is returned. |
| 389 | /// | 384 | /// |
| 390 | /// For POSIX systems, if the application has a global event loop enabled, EAGAIN is handled | 385 | /// For POSIX systems, if `fd` is opened in non blocking mode, the function will |
| 391 | /// via the event loop. Otherwise EAGAIN results in `error.WouldBlock`. | 386 | /// return error.WouldBlock when EAGAIN is received. |
| 392 | /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are | 387 | /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are |
| 393 | /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. | 388 | /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. |
| 394 | /// | 389 | /// |
| ... | @@ -428,12 +423,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize { | ... | @@ -428,12 +423,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize { |
| 428 | EINTR => continue, | 423 | EINTR => continue, |
| 429 | EINVAL => unreachable, | 424 | EINVAL => unreachable, |
| 430 | EFAULT => unreachable, | 425 | EFAULT => unreachable, |
| 431 | EAGAIN => if (std.event.Loop.instance) |loop| { | 426 | EAGAIN => return error.WouldBlock, |
| 432 | loop.waitUntilFdReadable(fd); | ||
| 433 | continue; | ||
| 434 | } else { | ||
| 435 | return error.WouldBlock; | ||
| 436 | }, | ||
| 437 | EBADF => return error.NotOpenForReading, // can be a race condition | 427 | EBADF => return error.NotOpenForReading, // can be a race condition |
| 438 | EIO => return error.InputOutput, | 428 | EIO => return error.InputOutput, |
| 439 | EISDIR => return error.IsDir, | 429 | EISDIR => return error.IsDir, |
| ... | @@ -450,8 +440,8 @@ pub const PReadError = ReadError || error{Unseekable}; | ... | @@ -450,8 +440,8 @@ pub const PReadError = ReadError || error{Unseekable}; |
| 450 | /// | 440 | /// |
| 451 | /// Retries when interrupted by a signal. | 441 | /// Retries when interrupted by a signal. |
| 452 | /// | 442 | /// |
| 453 | /// For POSIX systems, if the application has a global event loop enabled, EAGAIN is handled | 443 | /// For POSIX systems, if `fd` is opened in non blocking mode, the function will |
| 454 | /// via the event loop. Otherwise EAGAIN results in `error.WouldBlock`. | 444 | /// return error.WouldBlock when EAGAIN is received. |
| 455 | /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are | 445 | /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are |
| 456 | /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. | 446 | /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. |
| 457 | pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { | 447 | pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { |
| ... | @@ -492,12 +482,7 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { | ... | @@ -492,12 +482,7 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { |
| 492 | EINTR => continue, | 482 | EINTR => continue, |
| 493 | EINVAL => unreachable, | 483 | EINVAL => unreachable, |
| 494 | EFAULT => unreachable, | 484 | EFAULT => unreachable, |
| 495 | EAGAIN => if (std.event.Loop.instance) |loop| { | 485 | EAGAIN => return error.WouldBlock, |
| 496 | loop.waitUntilFdReadable(fd); | ||
| 497 | continue; | ||
| 498 | } else { | ||
| 499 | return error.WouldBlock; | ||
| 500 | }, | ||
| 501 | EBADF => return error.NotOpenForReading, // Can be a race condition. | 486 | EBADF => return error.NotOpenForReading, // Can be a race condition. |
| 502 | EIO => return error.InputOutput, | 487 | EIO => return error.InputOutput, |
| 503 | EISDIR => return error.IsDir, | 488 | EISDIR => return error.IsDir, |
| ... | @@ -586,8 +571,8 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void { | ... | @@ -586,8 +571,8 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void { |
| 586 | /// | 571 | /// |
| 587 | /// Retries when interrupted by a signal. | 572 | /// Retries when interrupted by a signal. |
| 588 | /// | 573 | /// |
| 589 | /// For POSIX systems, if the application has a global event loop enabled, EAGAIN is handled | 574 | /// For POSIX systems, if `fd` is opened in non blocking mode, the function will |
| 590 | /// via the event loop. Otherwise EAGAIN results in `error.WouldBlock`. | 575 | /// return error.WouldBlock when EAGAIN is received. |
| 591 | /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are | 576 | /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are |
| 592 | /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. | 577 | /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. |
| 593 | /// | 578 | /// |
| ... | @@ -637,12 +622,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize { | ... | @@ -637,12 +622,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize { |
| 637 | EINTR => continue, | 622 | EINTR => continue, |
| 638 | EINVAL => unreachable, | 623 | EINVAL => unreachable, |
| 639 | EFAULT => unreachable, | 624 | EFAULT => unreachable, |
| 640 | EAGAIN => if (std.event.Loop.instance) |loop| { | 625 | EAGAIN => return error.WouldBlock, |
| 641 | loop.waitUntilFdReadable(fd); | ||
| 642 | continue; | ||
| 643 | } else { | ||
| 644 | return error.WouldBlock; | ||
| 645 | }, | ||
| 646 | EBADF => return error.NotOpenForReading, // can be a race condition | 626 | EBADF => return error.NotOpenForReading, // can be a race condition |
| 647 | EIO => return error.InputOutput, | 627 | EIO => return error.InputOutput, |
| 648 | EISDIR => return error.IsDir, | 628 | EISDIR => return error.IsDir, |
| ... | @@ -687,8 +667,8 @@ pub const WriteError = error{ | ... | @@ -687,8 +667,8 @@ pub const WriteError = error{ |
| 687 | /// another write() call to transfer the remaining bytes. The subsequent call will either | 667 | /// another write() call to transfer the remaining bytes. The subsequent call will either |
| 688 | /// transfer further bytes or may result in an error (e.g., if the disk is now full). | 668 | /// transfer further bytes or may result in an error (e.g., if the disk is now full). |
| 689 | /// | 669 | /// |
| 690 | /// For POSIX systems, if the application has a global event loop enabled, EAGAIN is handled | 670 | /// For POSIX systems, if `fd` is opened in non blocking mode, the function will |
| 691 | /// via the event loop. Otherwise EAGAIN results in `error.WouldBlock`. | 671 | /// return error.WouldBlock when EAGAIN is received. |
| 692 | /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are | 672 | /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are |
| 693 | /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. | 673 | /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. |
| 694 | /// | 674 | /// |
| ... | @@ -741,12 +721,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { | ... | @@ -741,12 +721,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { |
| 741 | EINTR => continue, | 721 | EINTR => continue, |
| 742 | EINVAL => unreachable, | 722 | EINVAL => unreachable, |
| 743 | EFAULT => unreachable, | 723 | EFAULT => unreachable, |
| 744 | EAGAIN => if (std.event.Loop.instance) |loop| { | 724 | EAGAIN => return error.WouldBlock, |
| 745 | loop.waitUntilFdWritable(fd); | ||
| 746 | continue; | ||
| 747 | } else { | ||
| 748 | return error.WouldBlock; | ||
| 749 | }, | ||
| 750 | EBADF => return error.NotOpenForWriting, // can be a race condition. | 725 | EBADF => return error.NotOpenForWriting, // can be a race condition. |
| 751 | EDESTADDRREQ => unreachable, // `connect` was never called. | 726 | EDESTADDRREQ => unreachable, // `connect` was never called. |
| 752 | EDQUOT => return error.DiskQuota, | 727 | EDQUOT => return error.DiskQuota, |
| ... | @@ -772,8 +747,8 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { | ... | @@ -772,8 +747,8 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { |
| 772 | /// another write() call to transfer the remaining bytes. The subsequent call will either | 747 | /// another write() call to transfer the remaining bytes. The subsequent call will either |
| 773 | /// transfer further bytes or may result in an error (e.g., if the disk is now full). | 748 | /// transfer further bytes or may result in an error (e.g., if the disk is now full). |
| 774 | /// | 749 | /// |
| 775 | /// For POSIX systems, if the application has a global event loop enabled, EAGAIN is handled | 750 | /// For POSIX systems, if `fd` is opened in non blocking mode, the function will |
| 776 | /// via the event loop. Otherwise EAGAIN results in `error.WouldBlock`. | 751 | /// return error.WouldBlock when EAGAIN is received.k`. |
| 777 | /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are | 752 | /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are |
| 778 | /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. | 753 | /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. |
| 779 | /// | 754 | /// |
| ... | @@ -814,12 +789,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { | ... | @@ -814,12 +789,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { |
| 814 | EINTR => continue, | 789 | EINTR => continue, |
| 815 | EINVAL => unreachable, | 790 | EINVAL => unreachable, |
| 816 | EFAULT => unreachable, | 791 | EFAULT => unreachable, |
| 817 | EAGAIN => if (std.event.Loop.instance) |loop| { | 792 | EAGAIN => return error.WouldBlock, |
| 818 | loop.waitUntilFdWritable(fd); | ||
| 819 | continue; | ||
| 820 | } else { | ||
| 821 | return error.WouldBlock; | ||
| 822 | }, | ||
| 823 | EBADF => return error.NotOpenForWriting, // Can be a race condition. | 793 | EBADF => return error.NotOpenForWriting, // Can be a race condition. |
| 824 | EDESTADDRREQ => unreachable, // `connect` was never called. | 794 | EDESTADDRREQ => unreachable, // `connect` was never called. |
| 825 | EDQUOT => return error.DiskQuota, | 795 | EDQUOT => return error.DiskQuota, |
| ... | @@ -847,8 +817,8 @@ pub const PWriteError = WriteError || error{Unseekable}; | ... | @@ -847,8 +817,8 @@ pub const PWriteError = WriteError || error{Unseekable}; |
| 847 | /// another write() call to transfer the remaining bytes. The subsequent call will either | 817 | /// another write() call to transfer the remaining bytes. The subsequent call will either |
| 848 | /// transfer further bytes or may result in an error (e.g., if the disk is now full). | 818 | /// transfer further bytes or may result in an error (e.g., if the disk is now full). |
| 849 | /// | 819 | /// |
| 850 | /// For POSIX systems, if the application has a global event loop enabled, EAGAIN is handled | 820 | /// For POSIX systems, if `fd` is opened in non blocking mode, the function will |
| 851 | /// via the event loop. Otherwise EAGAIN results in `error.WouldBlock`. | 821 | /// return error.WouldBlock when EAGAIN is received. |
| 852 | /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are | 822 | /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are |
| 853 | /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. | 823 | /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. |
| 854 | /// | 824 | /// |
| ... | @@ -905,12 +875,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { | ... | @@ -905,12 +875,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { |
| 905 | EINTR => continue, | 875 | EINTR => continue, |
| 906 | EINVAL => unreachable, | 876 | EINVAL => unreachable, |
| 907 | EFAULT => unreachable, | 877 | EFAULT => unreachable, |
| 908 | EAGAIN => if (std.event.Loop.instance) |loop| { | 878 | EAGAIN => return error.WouldBlock, |
| 909 | loop.waitUntilFdWritable(fd); | ||
| 910 | continue; | ||
| 911 | } else { | ||
| 912 | return error.WouldBlock; | ||
| 913 | }, | ||
| 914 | EBADF => return error.NotOpenForWriting, // Can be a race condition. | 879 | EBADF => return error.NotOpenForWriting, // Can be a race condition. |
| 915 | EDESTADDRREQ => unreachable, // `connect` was never called. | 880 | EDESTADDRREQ => unreachable, // `connect` was never called. |
| 916 | EDQUOT => return error.DiskQuota, | 881 | EDQUOT => return error.DiskQuota, |
| ... | @@ -939,8 +904,8 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { | ... | @@ -939,8 +904,8 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { |
| 939 | /// another write() call to transfer the remaining bytes. The subsequent call will either | 904 | /// another write() call to transfer the remaining bytes. The subsequent call will either |
| 940 | /// transfer further bytes or may result in an error (e.g., if the disk is now full). | 905 | /// transfer further bytes or may result in an error (e.g., if the disk is now full). |
| 941 | /// | 906 | /// |
| 942 | /// If the application has a global event loop enabled, EAGAIN is handled | 907 | /// If `fd` is opened in non blocking mode, the function will |
| 943 | /// via the event loop. Otherwise EAGAIN results in `error.WouldBlock`. | 908 | /// return error.WouldBlock when EAGAIN is received. |
| 944 | /// | 909 | /// |
| 945 | /// The following systems do not have this syscall, and will return partial writes if more than one | 910 | /// The following systems do not have this syscall, and will return partial writes if more than one |
| 946 | /// vector is provided: | 911 | /// vector is provided: |
| ... | @@ -993,12 +958,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz | ... | @@ -993,12 +958,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz |
| 993 | EINTR => continue, | 958 | EINTR => continue, |
| 994 | EINVAL => unreachable, | 959 | EINVAL => unreachable, |
| 995 | EFAULT => unreachable, | 960 | EFAULT => unreachable, |
| 996 | EAGAIN => if (std.event.Loop.instance) |loop| { | 961 | EAGAIN => return error.WouldBlock, |
| 997 | loop.waitUntilFdWritable(fd); | ||
| 998 | continue; | ||
| 999 | } else { | ||
| 1000 | return error.WouldBlock; | ||
| 1001 | }, | ||
| 1002 | EBADF => return error.NotOpenForWriting, // Can be a race condition. | 962 | EBADF => return error.NotOpenForWriting, // Can be a race condition. |
| 1003 | EDESTADDRREQ => unreachable, // `connect` was never called. | 963 | EDESTADDRREQ => unreachable, // `connect` was never called. |
| 1004 | EDQUOT => return error.DiskQuota, | 964 | EDQUOT => return error.DiskQuota, |
| ... | @@ -2846,8 +2806,8 @@ pub const AcceptError = error{ | ... | @@ -2846,8 +2806,8 @@ pub const AcceptError = error{ |
| 2846 | } || UnexpectedError; | 2806 | } || UnexpectedError; |
| 2847 | 2807 | ||
| 2848 | /// Accept a connection on a socket. | 2808 | /// Accept a connection on a socket. |
| 2849 | /// If the application has a global event loop enabled, EAGAIN is handled | 2809 | /// If `sockfd` is opened in non blocking mode, the function will |
| 2850 | /// via the event loop. Otherwise EAGAIN results in error.WouldBlock. | 2810 | /// return error.WouldBlock when EAGAIN is received. |
| 2851 | pub fn accept( | 2811 | pub fn accept( |
| 2852 | /// This argument is a socket that has been created with `socket`, bound to a local address | 2812 | /// This argument is a socket that has been created with `socket`, bound to a local address |
| 2853 | /// with `bind`, and is listening for connections after a `listen`. | 2813 | /// with `bind`, and is listening for connections after a `listen`. |
| ... | @@ -2890,12 +2850,7 @@ pub fn accept( | ... | @@ -2890,12 +2850,7 @@ pub fn accept( |
| 2890 | return fd; | 2850 | return fd; |
| 2891 | }, | 2851 | }, |
| 2892 | EINTR => continue, | 2852 | EINTR => continue, |
| 2893 | EAGAIN => if (std.event.Loop.instance) |loop| { | 2853 | EAGAIN => return error.WouldBlock, |
| 2894 | loop.waitUntilFdReadable(sockfd); | ||
| 2895 | continue; | ||
| 2896 | } else { | ||
| 2897 | return error.WouldBlock; | ||
| 2898 | }, | ||
| 2899 | EBADF => unreachable, // always a race condition | 2854 | EBADF => unreachable, // always a race condition |
| 2900 | ECONNABORTED => return error.ConnectionAborted, | 2855 | ECONNABORTED => return error.ConnectionAborted, |
| 2901 | EFAULT => unreachable, | 2856 | EFAULT => unreachable, |
| ... | @@ -3081,6 +3036,8 @@ pub const ConnectError = error{ | ... | @@ -3081,6 +3036,8 @@ pub const ConnectError = error{ |
| 3081 | } || UnexpectedError; | 3036 | } || UnexpectedError; |
| 3082 | 3037 | ||
| 3083 | /// Initiate a connection on a socket. | 3038 | /// Initiate a connection on a socket. |
| 3039 | /// If `sockfd` is opened in non blocking mode, the function will | ||
| 3040 | /// return error.WouldBlock when EAGAIN or EINPROGRESS is received. | ||
| 3084 | pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) ConnectError!void { | 3041 | pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) ConnectError!void { |
| 3085 | if (builtin.os.tag == .windows) { | 3042 | if (builtin.os.tag == .windows) { |
| 3086 | const rc = windows.ws2_32.connect(sockfd, sock_addr, len); | 3043 | const rc = windows.ws2_32.connect(sockfd, sock_addr, len); |
| ... | @@ -3113,11 +3070,7 @@ pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) Con | ... | @@ -3113,11 +3070,7 @@ pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) Con |
| 3113 | EADDRINUSE => return error.AddressInUse, | 3070 | EADDRINUSE => return error.AddressInUse, |
| 3114 | EADDRNOTAVAIL => return error.AddressNotAvailable, | 3071 | EADDRNOTAVAIL => return error.AddressNotAvailable, |
| 3115 | EAFNOSUPPORT => return error.AddressFamilyNotSupported, | 3072 | EAFNOSUPPORT => return error.AddressFamilyNotSupported, |
| 3116 | EAGAIN, EINPROGRESS => { | 3073 | EAGAIN, EINPROGRESS => return error.WouldBlock, |
| 3117 | const loop = std.event.Loop.instance orelse return error.WouldBlock; | ||
| 3118 | loop.waitUntilFdWritable(sockfd); | ||
| 3119 | return getsockoptError(sockfd); | ||
| 3120 | }, | ||
| 3121 | EALREADY => unreachable, // The socket is nonblocking and a previous connection attempt has not yet been completed. | 3074 | EALREADY => unreachable, // The socket is nonblocking and a previous connection attempt has not yet been completed. |
| 3122 | EBADF => unreachable, // sockfd is not a valid open file descriptor. | 3075 | EBADF => unreachable, // sockfd is not a valid open file descriptor. |
| 3123 | ECONNREFUSED => return error.ConnectionRefused, | 3076 | ECONNREFUSED => return error.ConnectionRefused, |
| ... | @@ -4620,14 +4573,8 @@ pub fn sendto( | ... | @@ -4620,14 +4573,8 @@ pub fn sendto( |
| 4620 | const rc = system.sendto(sockfd, buf.ptr, buf.len, flags, dest_addr, addrlen); | 4573 | const rc = system.sendto(sockfd, buf.ptr, buf.len, flags, dest_addr, addrlen); |
| 4621 | switch (errno(rc)) { | 4574 | switch (errno(rc)) { |
| 4622 | 0 => return @intCast(usize, rc), | 4575 | 0 => return @intCast(usize, rc), |
| 4623 | |||
| 4624 | EACCES => return error.AccessDenied, | 4576 | EACCES => return error.AccessDenied, |
| 4625 | EAGAIN => if (std.event.Loop.instance) |loop| { | 4577 | EAGAIN => return error.WouldBlock, |
| 4626 | loop.waitUntilFdWritable(sockfd); | ||
| 4627 | continue; | ||
| 4628 | } else { | ||
| 4629 | return error.WouldBlock; | ||
| 4630 | }, | ||
| 4631 | EALREADY => return error.FastOpenAlreadyInProgress, | 4578 | EALREADY => return error.FastOpenAlreadyInProgress, |
| 4632 | EBADF => unreachable, // always a race condition | 4579 | EBADF => unreachable, // always a race condition |
| 4633 | ECONNRESET => return error.ConnectionResetByPeer, | 4580 | ECONNRESET => return error.ConnectionResetByPeer, |
| ... | @@ -5106,6 +5053,8 @@ pub const RecvFromError = error{ | ... | @@ -5106,6 +5053,8 @@ pub const RecvFromError = error{ |
| 5106 | SystemResources, | 5053 | SystemResources, |
| 5107 | } || UnexpectedError; | 5054 | } || UnexpectedError; |
| 5108 | 5055 | ||
| 5056 | /// If `sockfd` is opened in non blocking mode, the function will | ||
| 5057 | /// return error.WouldBlock when EAGAIN is received. | ||
| 5109 | pub fn recvfrom( | 5058 | pub fn recvfrom( |
| 5110 | sockfd: fd_t, | 5059 | sockfd: fd_t, |
| 5111 | buf: []u8, | 5060 | buf: []u8, |
| ... | @@ -5123,12 +5072,7 @@ pub fn recvfrom( | ... | @@ -5123,12 +5072,7 @@ pub fn recvfrom( |
| 5123 | ENOTCONN => unreachable, | 5072 | ENOTCONN => unreachable, |
| 5124 | ENOTSOCK => unreachable, | 5073 | ENOTSOCK => unreachable, |
| 5125 | EINTR => continue, | 5074 | EINTR => continue, |
| 5126 | EAGAIN => if (std.event.Loop.instance) |loop| { | 5075 | EAGAIN => return error.WouldBlock, |
| 5127 | loop.waitUntilFdReadable(sockfd); | ||
| 5128 | continue; | ||
| 5129 | } else { | ||
| 5130 | return error.WouldBlock; | ||
| 5131 | }, | ||
| 5132 | ENOMEM => return error.SystemResources, | 5076 | ENOMEM => return error.SystemResources, |
| 5133 | ECONNREFUSED => return error.ConnectionRefused, | 5077 | ECONNREFUSED => return error.ConnectionRefused, |
| 5134 | else => |err| return unexpectedErrno(err), | 5078 | else => |err| return unexpectedErrno(err), |
lib/std/os/uefi/tables/system_table.zig+1-1| ... | @@ -35,7 +35,7 @@ pub const SystemTable = extern struct { | ... | @@ -35,7 +35,7 @@ pub const SystemTable = extern struct { |
| 35 | runtime_services: *RuntimeServices, | 35 | runtime_services: *RuntimeServices, |
| 36 | boot_services: ?*BootServices, | 36 | boot_services: ?*BootServices, |
| 37 | number_of_table_entries: usize, | 37 | number_of_table_entries: usize, |
| 38 | configuration_table: *ConfigurationTable, | 38 | configuration_table: [*]ConfigurationTable, |
| 39 | 39 | ||
| 40 | pub const signature: u64 = 0x5453595320494249; | 40 | pub const signature: u64 = 0x5453595320494249; |
| 41 | pub const revision_1_02: u32 = (1 << 16) | 2; | 41 | pub const revision_1_02: u32 = (1 << 16) | 2; |
lib/std/os/windows.zig+17-1| ... | @@ -765,6 +765,7 @@ pub const DeleteFileError = error{ | ... | @@ -765,6 +765,7 @@ pub const DeleteFileError = error{ |
| 765 | Unexpected, | 765 | Unexpected, |
| 766 | NotDir, | 766 | NotDir, |
| 767 | IsDir, | 767 | IsDir, |
| 768 | DirNotEmpty, | ||
| 768 | }; | 769 | }; |
| 769 | 770 | ||
| 770 | pub const DeleteFileOptions = struct { | 771 | pub const DeleteFileOptions = struct { |
| ... | @@ -819,7 +820,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil | ... | @@ -819,7 +820,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil |
| 819 | 0, | 820 | 0, |
| 820 | ); | 821 | ); |
| 821 | switch (rc) { | 822 | switch (rc) { |
| 822 | .SUCCESS => return CloseHandle(tmp_handle), | 823 | .SUCCESS => CloseHandle(tmp_handle), |
| 823 | .OBJECT_NAME_INVALID => unreachable, | 824 | .OBJECT_NAME_INVALID => unreachable, |
| 824 | .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, | 825 | .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, |
| 825 | .INVALID_PARAMETER => unreachable, | 826 | .INVALID_PARAMETER => unreachable, |
| ... | @@ -828,6 +829,21 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil | ... | @@ -828,6 +829,21 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil |
| 828 | .SHARING_VIOLATION => return error.FileBusy, | 829 | .SHARING_VIOLATION => return error.FileBusy, |
| 829 | else => return unexpectedStatus(rc), | 830 | else => return unexpectedStatus(rc), |
| 830 | } | 831 | } |
| 832 | |||
| 833 | // If a directory fails to be deleted, CloseHandle will still report success | ||
| 834 | // Check if the directory still exists and return error.DirNotEmpty if true | ||
| 835 | if (options.remove_dir) { | ||
| 836 | var basic_info: FILE_BASIC_INFORMATION = undefined; | ||
| 837 | switch (ntdll.NtQueryAttributesFile(&attr, &basic_info)) { | ||
| 838 | .SUCCESS => return error.DirNotEmpty, | ||
| 839 | .OBJECT_NAME_NOT_FOUND => return, | ||
| 840 | .OBJECT_PATH_NOT_FOUND => return, | ||
| 841 | .INVALID_PARAMETER => unreachable, | ||
| 842 | .ACCESS_DENIED => return error.AccessDenied, | ||
| 843 | .OBJECT_PATH_SYNTAX_BAD => unreachable, | ||
| 844 | else => |urc| return unexpectedStatus(urc), | ||
| 845 | } | ||
| 846 | } | ||
| 831 | } | 847 | } |
| 832 | 848 | ||
| 833 | pub const MoveFileError = error{ FileNotFound, Unexpected }; | 849 | pub const MoveFileError = error{ FileNotFound, Unexpected }; |
lib/std/zig/ast.zig+9| ... | @@ -823,6 +823,15 @@ pub const Node = struct { | ... | @@ -823,6 +823,15 @@ pub const Node = struct { |
| 823 | } | 823 | } |
| 824 | } | 824 | } |
| 825 | 825 | ||
| 826 | pub fn findFirstWithId(self: *Node, id: Id) ?*Node { | ||
| 827 | if (self.id == id) return self; | ||
| 828 | var child_i: usize = 0; | ||
| 829 | while (self.iterate(child_i)) |child| : (child_i += 1) { | ||
| 830 | if (child.findFirstWithId(id)) |result| return result; | ||
| 831 | } | ||
| 832 | return null; | ||
| 833 | } | ||
| 834 | |||
| 826 | pub fn dump(self: *Node, indent: usize) void { | 835 | pub fn dump(self: *Node, indent: usize) void { |
| 827 | { | 836 | { |
| 828 | var i: usize = 0; | 837 | var i: usize = 0; |
lib/std/zig/parser_test.zig+325-3| ... | @@ -1301,8 +1301,10 @@ test "zig fmt: array literal with hint" { | ... | @@ -1301,8 +1301,10 @@ test "zig fmt: array literal with hint" { |
| 1301 | \\const a = []u8{ | 1301 | \\const a = []u8{ |
| 1302 | \\ 1, 2, | 1302 | \\ 1, 2, |
| 1303 | \\ 3, 4, | 1303 | \\ 3, 4, |
| 1304 | \\ 5, 6, // blah | 1304 | \\ 5, |
| 1305 | \\ 7, 8, | 1305 | \\ 6, // blah |
| 1306 | \\ 7, | ||
| 1307 | \\ 8, | ||
| 1306 | \\}; | 1308 | \\}; |
| 1307 | \\const a = []u8{ | 1309 | \\const a = []u8{ |
| 1308 | \\ 1, 2, | 1310 | \\ 1, 2, |
| ... | @@ -1372,7 +1374,7 @@ test "zig fmt: multiline string parameter in fn call with trailing comma" { | ... | @@ -1372,7 +1374,7 @@ test "zig fmt: multiline string parameter in fn call with trailing comma" { |
| 1372 | \\ \\ZIG_C_HEADER_FILES {} | 1374 | \\ \\ZIG_C_HEADER_FILES {} |
| 1373 | \\ \\ZIG_DIA_GUIDS_LIB {} | 1375 | \\ \\ZIG_DIA_GUIDS_LIB {} |
| 1374 | \\ \\ | 1376 | \\ \\ |
| 1375 | \\ , | 1377 | \\ , |
| 1376 | \\ std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR), | 1378 | \\ std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR), |
| 1377 | \\ std.cstr.toSliceConst(c.ZIG_CXX_COMPILER), | 1379 | \\ std.cstr.toSliceConst(c.ZIG_CXX_COMPILER), |
| 1378 | \\ std.cstr.toSliceConst(c.ZIG_DIA_GUIDS_LIB), | 1380 | \\ std.cstr.toSliceConst(c.ZIG_DIA_GUIDS_LIB), |
| ... | @@ -3321,6 +3323,326 @@ test "zig fmt: Don't add extra newline after if" { | ... | @@ -3321,6 +3323,326 @@ test "zig fmt: Don't add extra newline after if" { |
| 3321 | ); | 3323 | ); |
| 3322 | } | 3324 | } |
| 3323 | 3325 | ||
| 3326 | test "zig fmt: comments in ternary ifs" { | ||
| 3327 | try testCanonical( | ||
| 3328 | \\const x = if (true) { | ||
| 3329 | \\ 1; | ||
| 3330 | \\} else if (false) | ||
| 3331 | \\ // Comment | ||
| 3332 | \\ 0; | ||
| 3333 | \\const y = if (true) | ||
| 3334 | \\ // Comment | ||
| 3335 | \\ 1 | ||
| 3336 | \\else | ||
| 3337 | \\ 0; | ||
| 3338 | \\ | ||
| 3339 | \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int; | ||
| 3340 | \\ | ||
| 3341 | ); | ||
| 3342 | } | ||
| 3343 | |||
| 3344 | test "zig fmt: test comments in field access chain" { | ||
| 3345 | try testCanonical( | ||
| 3346 | \\pub const str = struct { | ||
| 3347 | \\ pub const Thing = more.more // | ||
| 3348 | \\ .more() // | ||
| 3349 | \\ .more().more() // | ||
| 3350 | \\ .more() // | ||
| 3351 | \\ // .more() // | ||
| 3352 | \\ .more() // | ||
| 3353 | \\ .more(); | ||
| 3354 | \\ data: Data, | ||
| 3355 | \\}; | ||
| 3356 | \\ | ||
| 3357 | \\pub const str = struct { | ||
| 3358 | \\ pub const Thing = more.more // | ||
| 3359 | \\ .more() // | ||
| 3360 | \\ // .more() // | ||
| 3361 | \\ // .more() // | ||
| 3362 | \\ // .more() // | ||
| 3363 | \\ .more() // | ||
| 3364 | \\ .more(); | ||
| 3365 | \\ data: Data, | ||
| 3366 | \\}; | ||
| 3367 | \\ | ||
| 3368 | \\pub const str = struct { | ||
| 3369 | \\ pub const Thing = more // | ||
| 3370 | \\ .more // | ||
| 3371 | \\ .more() // | ||
| 3372 | \\ .more(); | ||
| 3373 | \\ data: Data, | ||
| 3374 | \\}; | ||
| 3375 | \\ | ||
| 3376 | ); | ||
| 3377 | } | ||
| 3378 | |||
| 3379 | test "zig fmt: Indent comma correctly after multiline string literals in arg list (trailing comma)" { | ||
| 3380 | try testCanonical( | ||
| 3381 | \\fn foo() void { | ||
| 3382 | \\ z.display_message_dialog( | ||
| 3383 | \\ *const [323:0]u8, | ||
| 3384 | \\ \\Message Text | ||
| 3385 | \\ \\------------ | ||
| 3386 | \\ \\xxxxxxxxxxxx | ||
| 3387 | \\ \\xxxxxxxxxxxx | ||
| 3388 | \\ , | ||
| 3389 | \\ g.GtkMessageType.GTK_MESSAGE_WARNING, | ||
| 3390 | \\ null, | ||
| 3391 | \\ ); | ||
| 3392 | \\ | ||
| 3393 | \\ z.display_message_dialog(*const [323:0]u8, | ||
| 3394 | \\ \\Message Text | ||
| 3395 | \\ \\------------ | ||
| 3396 | \\ \\xxxxxxxxxxxx | ||
| 3397 | \\ \\xxxxxxxxxxxx | ||
| 3398 | \\ , g.GtkMessageType.GTK_MESSAGE_WARNING, null); | ||
| 3399 | \\} | ||
| 3400 | \\ | ||
| 3401 | ); | ||
| 3402 | } | ||
| 3403 | |||
| 3404 | test "zig fmt: Control flow statement as body of blockless if" { | ||
| 3405 | try testCanonical( | ||
| 3406 | \\pub fn main() void { | ||
| 3407 | \\ const zoom_node = if (focused_node == layout_first) | ||
| 3408 | \\ if (it.next()) { | ||
| 3409 | \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node; | ||
| 3410 | \\ } else null | ||
| 3411 | \\ else | ||
| 3412 | \\ focused_node; | ||
| 3413 | \\ | ||
| 3414 | \\ const zoom_node = if (focused_node == layout_first) while (it.next()) |node| { | ||
| 3415 | \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node; | ||
| 3416 | \\ } else null else | ||
| 3417 | \\ focused_node; | ||
| 3418 | \\ | ||
| 3419 | \\ const zoom_node = if (focused_node == layout_first) | ||
| 3420 | \\ if (it.next()) { | ||
| 3421 | \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node; | ||
| 3422 | \\ } else null; | ||
| 3423 | \\ | ||
| 3424 | \\ const zoom_node = if (focused_node == layout_first) while (it.next()) |node| { | ||
| 3425 | \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node; | ||
| 3426 | \\ }; | ||
| 3427 | \\ | ||
| 3428 | \\ const zoom_node = if (focused_node == layout_first) for (nodes) |node| { | ||
| 3429 | \\ break node; | ||
| 3430 | \\ }; | ||
| 3431 | \\ | ||
| 3432 | \\ const zoom_node = if (focused_node == layout_first) switch (nodes) { | ||
| 3433 | \\ 0 => 0, | ||
| 3434 | \\ } else | ||
| 3435 | \\ focused_node; | ||
| 3436 | \\} | ||
| 3437 | \\ | ||
| 3438 | ); | ||
| 3439 | } | ||
| 3440 | |||
| 3441 | test "zig fmt: " { | ||
| 3442 | try testCanonical( | ||
| 3443 | \\pub fn sendViewTags(self: Self) void { | ||
| 3444 | \\ var it = ViewStack(View).iterator(self.output.views.first, std.math.maxInt(u32)); | ||
| 3445 | \\ while (it.next()) |node| | ||
| 3446 | \\ view_tags.append(node.view.current_tags) catch { | ||
| 3447 | \\ c.wl_resource_post_no_memory(self.wl_resource); | ||
| 3448 | \\ log.crit(.river_status, "out of memory", .{}); | ||
| 3449 | \\ return; | ||
| 3450 | \\ }; | ||
| 3451 | \\} | ||
| 3452 | \\ | ||
| 3453 | ); | ||
| 3454 | } | ||
| 3455 | |||
| 3456 | test "zig fmt: allow trailing line comments to do manual array formatting" { | ||
| 3457 | try testCanonical( | ||
| 3458 | \\fn foo() void { | ||
| 3459 | \\ self.code.appendSliceAssumeCapacity(&[_]u8{ | ||
| 3460 | \\ 0x55, // push rbp | ||
| 3461 | \\ 0x48, 0x89, 0xe5, // mov rbp, rsp | ||
| 3462 | \\ 0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc) | ||
| 3463 | \\ }); | ||
| 3464 | \\ | ||
| 3465 | \\ di_buf.appendAssumeCapacity(&[_]u8{ | ||
| 3466 | \\ 1, DW.TAG_compile_unit, DW.CHILDREN_no, // header | ||
| 3467 | \\ DW.AT_stmt_list, DW_FORM_data4, // form value pairs | ||
| 3468 | \\ DW.AT_low_pc, DW_FORM_addr, | ||
| 3469 | \\ DW.AT_high_pc, DW_FORM_addr, | ||
| 3470 | \\ DW.AT_name, DW_FORM_strp, | ||
| 3471 | \\ DW.AT_comp_dir, DW_FORM_strp, | ||
| 3472 | \\ DW.AT_producer, DW_FORM_strp, | ||
| 3473 | \\ DW.AT_language, DW_FORM_data2, | ||
| 3474 | \\ 0, 0, // sentinel | ||
| 3475 | \\ }); | ||
| 3476 | \\ | ||
| 3477 | \\ self.code.appendSliceAssumeCapacity(&[_]u8{ | ||
| 3478 | \\ 0x55, // push rbp | ||
| 3479 | \\ 0x48, 0x89, 0xe5, // mov rbp, rsp | ||
| 3480 | \\ // How do we handle this? | ||
| 3481 | \\ //0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc) | ||
| 3482 | \\ // Here's a blank line, should that be allowed? | ||
| 3483 | \\ | ||
| 3484 | \\ 0x48, 0x89, 0xe5, | ||
| 3485 | \\ 0x33, 0x45, | ||
| 3486 | \\ // Now the comment breaks a single line -- how do we handle this? | ||
| 3487 | \\ 0x88, | ||
| 3488 | \\ }); | ||
| 3489 | \\} | ||
| 3490 | \\ | ||
| 3491 | ); | ||
| 3492 | } | ||
| 3493 | |||
| 3494 | test "zig fmt: multiline string literals should play nice with array initializers" { | ||
| 3495 | try testCanonical( | ||
| 3496 | \\fn main() void { | ||
| 3497 | \\ var a = .{.{.{.{.{.{.{.{ | ||
| 3498 | \\ 0, | ||
| 3499 | \\ }}}}}}}}; | ||
| 3500 | \\ myFunc(.{ | ||
| 3501 | \\ "aaaaaaa", "bbbbbb", "ccccc", | ||
| 3502 | \\ "dddd", ("eee"), ("fff"), | ||
| 3503 | \\ ("gggg"), | ||
| 3504 | \\ // Line comment | ||
| 3505 | \\ \\Multiline String Literals can be quite long | ||
| 3506 | \\ , | ||
| 3507 | \\ \\Multiline String Literals can be quite long | ||
| 3508 | \\ \\Multiline String Literals can be quite long | ||
| 3509 | \\ , | ||
| 3510 | \\ \\Multiline String Literals can be quite long | ||
| 3511 | \\ \\Multiline String Literals can be quite long | ||
| 3512 | \\ \\Multiline String Literals can be quite long | ||
| 3513 | \\ \\Multiline String Literals can be quite long | ||
| 3514 | \\ , | ||
| 3515 | \\ ( | ||
| 3516 | \\ \\Multiline String Literals can be quite long | ||
| 3517 | \\ ), | ||
| 3518 | \\ .{ | ||
| 3519 | \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | ||
| 3520 | \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | ||
| 3521 | \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | ||
| 3522 | \\ }, | ||
| 3523 | \\ .{( | ||
| 3524 | \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | ||
| 3525 | \\ )}, | ||
| 3526 | \\ .{ | ||
| 3527 | \\ "xxxxxxx", "xxx", | ||
| 3528 | \\ ( | ||
| 3529 | \\ \\ xxx | ||
| 3530 | \\ ), | ||
| 3531 | \\ "xxx", "xxx", | ||
| 3532 | \\ }, | ||
| 3533 | \\ .{ "xxxxxxx", "xxx", "xxx", "xxx" }, .{ "xxxxxxx", "xxx", "xxx", "xxx" }, | ||
| 3534 | \\ "aaaaaaa", "bbbbbb", "ccccc", // - | ||
| 3535 | \\ "dddd", ("eee"), ("fff"), | ||
| 3536 | \\ .{ | ||
| 3537 | \\ "xxx", "xxx", | ||
| 3538 | \\ ( | ||
| 3539 | \\ \\ xxx | ||
| 3540 | \\ ), | ||
| 3541 | \\ "xxxxxxxxxxxxxx", "xxx", | ||
| 3542 | \\ }, | ||
| 3543 | \\ .{ | ||
| 3544 | \\ ( | ||
| 3545 | \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | ||
| 3546 | \\ ), | ||
| 3547 | \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | ||
| 3548 | \\ }, | ||
| 3549 | \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | ||
| 3550 | \\ \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | ||
| 3551 | \\ }); | ||
| 3552 | \\} | ||
| 3553 | \\ | ||
| 3554 | ); | ||
| 3555 | } | ||
| 3556 | |||
| 3557 | test "zig fmt: use of comments and Multiline string literals may force the parameters over multiple lines" { | ||
| 3558 | try testCanonical( | ||
| 3559 | \\pub fn makeMemUndefined(qzz: []u8) i1 { | ||
| 3560 | \\ cases.add( // fixed bug #2032 | ||
| 3561 | \\ "compile diagnostic string for top level decl type", | ||
| 3562 | \\ \\export fn entry() void { | ||
| 3563 | \\ \\ var foo: u32 = @This(){}; | ||
| 3564 | \\ \\} | ||
| 3565 | \\ , &[_][]const u8{ | ||
| 3566 | \\ "tmp.zig:2:27: error: type 'u32' does not support array initialization", | ||
| 3567 | \\ }); | ||
| 3568 | \\ @compileError( | ||
| 3569 | \\ \\ unknown-length pointers and C pointers cannot be hashed deeply. | ||
| 3570 | \\ \\ Consider providing your own hash function. | ||
| 3571 | \\ \\ unknown-length pointers and C pointers cannot be hashed deeply. | ||
| 3572 | \\ \\ Consider providing your own hash function. | ||
| 3573 | \\ ); | ||
| 3574 | \\ return @intCast(i1, doMemCheckClientRequestExpr(0, // default return | ||
| 3575 | \\ .MakeMemUndefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0)); | ||
| 3576 | \\} | ||
| 3577 | \\ | ||
| 3578 | \\// This looks like garbage don't do this | ||
| 3579 | \\const rparen = tree.prevToken( | ||
| 3580 | \\// the first token for the annotation expressions is the left | ||
| 3581 | \\// parenthesis, hence the need for two prevToken | ||
| 3582 | \\ if (fn_proto.getAlignExpr()) |align_expr| | ||
| 3583 | \\ tree.prevToken(tree.prevToken(align_expr.firstToken())) | ||
| 3584 | \\else if (fn_proto.getSectionExpr()) |section_expr| | ||
| 3585 | \\ tree.prevToken(tree.prevToken(section_expr.firstToken())) | ||
| 3586 | \\else if (fn_proto.getCallconvExpr()) |callconv_expr| | ||
| 3587 | \\ tree.prevToken(tree.prevToken(callconv_expr.firstToken())) | ||
| 3588 | \\else switch (fn_proto.return_type) { | ||
| 3589 | \\ .Explicit => |node| node.firstToken(), | ||
| 3590 | \\ .InferErrorSet => |node| tree.prevToken(node.firstToken()), | ||
| 3591 | \\ .Invalid => unreachable, | ||
| 3592 | \\}); | ||
| 3593 | \\ | ||
| 3594 | ); | ||
| 3595 | } | ||
| 3596 | |||
| 3597 | test "zig fmt: single argument trailing commas in @builtins()" { | ||
| 3598 | try testCanonical( | ||
| 3599 | \\pub fn foo(qzz: []u8) i1 { | ||
| 3600 | \\ @panic( | ||
| 3601 | \\ foo, | ||
| 3602 | \\ ); | ||
| 3603 | \\ panic( | ||
| 3604 | \\ foo, | ||
| 3605 | \\ ); | ||
| 3606 | \\ @panic( | ||
| 3607 | \\ foo, | ||
| 3608 | \\ bar, | ||
| 3609 | \\ ); | ||
| 3610 | \\} | ||
| 3611 | \\ | ||
| 3612 | ); | ||
| 3613 | } | ||
| 3614 | |||
| 3615 | test "zig fmt: trailing comma should force multiline 1 column" { | ||
| 3616 | try testTransform( | ||
| 3617 | \\pub const UUID_NULL: uuid_t = [16]u8{0,0,0,0,}; | ||
| 3618 | \\ | ||
| 3619 | , | ||
| 3620 | \\pub const UUID_NULL: uuid_t = [16]u8{ | ||
| 3621 | \\ 0, | ||
| 3622 | \\ 0, | ||
| 3623 | \\ 0, | ||
| 3624 | \\ 0, | ||
| 3625 | \\}; | ||
| 3626 | \\ | ||
| 3627 | ); | ||
| 3628 | } | ||
| 3629 | |||
| 3630 | test "zig fmt: function params should align nicely" { | ||
| 3631 | try testCanonical( | ||
| 3632 | \\pub fn foo() void { | ||
| 3633 | \\ cases.addRuntimeSafety("slicing operator with sentinel", | ||
| 3634 | \\ \\const std = @import("std"); | ||
| 3635 | \\ ++ check_panic_msg ++ | ||
| 3636 | \\ \\pub fn main() void { | ||
| 3637 | \\ \\ var buf = [4]u8{'a','b','c',0}; | ||
| 3638 | \\ \\ const slice = buf[0..:0]; | ||
| 3639 | \\ \\} | ||
| 3640 | \\ ); | ||
| 3641 | \\} | ||
| 3642 | \\ | ||
| 3643 | ); | ||
| 3644 | } | ||
| 3645 | |||
| 3324 | const std = @import("std"); | 3646 | const std = @import("std"); |
| 3325 | const mem = std.mem; | 3647 | const mem = std.mem; |
| 3326 | const warn = std.debug.warn; | 3648 | const warn = std.debug.warn; |
lib/std/zig/render.zig+241-139| ... | @@ -522,7 +522,11 @@ fn renderExpression( | ... | @@ -522,7 +522,11 @@ fn renderExpression( |
| 522 | break :blk if (loc.line == 0) op_space else Space.Newline; | 522 | break :blk if (loc.line == 0) op_space else Space.Newline; |
| 523 | }; | 523 | }; |
| 524 | 524 | ||
| 525 | try renderToken(tree, ais, infix_op_node.op_token, after_op_space); | 525 | { |
| 526 | ais.pushIndent(); | ||
| 527 | defer ais.popIndent(); | ||
| 528 | try renderToken(tree, ais, infix_op_node.op_token, after_op_space); | ||
| 529 | } | ||
| 526 | ais.pushIndentOneShot(); | 530 | ais.pushIndentOneShot(); |
| 527 | return renderExpression(allocator, ais, tree, infix_op_node.rhs, space); | 531 | return renderExpression(allocator, ais, tree, infix_op_node.rhs, space); |
| 528 | }, | 532 | }, |
| ... | @@ -710,141 +714,194 @@ fn renderExpression( | ... | @@ -710,141 +714,194 @@ fn renderExpression( |
| 710 | .node => |node| tree.nextToken(node.lastToken()), | 714 | .node => |node| tree.nextToken(node.lastToken()), |
| 711 | }; | 715 | }; |
| 712 | 716 | ||
| 713 | if (exprs.len == 0) { | 717 | switch (lhs) { |
| 714 | switch (lhs) { | 718 | .dot => |dot| try renderToken(tree, ais, dot, Space.None), |
| 715 | .dot => |dot| try renderToken(tree, ais, dot, Space.None), | 719 | .node => |node| try renderExpression(allocator, ais, tree, node, Space.None), |
| 716 | .node => |node| try renderExpression(allocator, ais, tree, node, Space.None), | 720 | } |
| 717 | } | ||
| 718 | |||
| 719 | { | ||
| 720 | ais.pushIndent(); | ||
| 721 | defer ais.popIndent(); | ||
| 722 | try renderToken(tree, ais, lbrace, Space.None); | ||
| 723 | } | ||
| 724 | 721 | ||
| 722 | if (exprs.len == 0) { | ||
| 723 | try renderToken(tree, ais, lbrace, Space.None); | ||
| 725 | return renderToken(tree, ais, rtoken, space); | 724 | return renderToken(tree, ais, rtoken, space); |
| 726 | } | 725 | } |
| 727 | if (exprs.len == 1 and tree.token_ids[exprs[0].*.lastToken() + 1] == .RBrace) { | 726 | |
| 727 | if (exprs.len == 1 and exprs[0].tag != .MultilineStringLiteral and tree.token_ids[exprs[0].*.lastToken() + 1] == .RBrace) { | ||
| 728 | const expr = exprs[0]; | 728 | const expr = exprs[0]; |
| 729 | 729 | ||
| 730 | switch (lhs) { | ||
| 731 | .dot => |dot| try renderToken(tree, ais, dot, Space.None), | ||
| 732 | .node => |node| try renderExpression(allocator, ais, tree, node, Space.None), | ||
| 733 | } | ||
| 734 | try renderToken(tree, ais, lbrace, Space.None); | 730 | try renderToken(tree, ais, lbrace, Space.None); |
| 735 | try renderExpression(allocator, ais, tree, expr, Space.None); | 731 | try renderExpression(allocator, ais, tree, expr, Space.None); |
| 736 | return renderToken(tree, ais, rtoken, space); | 732 | return renderToken(tree, ais, rtoken, space); |
| 737 | } | 733 | } |
| 738 | 734 | ||
| 739 | switch (lhs) { | ||
| 740 | .dot => |dot| try renderToken(tree, ais, dot, Space.None), | ||
| 741 | .node => |node| try renderExpression(allocator, ais, tree, node, Space.None), | ||
| 742 | } | ||
| 743 | |||
| 744 | // scan to find row size | 735 | // scan to find row size |
| 745 | const maybe_row_size: ?usize = blk: { | 736 | if (rowSize(tree, exprs, rtoken) != null) { |
| 746 | var count: usize = 1; | ||
| 747 | for (exprs) |expr, i| { | ||
| 748 | if (i + 1 < exprs.len) { | ||
| 749 | const expr_last_token = expr.lastToken() + 1; | ||
| 750 | const loc = tree.tokenLocation(tree.token_locs[expr_last_token].end, exprs[i + 1].firstToken()); | ||
| 751 | if (loc.line != 0) break :blk count; | ||
| 752 | count += 1; | ||
| 753 | } else { | ||
| 754 | const expr_last_token = expr.lastToken(); | ||
| 755 | const loc = tree.tokenLocation(tree.token_locs[expr_last_token].end, rtoken); | ||
| 756 | if (loc.line == 0) { | ||
| 757 | // all on one line | ||
| 758 | const src_has_trailing_comma = trailblk: { | ||
| 759 | const maybe_comma = tree.prevToken(rtoken); | ||
| 760 | break :trailblk tree.token_ids[maybe_comma] == .Comma; | ||
| 761 | }; | ||
| 762 | if (src_has_trailing_comma) { | ||
| 763 | break :blk 1; // force row size 1 | ||
| 764 | } else { | ||
| 765 | break :blk null; // no newlines | ||
| 766 | } | ||
| 767 | } | ||
| 768 | break :blk count; | ||
| 769 | } | ||
| 770 | } | ||
| 771 | unreachable; | ||
| 772 | }; | ||
| 773 | |||
| 774 | if (maybe_row_size) |row_size| { | ||
| 775 | // A place to store the width of each expression and its column's maximum | ||
| 776 | var widths = try allocator.alloc(usize, exprs.len + row_size); | ||
| 777 | defer allocator.free(widths); | ||
| 778 | mem.set(usize, widths, 0); | ||
| 779 | |||
| 780 | var expr_widths = widths[0 .. widths.len - row_size]; | ||
| 781 | var column_widths = widths[widths.len - row_size ..]; | ||
| 782 | |||
| 783 | // Null ais for counting the printed length of each expression | ||
| 784 | var counting_stream = std.io.countingOutStream(std.io.null_out_stream); | ||
| 785 | var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, counting_stream.writer()); | ||
| 786 | |||
| 787 | for (exprs) |expr, i| { | ||
| 788 | counting_stream.bytes_written = 0; | ||
| 789 | try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None); | ||
| 790 | const width = @intCast(usize, counting_stream.bytes_written); | ||
| 791 | const col = i % row_size; | ||
| 792 | column_widths[col] = std.math.max(column_widths[col], width); | ||
| 793 | expr_widths[i] = width; | ||
| 794 | } | ||
| 795 | |||
| 796 | { | 737 | { |
| 797 | ais.pushIndentNextLine(); | 738 | ais.pushIndentNextLine(); |
| 798 | defer ais.popIndent(); | 739 | defer ais.popIndent(); |
| 799 | try renderToken(tree, ais, lbrace, Space.Newline); | 740 | try renderToken(tree, ais, lbrace, Space.Newline); |
| 800 | 741 | ||
| 801 | var col: usize = 1; | 742 | var expr_index: usize = 0; |
| 802 | for (exprs) |expr, i| { | 743 | while (rowSize(tree, exprs[expr_index..], rtoken)) |row_size| { |
| 803 | if (i + 1 < exprs.len) { | 744 | const row_exprs = exprs[expr_index..]; |
| 804 | const next_expr = exprs[i + 1]; | 745 | // A place to store the width of each expression and its column's maximum |
| 805 | try renderExpression(allocator, ais, tree, expr, Space.None); | 746 | var widths = try allocator.alloc(usize, row_exprs.len + row_size); |
| 806 | 747 | defer allocator.free(widths); | |
| 807 | const comma = tree.nextToken(expr.*.lastToken()); | 748 | mem.set(usize, widths, 0); |
| 808 | 749 | ||
| 809 | if (col != row_size) { | 750 | var expr_newlines = try allocator.alloc(bool, row_exprs.len); |
| 810 | try renderToken(tree, ais, comma, Space.Space); // , | 751 | defer allocator.free(expr_newlines); |
| 811 | 752 | mem.set(bool, expr_newlines, false); | |
| 812 | const padding = column_widths[i % row_size] - expr_widths[i]; | 753 | |
| 813 | try ais.writer().writeByteNTimes(' ', padding); | 754 | var expr_widths = widths[0 .. widths.len - row_size]; |
| 814 | 755 | var column_widths = widths[widths.len - row_size ..]; | |
| 815 | col += 1; | 756 | |
| 816 | continue; | 757 | // Find next row with trailing comment (if any) to end the current section |
| 758 | var section_end = sec_end: { | ||
| 759 | var this_line_first_expr: usize = 0; | ||
| 760 | var this_line_size = rowSize(tree, row_exprs, rtoken); | ||
| 761 | for (row_exprs) |expr, i| { | ||
| 762 | // Ignore comment on first line of this section | ||
| 763 | if (i == 0 or tree.tokensOnSameLine(row_exprs[0].firstToken(), expr.lastToken())) continue; | ||
| 764 | // Track start of line containing comment | ||
| 765 | if (!tree.tokensOnSameLine(row_exprs[this_line_first_expr].firstToken(), expr.lastToken())) { | ||
| 766 | this_line_first_expr = i; | ||
| 767 | this_line_size = rowSize(tree, row_exprs[this_line_first_expr..], rtoken); | ||
| 768 | } | ||
| 769 | |||
| 770 | const maybe_comma = expr.lastToken() + 1; | ||
| 771 | const maybe_comment = expr.lastToken() + 2; | ||
| 772 | if (maybe_comment < tree.token_ids.len) { | ||
| 773 | if (tree.token_ids[maybe_comma] == .Comma and | ||
| 774 | tree.token_ids[maybe_comment] == .LineComment and | ||
| 775 | tree.tokensOnSameLine(expr.lastToken(), maybe_comment)) | ||
| 776 | { | ||
| 777 | var comment_token_loc = tree.token_locs[maybe_comment]; | ||
| 778 | const comment_is_empty = mem.trimRight(u8, tree.tokenSliceLoc(comment_token_loc), " ").len == 2; | ||
| 779 | if (!comment_is_empty) { | ||
| 780 | // Found row ending in comment | ||
| 781 | break :sec_end i - this_line_size.? + 1; | ||
| 782 | } | ||
| 783 | } | ||
| 784 | } | ||
| 817 | } | 785 | } |
| 818 | col = 1; | 786 | break :sec_end row_exprs.len; |
| 787 | }; | ||
| 788 | expr_index += section_end; | ||
| 789 | |||
| 790 | const section_exprs = row_exprs[0..section_end]; | ||
| 791 | |||
| 792 | // Null stream for counting the printed length of each expression | ||
| 793 | var line_find_stream = std.io.findByteOutStream('\n', std.io.null_out_stream); | ||
| 794 | var counting_stream = std.io.countingOutStream(line_find_stream.writer()); | ||
| 795 | var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, counting_stream.writer()); | ||
| 796 | |||
| 797 | // Calculate size of columns in current section | ||
| 798 | var column_counter: usize = 0; | ||
| 799 | var single_line = true; | ||
| 800 | for (section_exprs) |expr, i| { | ||
| 801 | if (i + 1 < section_exprs.len) { | ||
| 802 | counting_stream.bytes_written = 0; | ||
| 803 | line_find_stream.byte_found = false; | ||
| 804 | try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None); | ||
| 805 | const width = @intCast(usize, counting_stream.bytes_written); | ||
| 806 | expr_widths[i] = width; | ||
| 807 | expr_newlines[i] = line_find_stream.byte_found; | ||
| 808 | |||
| 809 | if (!line_find_stream.byte_found) { | ||
| 810 | const column = column_counter % row_size; | ||
| 811 | column_widths[column] = std.math.max(column_widths[column], width); | ||
| 812 | |||
| 813 | const expr_last_token = expr.*.lastToken() + 1; | ||
| 814 | const next_expr = section_exprs[i + 1]; | ||
| 815 | const loc = tree.tokenLocation(tree.token_locs[expr_last_token].start, next_expr.*.firstToken()); | ||
| 816 | if (loc.line == 0) { | ||
| 817 | column_counter += 1; | ||
| 818 | } else { | ||
| 819 | single_line = false; | ||
| 820 | column_counter = 0; | ||
| 821 | } | ||
| 822 | } else { | ||
| 823 | single_line = false; | ||
| 824 | column_counter = 0; | ||
| 825 | } | ||
| 826 | } else { | ||
| 827 | counting_stream.bytes_written = 0; | ||
| 828 | try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None); | ||
| 829 | const width = @intCast(usize, counting_stream.bytes_written); | ||
| 830 | expr_widths[i] = width; | ||
| 831 | expr_newlines[i] = line_find_stream.byte_found; | ||
| 832 | |||
| 833 | if (!line_find_stream.byte_found) { | ||
| 834 | const column = column_counter % row_size; | ||
| 835 | column_widths[column] = std.math.max(column_widths[column], width); | ||
| 836 | } | ||
| 837 | break; | ||
| 838 | } | ||
| 839 | } | ||
| 819 | 840 | ||
| 820 | if (tree.token_ids[tree.nextToken(comma)] != .MultilineStringLiteralLine) { | 841 | // Render exprs in current section |
| 842 | column_counter = 0; | ||
| 843 | var last_col_index: usize = row_size - 1; | ||
| 844 | for (section_exprs) |expr, i| { | ||
| 845 | if (i + 1 < section_exprs.len) { | ||
| 846 | const next_expr = section_exprs[i + 1]; | ||
| 847 | try renderExpression(allocator, ais, tree, expr, Space.None); | ||
| 848 | |||
| 849 | const comma = tree.nextToken(expr.*.lastToken()); | ||
| 850 | |||
| 851 | if (column_counter != last_col_index) { | ||
| 852 | if (!expr_newlines[i] and !expr_newlines[i + 1]) { | ||
| 853 | // Neither the current or next expression is multiline | ||
| 854 | try renderToken(tree, ais, comma, Space.Space); // , | ||
| 855 | assert(column_widths[column_counter % row_size] >= expr_widths[i]); | ||
| 856 | const padding = column_widths[column_counter % row_size] - expr_widths[i]; | ||
| 857 | try ais.writer().writeByteNTimes(' ', padding); | ||
| 858 | |||
| 859 | column_counter += 1; | ||
| 860 | continue; | ||
| 861 | } | ||
| 862 | } | ||
| 863 | if (single_line and row_size != 1) { | ||
| 864 | try renderToken(tree, ais, comma, Space.Space); // , | ||
| 865 | continue; | ||
| 866 | } | ||
| 867 | |||
| 868 | column_counter = 0; | ||
| 821 | try renderToken(tree, ais, comma, Space.Newline); // , | 869 | try renderToken(tree, ais, comma, Space.Newline); // , |
| 870 | try renderExtraNewline(tree, ais, next_expr); | ||
| 822 | } else { | 871 | } else { |
| 823 | try renderToken(tree, ais, comma, Space.None); // , | 872 | const maybe_comma = tree.nextToken(expr.*.lastToken()); |
| 873 | if (tree.token_ids[maybe_comma] == .Comma) { | ||
| 874 | try renderExpression(allocator, ais, tree, expr, Space.None); // , | ||
| 875 | try renderToken(tree, ais, maybe_comma, Space.Newline); // , | ||
| 876 | } else { | ||
| 877 | try renderExpression(allocator, ais, tree, expr, Space.Comma); // , | ||
| 878 | } | ||
| 824 | } | 879 | } |
| 880 | } | ||
| 825 | 881 | ||
| 826 | try renderExtraNewline(tree, ais, next_expr); | 882 | if (expr_index == exprs.len) { |
| 827 | } else { | 883 | break; |
| 828 | try renderExpression(allocator, ais, tree, expr, Space.Comma); // , | ||
| 829 | } | 884 | } |
| 830 | } | 885 | } |
| 831 | } | 886 | } |
| 832 | return renderToken(tree, ais, rtoken, space); | ||
| 833 | } else { | ||
| 834 | try renderToken(tree, ais, lbrace, Space.Space); | ||
| 835 | for (exprs) |expr, i| { | ||
| 836 | if (i + 1 < exprs.len) { | ||
| 837 | const next_expr = exprs[i + 1]; | ||
| 838 | try renderExpression(allocator, ais, tree, expr, Space.None); | ||
| 839 | const comma = tree.nextToken(expr.*.lastToken()); | ||
| 840 | try renderToken(tree, ais, comma, Space.Space); // , | ||
| 841 | } else { | ||
| 842 | try renderExpression(allocator, ais, tree, expr, Space.Space); | ||
| 843 | } | ||
| 844 | } | ||
| 845 | 887 | ||
| 846 | return renderToken(tree, ais, rtoken, space); | 888 | return renderToken(tree, ais, rtoken, space); |
| 847 | } | 889 | } |
| 890 | |||
| 891 | // Single line | ||
| 892 | try renderToken(tree, ais, lbrace, Space.Space); | ||
| 893 | for (exprs) |expr, i| { | ||
| 894 | if (i + 1 < exprs.len) { | ||
| 895 | const next_expr = exprs[i + 1]; | ||
| 896 | try renderExpression(allocator, ais, tree, expr, Space.None); | ||
| 897 | const comma = tree.nextToken(expr.*.lastToken()); | ||
| 898 | try renderToken(tree, ais, comma, Space.Space); // , | ||
| 899 | } else { | ||
| 900 | try renderExpression(allocator, ais, tree, expr, Space.Space); | ||
| 901 | } | ||
| 902 | } | ||
| 903 | |||
| 904 | return renderToken(tree, ais, rtoken, space); | ||
| 848 | }, | 905 | }, |
| 849 | 906 | ||
| 850 | .StructInitializer, .StructInitializerDot => { | 907 | .StructInitializer, .StructInitializerDot => { |
| ... | @@ -1004,21 +1061,29 @@ fn renderExpression( | ... | @@ -1004,21 +1061,29 @@ fn renderExpression( |
| 1004 | }; | 1061 | }; |
| 1005 | 1062 | ||
| 1006 | if (src_has_trailing_comma) { | 1063 | if (src_has_trailing_comma) { |
| 1007 | try renderToken(tree, ais, lparen, Space.Newline); | 1064 | { |
| 1008 | |||
| 1009 | const params = call.params(); | ||
| 1010 | for (params) |param_node, i| { | ||
| 1011 | ais.pushIndent(); | 1065 | ais.pushIndent(); |
| 1012 | defer ais.popIndent(); | 1066 | defer ais.popIndent(); |
| 1013 | 1067 | ||
| 1014 | if (i + 1 < params.len) { | 1068 | try renderToken(tree, ais, lparen, Space.Newline); // ( |
| 1015 | const next_node = params[i + 1]; | 1069 | const params = call.params(); |
| 1016 | try renderExpression(allocator, ais, tree, param_node, Space.None); | 1070 | for (params) |param_node, i| { |
| 1017 | const comma = tree.nextToken(param_node.lastToken()); | 1071 | if (i + 1 < params.len) { |
| 1018 | try renderToken(tree, ais, comma, Space.Newline); // , | 1072 | const next_node = params[i + 1]; |
| 1019 | try renderExtraNewline(tree, ais, next_node); | 1073 | try renderExpression(allocator, ais, tree, param_node, Space.None); |
| 1020 | } else { | 1074 | |
| 1021 | try renderExpression(allocator, ais, tree, param_node, Space.Comma); | 1075 | // Unindent the comma for multiline string literals |
| 1076 | const maybe_multiline_string = param_node.firstToken(); | ||
| 1077 | const is_multiline_string = tree.token_ids[maybe_multiline_string] == .MultilineStringLiteralLine; | ||
| 1078 | if (is_multiline_string) ais.popIndent(); | ||
| 1079 | defer if (is_multiline_string) ais.pushIndent(); | ||
| 1080 | |||
| 1081 | const comma = tree.nextToken(param_node.lastToken()); | ||
| 1082 | try renderToken(tree, ais, comma, Space.Newline); // , | ||
| 1083 | try renderExtraNewline(tree, ais, next_node); | ||
| 1084 | } else { | ||
| 1085 | try renderExpression(allocator, ais, tree, param_node, Space.Comma); | ||
| 1086 | } | ||
| 1022 | } | 1087 | } |
| 1023 | } | 1088 | } |
| 1024 | return renderToken(tree, ais, call.rtoken, space); | 1089 | return renderToken(tree, ais, call.rtoken, space); |
| ... | @@ -1028,17 +1093,20 @@ fn renderExpression( | ... | @@ -1028,17 +1093,20 @@ fn renderExpression( |
| 1028 | 1093 | ||
| 1029 | const params = call.params(); | 1094 | const params = call.params(); |
| 1030 | for (params) |param_node, i| { | 1095 | for (params) |param_node, i| { |
| 1031 | if (param_node.*.tag == .MultilineStringLiteral) ais.pushIndentOneShot(); | 1096 | const maybe_comment = param_node.firstToken() - 1; |
| 1097 | const maybe_multiline_string = param_node.firstToken(); | ||
| 1098 | if (tree.token_ids[maybe_multiline_string] == .MultilineStringLiteralLine or tree.token_ids[maybe_comment] == .LineComment) { | ||
| 1099 | ais.pushIndentOneShot(); | ||
| 1100 | } | ||
| 1032 | 1101 | ||
| 1033 | try renderExpression(allocator, ais, tree, param_node, Space.None); | 1102 | try renderExpression(allocator, ais, tree, param_node, Space.None); |
| 1034 | 1103 | ||
| 1035 | if (i + 1 < params.len) { | 1104 | if (i + 1 < params.len) { |
| 1036 | const next_param = params[i + 1]; | ||
| 1037 | const comma = tree.nextToken(param_node.lastToken()); | 1105 | const comma = tree.nextToken(param_node.lastToken()); |
| 1038 | try renderToken(tree, ais, comma, Space.Space); | 1106 | try renderToken(tree, ais, comma, Space.Space); |
| 1039 | } | 1107 | } |
| 1040 | } | 1108 | } |
| 1041 | return renderToken(tree, ais, call.rtoken, space); | 1109 | return renderToken(tree, ais, call.rtoken, space); // ) |
| 1042 | }, | 1110 | }, |
| 1043 | 1111 | ||
| 1044 | .ArrayAccess => { | 1112 | .ArrayAccess => { |
| ... | @@ -1429,7 +1497,7 @@ fn renderExpression( | ... | @@ -1429,7 +1497,7 @@ fn renderExpression( |
| 1429 | try renderToken(tree, ais, builtin_call.builtin_token, Space.None); // @name | 1497 | try renderToken(tree, ais, builtin_call.builtin_token, Space.None); // @name |
| 1430 | 1498 | ||
| 1431 | const src_params_trailing_comma = blk: { | 1499 | const src_params_trailing_comma = blk: { |
| 1432 | if (builtin_call.params_len < 2) break :blk false; | 1500 | if (builtin_call.params_len == 0) break :blk false; |
| 1433 | const last_node = builtin_call.params()[builtin_call.params_len - 1]; | 1501 | const last_node = builtin_call.params()[builtin_call.params_len - 1]; |
| 1434 | const maybe_comma = tree.nextToken(last_node.lastToken()); | 1502 | const maybe_comma = tree.nextToken(last_node.lastToken()); |
| 1435 | break :blk tree.token_ids[maybe_comma] == .Comma; | 1503 | break :blk tree.token_ids[maybe_comma] == .Comma; |
| ... | @@ -1443,6 +1511,10 @@ fn renderExpression( | ... | @@ -1443,6 +1511,10 @@ fn renderExpression( |
| 1443 | // render all on one line, no trailing comma | 1511 | // render all on one line, no trailing comma |
| 1444 | const params = builtin_call.params(); | 1512 | const params = builtin_call.params(); |
| 1445 | for (params) |param_node, i| { | 1513 | for (params) |param_node, i| { |
| 1514 | const maybe_comment = param_node.firstToken() - 1; | ||
| 1515 | if (param_node.*.tag == .MultilineStringLiteral or tree.token_ids[maybe_comment] == .LineComment) { | ||
| 1516 | ais.pushIndentOneShot(); | ||
| 1517 | } | ||
| 1446 | try renderExpression(allocator, ais, tree, param_node, Space.None); | 1518 | try renderExpression(allocator, ais, tree, param_node, Space.None); |
| 1447 | 1519 | ||
| 1448 | if (i + 1 < params.len) { | 1520 | if (i + 1 < params.len) { |
| ... | @@ -1494,19 +1566,20 @@ fn renderExpression( | ... | @@ -1494,19 +1566,20 @@ fn renderExpression( |
| 1494 | assert(tree.token_ids[lparen] == .LParen); | 1566 | assert(tree.token_ids[lparen] == .LParen); |
| 1495 | 1567 | ||
| 1496 | const rparen = tree.prevToken( | 1568 | const rparen = tree.prevToken( |
| 1497 | // the first token for the annotation expressions is the left | 1569 | // the first token for the annotation expressions is the left |
| 1498 | // parenthesis, hence the need for two prevToken | 1570 | // parenthesis, hence the need for two prevToken |
| 1499 | if (fn_proto.getAlignExpr()) |align_expr| | 1571 | if (fn_proto.getAlignExpr()) |align_expr| |
| 1500 | tree.prevToken(tree.prevToken(align_expr.firstToken())) | 1572 | tree.prevToken(tree.prevToken(align_expr.firstToken())) |
| 1501 | else if (fn_proto.getSectionExpr()) |section_expr| | 1573 | else if (fn_proto.getSectionExpr()) |section_expr| |
| 1502 | tree.prevToken(tree.prevToken(section_expr.firstToken())) | 1574 | tree.prevToken(tree.prevToken(section_expr.firstToken())) |
| 1503 | else if (fn_proto.getCallconvExpr()) |callconv_expr| | 1575 | else if (fn_proto.getCallconvExpr()) |callconv_expr| |
| 1504 | tree.prevToken(tree.prevToken(callconv_expr.firstToken())) | 1576 | tree.prevToken(tree.prevToken(callconv_expr.firstToken())) |
| 1505 | else switch (fn_proto.return_type) { | 1577 | else switch (fn_proto.return_type) { |
| 1506 | .Explicit => |node| node.firstToken(), | 1578 | .Explicit => |node| node.firstToken(), |
| 1507 | .InferErrorSet => |node| tree.prevToken(node.firstToken()), | 1579 | .InferErrorSet => |node| tree.prevToken(node.firstToken()), |
| 1508 | .Invalid => unreachable, | 1580 | .Invalid => unreachable, |
| 1509 | }); | 1581 | }, |
| 1582 | ); | ||
| 1510 | assert(tree.token_ids[rparen] == .RParen); | 1583 | assert(tree.token_ids[rparen] == .RParen); |
| 1511 | 1584 | ||
| 1512 | const src_params_trailing_comma = blk: { | 1585 | const src_params_trailing_comma = blk: { |
| ... | @@ -1758,7 +1831,7 @@ fn renderExpression( | ... | @@ -1758,7 +1831,7 @@ fn renderExpression( |
| 1758 | } | 1831 | } |
| 1759 | 1832 | ||
| 1760 | if (while_node.payload) |payload| { | 1833 | if (while_node.payload) |payload| { |
| 1761 | const payload_space = Space.Space; //if (while_node.continue_expr != null) Space.Space else block_start_space; | 1834 | const payload_space = if (while_node.continue_expr != null) Space.Space else block_start_space; |
| 1762 | try renderExpression(allocator, ais, tree, payload, payload_space); | 1835 | try renderExpression(allocator, ais, tree, payload, payload_space); |
| 1763 | } | 1836 | } |
| 1764 | 1837 | ||
| ... | @@ -1873,7 +1946,12 @@ fn renderExpression( | ... | @@ -1873,7 +1946,12 @@ fn renderExpression( |
| 1873 | 1946 | ||
| 1874 | if (src_has_newline) { | 1947 | if (src_has_newline) { |
| 1875 | const after_rparen_space = if (if_node.payload == null) Space.Newline else Space.Space; | 1948 | const after_rparen_space = if (if_node.payload == null) Space.Newline else Space.Space; |
| 1876 | try renderToken(tree, ais, rparen, after_rparen_space); // ) | 1949 | |
| 1950 | { | ||
| 1951 | ais.pushIndent(); | ||
| 1952 | defer ais.popIndent(); | ||
| 1953 | try renderToken(tree, ais, rparen, after_rparen_space); // ) | ||
| 1954 | } | ||
| 1877 | 1955 | ||
| 1878 | if (if_node.payload) |payload| { | 1956 | if (if_node.payload) |payload| { |
| 1879 | try renderExpression(allocator, ais, tree, payload, Space.Newline); | 1957 | try renderExpression(allocator, ais, tree, payload, Space.Newline); |
| ... | @@ -2558,3 +2636,27 @@ fn copyFixingWhitespace(ais: anytype, slice: []const u8) @TypeOf(ais.*).Error!vo | ... | @@ -2558,3 +2636,27 @@ fn copyFixingWhitespace(ais: anytype, slice: []const u8) @TypeOf(ais.*).Error!vo |
| 2558 | else => try ais.writer().writeByte(byte), | 2636 | else => try ais.writer().writeByte(byte), |
| 2559 | }; | 2637 | }; |
| 2560 | } | 2638 | } |
| 2639 | |||
| 2640 | fn rowSize(tree: *ast.Tree, exprs: []*ast.Node, rtoken: ast.TokenIndex) ?usize { | ||
| 2641 | const first_token = exprs[0].firstToken(); | ||
| 2642 | const first_loc = tree.tokenLocation(tree.token_locs[first_token].start, rtoken); | ||
| 2643 | if (first_loc.line == 0) { | ||
| 2644 | const maybe_comma = tree.prevToken(rtoken); | ||
| 2645 | if (tree.token_ids[maybe_comma] == .Comma) | ||
| 2646 | return 1; | ||
| 2647 | return null; // no newlines | ||
| 2648 | } | ||
| 2649 | |||
| 2650 | var count: usize = 1; | ||
| 2651 | for (exprs) |expr, i| { | ||
| 2652 | if (i + 1 < exprs.len) { | ||
| 2653 | const expr_last_token = expr.lastToken() + 1; | ||
| 2654 | const loc = tree.tokenLocation(tree.token_locs[expr_last_token].start, exprs[i + 1].firstToken()); | ||
| 2655 | if (loc.line != 0) return count; | ||
| 2656 | count += 1; | ||
| 2657 | } else { | ||
| 2658 | return count; | ||
| 2659 | } | ||
| 2660 | } | ||
| 2661 | unreachable; | ||
| 2662 | } |
lib/std/zig/tokenizer.zig+9| ... | @@ -1195,6 +1195,7 @@ pub const Tokenizer = struct { | ... | @@ -1195,6 +1195,7 @@ pub const Tokenizer = struct { |
| 1195 | }, | 1195 | }, |
| 1196 | .num_dot_hex => switch (c) { | 1196 | .num_dot_hex => switch (c) { |
| 1197 | '.' => { | 1197 | '.' => { |
| 1198 | result.id = .IntegerLiteral; | ||
| 1198 | self.index -= 1; | 1199 | self.index -= 1; |
| 1199 | state = .start; | 1200 | state = .start; |
| 1200 | break; | 1201 | break; |
| ... | @@ -1758,6 +1759,14 @@ test "correctly parse pointer assignment" { | ... | @@ -1758,6 +1759,14 @@ test "correctly parse pointer assignment" { |
| 1758 | }); | 1759 | }); |
| 1759 | } | 1760 | } |
| 1760 | 1761 | ||
| 1762 | test "tokenizer - range literals" { | ||
| 1763 | testTokenize("0...9", &[_]Token.Id{ .IntegerLiteral, .Ellipsis3, .IntegerLiteral }); | ||
| 1764 | testTokenize("'0'...'9'", &[_]Token.Id{ .CharLiteral, .Ellipsis3, .CharLiteral }); | ||
| 1765 | testTokenize("0x00...0x09", &[_]Token.Id{ .IntegerLiteral, .Ellipsis3, .IntegerLiteral }); | ||
| 1766 | testTokenize("0b00...0b11", &[_]Token.Id{ .IntegerLiteral, .Ellipsis3, .IntegerLiteral }); | ||
| 1767 | testTokenize("0o00...0o11", &[_]Token.Id{ .IntegerLiteral, .Ellipsis3, .IntegerLiteral }); | ||
| 1768 | } | ||
| 1769 | |||
| 1761 | test "tokenizer - number literals decimal" { | 1770 | test "tokenizer - number literals decimal" { |
| 1762 | testTokenize("0", &[_]Token.Id{.IntegerLiteral}); | 1771 | testTokenize("0", &[_]Token.Id{.IntegerLiteral}); |
| 1763 | testTokenize("1", &[_]Token.Id{.IntegerLiteral}); | 1772 | testTokenize("1", &[_]Token.Id{.IntegerLiteral}); |
src/stage1/tokenizer.cpp+3-3| ... | @@ -1225,9 +1225,6 @@ void tokenize(Buf *buf, Tokenization *out) { | ... | @@ -1225,9 +1225,6 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 1225 | invalid_char_error(&t, c); | 1225 | invalid_char_error(&t, c); |
| 1226 | break; | 1226 | break; |
| 1227 | } | 1227 | } |
| 1228 | if (t.radix != 16 && t.radix != 10) { | ||
| 1229 | invalid_char_error(&t, c); | ||
| 1230 | } | ||
| 1231 | t.state = TokenizeStateNumberDot; | 1228 | t.state = TokenizeStateNumberDot; |
| 1232 | break; | 1229 | break; |
| 1233 | } | 1230 | } |
| ... | @@ -1281,6 +1278,9 @@ void tokenize(Buf *buf, Tokenization *out) { | ... | @@ -1281,6 +1278,9 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 1281 | t.state = TokenizeStateStart; | 1278 | t.state = TokenizeStateStart; |
| 1282 | continue; | 1279 | continue; |
| 1283 | } | 1280 | } |
| 1281 | if (t.radix != 16 && t.radix != 10) { | ||
| 1282 | invalid_char_error(&t, c); | ||
| 1283 | } | ||
| 1284 | t.pos -= 1; | 1284 | t.pos -= 1; |
| 1285 | t.state = TokenizeStateFloatFractionNoUnderscore; | 1285 | t.state = TokenizeStateFloatFractionNoUnderscore; |
| 1286 | assert(t.cur_tok->id == TokenIdIntLiteral); | 1286 | assert(t.cur_tok->id == TokenIdIntLiteral); |