diff --git a/README.md b/README.md index d644037..a81504c 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,10 @@ [Installation](#installation) -# 🍵 mynixos-extra-modules +# 🍵 nixos-extra-modules -This repository contains extra modules for `mynixos` that are very opinionated and mainly useful to me and is used in [`sokai/mynixos-config`](https://git.mediani.de/sokai/mynixos-config). -All modules in here are opt-in, so nothing will be changed unless you decide you want to use that specific module. +This repository contains extra modules for nixos that are very opinionated and mainly +useful to me and my colleagues. All modules in here are opt-in, so nothing will +be changed unless you decide you want to use that specific module. ## Overview @@ -30,9 +31,12 @@ Wallpapers | Module | [Link](./hm-modules/wallpapers.nix) | - | - | A simple wal ## Installation -To use the extra modules, you will have to add this project to your `flake.nix`, and import the provided main NixOS module in your hosts. Afterwards the new options will be available. +To use the extra modules, you will have to add this project to your `flake.nix`, +and import the provided main NixOS module in your hosts. Afterwards the new options +will be available. -Certain modules may require the use of additional flakes. In particular depending on the modules you want to use, you might need: +Certain modules may require the use of additional flakes. In particular +depending on the modules you want to use, you might need: - [agenix](https://github.com/ryantm/agenix) - [agenix-rekey](https://github.com/oddlama/agenix-rekey) @@ -41,9 +45,13 @@ Certain modules may require the use of additional flakes. In particular dependin - [impermanence](https://github.com/nix-community/impermanence) - [microvm.nix](https://github.com/astro/microvm.nix) -You also must have a `specialArgs.inputs` that refers to all of your flake's inputs, and `inputs.self.pkgs.${system}` must refer to an initialized package set for that specific system that includes extra-modules as an overlay. +You also must have a `specialArgs.inputs` that refers to all of your flake's inputs, +and `inputs.self.pkgs.${system}` must refer to an initialized package set for that +specific system that includes extra-modules as an overlay. -All cross-node configuration modules (like wireguard) require you to expose all relevant nodes in your flake as `inputs.self.nodes`, so their configuration can be accessed by other nodes. +All cross-node configuration modules (like wireguard) require you to expose +all relevant nodes in your flake as `inputs.self.nodes`, so their configuration +can be accessed by other nodes. Here's an example configuration: @@ -52,14 +60,13 @@ Here's an example configuration: inputs = { flake-utils.url = "github:numtide/flake-utils"; - # TODO: "nixos-extra-modules" → "mynixos-extra-modules"? nixos-extra-modules = { - url = "git+ssh://git@git.mediani.de/sokai/mynixos-extra-modules"; + url = "github:oddlama/nixos-extra-modules"; inputs.nixpkgs.follows = "nixpkgs"; inputs.flake-utils.follows = "flake-utils"; }; - nixpkgs.url = "git+ssh://git@git.mediani.de/mirrors/NixOS_nixpkgs?ref=nixos-25.05"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; # Additional inputs, may or may not be needed for a particular module or extension. # Enable what you use. @@ -103,7 +110,7 @@ Here's an example configuration: ... } @ inputs: { # Example system configuration - nixosConfigurations.myhostname = let + nixosConfigurations.yourhostname = let system = "x86_64-linux"; pkgs = self.pkgs.${system}; in nixpkgs.lib.nixosSystem { @@ -146,4 +153,3 @@ Here's an example configuration: } } ``` -… or have a look at the **original**: [`oddlama/nix-config`](https://github.com/oddlama/nix-config) <3 :) \ No newline at end of file diff --git a/flake.lock b/flake.lock index e28dfde..cc6aa27 100644 --- a/flake.lock +++ b/flake.lock @@ -1,46 +1,5 @@ { "nodes": { - "blank": { - "locked": { - "lastModified": 1625557891, - "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", - "owner": "divnix", - "repo": "blank", - "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", - "type": "github" - }, - "original": { - "owner": "divnix", - "repo": "blank", - "type": "github" - } - }, - "crane": { - "inputs": { - "flake-compat": "flake-compat_2", - "flake-utils": "flake-utils_2", - "nixpkgs": [ - "nixt", - "std", - "paisano-mdbook-preprocessor", - "nixpkgs" - ], - "rust-overlay": "rust-overlay" - }, - "locked": { - "lastModified": 1676162383, - "narHash": "sha256-krUCKdz7ebHlFYm/A7IbKDnj2ZmMMm3yIEQcooqm7+E=", - "owner": "ipetkov", - "repo": "crane", - "rev": "6fb400ec631b22ccdbc7090b38207f7fb5cfb5f2", - "type": "github" - }, - "original": { - "owner": "ipetkov", - "repo": "crane", - "type": "github" - } - }, "devshell": { "inputs": { "nixpkgs": [ @@ -61,115 +20,7 @@ "type": "github" } }, - "devshell_2": { - "inputs": { - "flake-utils": [ - "nixt", - "std", - "flake-utils" - ], - "nixpkgs": [ - "nixt", - "std", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1682700442, - "narHash": "sha256-qjaAAcCYgp1pBBG7mY9z95ODUBZMtUpf0Qp3Gt/Wha0=", - "owner": "numtide", - "repo": "devshell", - "rev": "fb6673fe9fe4409e3f43ca86968261e970918a83", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "devshell", - "type": "github" - } - }, - "dmerge": { - "inputs": { - "haumea": "haumea", - "namaka": "namaka", - "nixlib": [ - "nixt", - "std", - "nixpkgs" - ], - "yants": [ - "nixt", - "std", - "yants" - ] - }, - "locked": { - "lastModified": 1684178600, - "narHash": "sha256-EtSQcCHRQUBBEj4vbYU0vgPUYiKP261ero5k1QfQ3Bc=", - "owner": "divnix", - "repo": "dmerge", - "rev": "ac9932f26325afac5baa59cf6478432d17762a4e", - "type": "github" - }, - "original": { - "owner": "divnix", - "ref": "0.2.0", - "repo": "dmerge", - "type": "github" - } - }, - "fenix": { - "inputs": { - "nixpkgs": "nixpkgs_2", - "rust-analyzer-src": "rust-analyzer-src" - }, - "locked": { - "lastModified": 1677306201, - "narHash": "sha256-VZ9x7qdTosFvVsrpgFHrtYfT6PU3yMIs7NRYn9ELapI=", - "owner": "nix-community", - "repo": "fenix", - "rev": "0923f0c162f65ae40261ec940406049726cfeab4", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "fenix", - "type": "github" - } - }, "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-compat_2": { - "flake": false, - "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-compat_3": { "flake": false, "locked": { "lastModified": 1696426674, @@ -203,36 +54,6 @@ "type": "github" } }, - "flake-utils": { - "locked": { - "lastModified": 1659877975, - "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_2": { - "locked": { - "lastModified": 1667395993, - "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "gitignore": { "inputs": { "nixpkgs": [ @@ -254,138 +75,17 @@ "type": "github" } }, - "haumea": { - "inputs": { - "nixpkgs": [ - "nixt", - "std", - "dmerge", - "nixlib" - ] - }, + "lib-net": { + "flake": false, "locked": { - "lastModified": 1681176209, - "narHash": "sha256-bJLDun6esIyWtwRVXcsgzGbh4UKu8wJDrPgykqPyzmg=", - "owner": "nix-community", - "repo": "haumea", - "rev": "b915b66b27da3a595d77b139e945bb0a2fcac926", - "type": "github" + "lastModified": 1596309860, + "narHash": "sha256-izAzepR/6cDvnRfaa2ceSolMLMwqzQB5x9q62aR5J2g=", + "type": "tarball", + "url": "https://gist.github.com/duairc/5c9bb3c922e5d501a1edb9e7b3b845ba/archive/3885f7cd9ed0a746a9d675da6f265d41e9fd6704.tar.gz" }, "original": { - "owner": "nix-community", - "repo": "haumea", - "type": "github" - } - }, - "incl": { - "inputs": { - "nixlib": [ - "nixt", - "std", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1669263024, - "narHash": "sha256-E/+23NKtxAqYG/0ydYgxlgarKnxmDbg6rCMWnOBqn9Q=", - "owner": "divnix", - "repo": "incl", - "rev": "ce7bebaee048e4cd7ebdb4cee7885e00c4e2abca", - "type": "github" - }, - "original": { - "owner": "divnix", - "repo": "incl", - "type": "github" - } - }, - "n2c": { - "inputs": { - "flake-utils": [ - "nixt", - "std", - "flake-utils" - ], - "nixpkgs": [ - "nixt", - "std", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1677330646, - "narHash": "sha256-hUYCwJneMjnxTvj30Fjow6UMJUITqHlpUGpXMPXUJsU=", - "owner": "nlewo", - "repo": "nix2container", - "rev": "ebca8f58d450cae1a19c07701a5a8ae40afc9efc", - "type": "github" - }, - "original": { - "owner": "nlewo", - "repo": "nix2container", - "type": "github" - } - }, - "namaka": { - "inputs": { - "haumea": [ - "nixt", - "std", - "dmerge", - "haumea" - ], - "nixpkgs": [ - "nixt", - "std", - "dmerge", - "nixlib" - ] - }, - "locked": { - "lastModified": 1683059428, - "narHash": "sha256-ZTMqleCWmuNWhZE375gtF1j1JRkaKEUFN1AM43e7h4Y=", - "owner": "nix-community", - "repo": "namaka", - "rev": "2deba2f416454aec770bc1cc7365e39c73e6b1d7", - "type": "github" - }, - "original": { - "owner": "nix-community", - "ref": "v0.1.1", - "repo": "namaka", - "type": "github" - } - }, - "nixago": { - "inputs": { - "flake-utils": [ - "nixt", - "std", - "flake-utils" - ], - "nixago-exts": [ - "nixt", - "std", - "blank" - ], - "nixpkgs": [ - "nixt", - "std", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1683210100, - "narHash": "sha256-bhGDOlkWtlhVECpoOog4fWiFJmLCpVEg09a40aTjCbw=", - "owner": "nix-community", - "repo": "nixago", - "rev": "1da60ad9412135f9ed7a004669fdcf3d378ec630", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nixago", - "type": "github" + "type": "tarball", + "url": "https://gist.github.com/duairc/5c9bb3c922e5d501a1edb9e7b3b845ba/archive/3885f7cd9ed0a746a9d675da6f265d41e9fd6704.tar.gz" } }, "nixpkgs": { @@ -416,170 +116,9 @@ "url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz" } }, - "nixpkgs_2": { - "locked": { - "lastModified": 1677063315, - "narHash": "sha256-qiB4ajTeAOVnVSAwCNEEkoybrAlA+cpeiBxLobHndE8=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "988cc958c57ce4350ec248d2d53087777f9e1949", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixt": { - "inputs": { - "flake-compat": "flake-compat", - "nixpkgs": [ - "nixpkgs" - ], - "std": "std", - "std-data-collection": "std-data-collection" - }, - "locked": { - "lastModified": 1729273076, - "narHash": "sha256-h2Y+5bikSXS8MPYpxyZpd+VX9H5uuCS/csMMxZCoS3c=", - "owner": "nix-community", - "repo": "nixt", - "rev": "ad8863c9f9e5a166d663f2f1f0eef74ab913a883", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nixt", - "type": "github" - } - }, - "nosys": { - "locked": { - "lastModified": 1668010795, - "narHash": "sha256-JBDVBnos8g0toU7EhIIqQ1If5m/nyBqtHhL3sicdPwI=", - "owner": "divnix", - "repo": "nosys", - "rev": "feade0141487801c71ff55623b421ed535dbdefa", - "type": "github" - }, - "original": { - "owner": "divnix", - "repo": "nosys", - "type": "github" - } - }, - "paisano": { - "inputs": { - "nixpkgs": [ - "nixt", - "std", - "nixpkgs" - ], - "nosys": "nosys", - "yants": [ - "nixt", - "std", - "yants" - ] - }, - "locked": { - "lastModified": 1678949904, - "narHash": "sha256-oAoF66hYYz1RPh3lEwb9/4e4iyBAfTbQKZRRQ8gP0Ds=", - "owner": "paisano-nix", - "repo": "core", - "rev": "88f2aff10a5064551d1d4cb86800d17084489ce3", - "type": "github" - }, - "original": { - "owner": "paisano-nix", - "repo": "core", - "type": "github" - } - }, - "paisano-actions": { - "inputs": { - "nixpkgs": [ - "nixt", - "std", - "paisano-mdbook-preprocessor", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1677306424, - "narHash": "sha256-H9/dI2rGEbKo4KEisqbRPHFG2ajF8Tm111NPdKGIf28=", - "owner": "paisano-nix", - "repo": "actions", - "rev": "65ec4e080b3480167fc1a748c89a05901eea9a9b", - "type": "github" - }, - "original": { - "owner": "paisano-nix", - "repo": "actions", - "type": "github" - } - }, - "paisano-mdbook-preprocessor": { - "inputs": { - "crane": "crane", - "fenix": "fenix", - "nixpkgs": [ - "nixt", - "std", - "nixpkgs" - ], - "paisano-actions": "paisano-actions", - "std": [ - "nixt", - "std" - ] - }, - "locked": { - "lastModified": 1680654400, - "narHash": "sha256-Qdpio+ldhUK3zfl22Mhf8HUULdUOJXDWDdO7MIK69OU=", - "owner": "paisano-nix", - "repo": "mdbook-paisano-preprocessor", - "rev": "11a8fc47f574f194a7ae7b8b98001f6143ba4cf1", - "type": "github" - }, - "original": { - "owner": "paisano-nix", - "repo": "mdbook-paisano-preprocessor", - "type": "github" - } - }, - "paisano-tui": { - "inputs": { - "nixpkgs": [ - "nixt", - "std", - "blank" - ], - "std": [ - "nixt", - "std" - ] - }, - "locked": { - "lastModified": 1681847764, - "narHash": "sha256-mdd7PJW1BZvxy0cIKsPfAO+ohVl/V7heE5ZTAHzTdv8=", - "owner": "paisano-nix", - "repo": "tui", - "rev": "3096bad91cae73ab8ab3367d31f8a143d248a244", - "type": "github" - }, - "original": { - "owner": "paisano-nix", - "ref": "0.1.1", - "repo": "tui", - "type": "github" - } - }, "pre-commit-hooks": { "inputs": { - "flake-compat": "flake-compat_3", + "flake-compat": "flake-compat", "gitignore": "gitignore", "nixpkgs": [ "nixpkgs" @@ -603,152 +142,10 @@ "inputs": { "devshell": "devshell", "flake-parts": "flake-parts", + "lib-net": "lib-net", "nixpkgs": "nixpkgs", - "nixt": "nixt", "pre-commit-hooks": "pre-commit-hooks" } - }, - "rust-analyzer-src": { - "flake": false, - "locked": { - "lastModified": 1677221702, - "narHash": "sha256-1M+58rC4eTCWNmmX0hQVZP20t3tfYNunl9D/PrGUyGE=", - "owner": "rust-lang", - "repo": "rust-analyzer", - "rev": "f5401f620699b26ed9d47a1d2e838143a18dbe3b", - "type": "github" - }, - "original": { - "owner": "rust-lang", - "ref": "nightly", - "repo": "rust-analyzer", - "type": "github" - } - }, - "rust-overlay": { - "inputs": { - "flake-utils": [ - "nixt", - "std", - "paisano-mdbook-preprocessor", - "crane", - "flake-utils" - ], - "nixpkgs": [ - "nixt", - "std", - "paisano-mdbook-preprocessor", - "crane", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1675391458, - "narHash": "sha256-ukDKZw922BnK5ohL9LhwtaDAdCsJL7L6ScNEyF1lO9w=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "383a4acfd11d778d5c2efcf28376cbd845eeaedf", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" - } - }, - "std": { - "inputs": { - "arion": [ - "nixt", - "std", - "blank" - ], - "blank": "blank", - "devshell": "devshell_2", - "dmerge": "dmerge", - "flake-utils": "flake-utils", - "incl": "incl", - "makes": [ - "nixt", - "std", - "blank" - ], - "microvm": [ - "nixt", - "std", - "blank" - ], - "n2c": "n2c", - "nixago": "nixago", - "nixpkgs": [ - "nixt", - "nixpkgs" - ], - "paisano": "paisano", - "paisano-mdbook-preprocessor": "paisano-mdbook-preprocessor", - "paisano-tui": "paisano-tui", - "yants": "yants" - }, - "locked": { - "lastModified": 1684180498, - "narHash": "sha256-kA58ms4yunOVPhe3r7V0IIKeWUV+vl4r2GTcfFfYW5o=", - "owner": "divnix", - "repo": "std", - "rev": "45b431ae09df98e046bcc8271aa209bdfc87444d", - "type": "github" - }, - "original": { - "owner": "divnix", - "repo": "std", - "type": "github" - } - }, - "std-data-collection": { - "inputs": { - "nixpkgs": [ - "nixt", - "nixpkgs" - ], - "std": [ - "nixt", - "std" - ] - }, - "locked": { - "lastModified": 1676163535, - "narHash": "sha256-xofkWLBqU4zj5vzJhWor2Z9CyPGKt7UGkTchsCT48Po=", - "owner": "divnix", - "repo": "std-data-collection", - "rev": "f713d81a6197e1b0854fb201cc7acde5ef9e93d4", - "type": "github" - }, - "original": { - "owner": "divnix", - "repo": "std-data-collection", - "type": "github" - } - }, - "yants": { - "inputs": { - "nixpkgs": [ - "nixt", - "std", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1667096281, - "narHash": "sha256-wRRec6ze0gJHmGn6m57/zhz/Kdvp9HS4Nl5fkQ+uIuA=", - "owner": "divnix", - "repo": "yants", - "rev": "d18f356ec25cb94dc9c275870c3a7927a10f8c3c", - "type": "github" - }, - "original": { - "owner": "divnix", - "repo": "yants", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 6d78bad..744f523 100644 --- a/flake.nix +++ b/flake.nix @@ -9,16 +9,17 @@ flake-parts.url = "github:hercules-ci/flake-parts"; + lib-net = { + url = "https://gist.github.com/duairc/5c9bb3c922e5d501a1edb9e7b3b845ba/archive/3885f7cd9ed0a746a9d675da6f265d41e9fd6704.tar.gz"; + flake = false; + }; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; pre-commit-hooks = { url = "github:cachix/pre-commit-hooks.nix"; inputs.nixpkgs.follows = "nixpkgs"; }; - nixt = { - url = "github:nix-community/nixt"; - inputs.nixpkgs.follows = "nixpkgs"; - }; }; outputs = @@ -32,18 +33,6 @@ "x86_64-linux" "aarch64-linux" ]; - flake.__nixt = inputs.nixt.lib.grow { - blocks = import ./tests { - inherit (inputs) nixt; - pkgs = import inputs.nixpkgs { - system = "x86_64-linux"; - config.allowUnfree = true; - overlays = [ - self.overlays.default - ]; - }; - }; - }; flake.modules = { flake = { @@ -92,10 +81,6 @@ package = statix; help = "Lint nix code"; } - { - package = inputs.nixt.packages.${system}.default; - help = "Lint nix code"; - } { package = deadnix; help = "Find unused expressions in nix code"; diff --git a/lib/misc.nix b/lib/misc.nix index dd0fbcc..70d667b 100644 --- a/lib/misc.nix +++ b/lib/misc.nix @@ -1,40 +1,43 @@ -_inputs: final: prev: -let - inherit (prev.lib) +_inputs: _final: prev: let + inherit + (prev.lib) filter foldl' genAttrs + genList mergeAttrs mkMerge stringToCharacters substring unique ; - inherit (final.lib) - bit - ; # Counts how often each element occurrs in xs. # Elements must be strings. - countOccurrences = foldl' (acc: x: acc // { ${x} = (acc.${x} or 0) + 1; }) { }; + countOccurrences = + foldl' + (acc: x: acc // {${x} = (acc.${x} or 0) + 1;}) + {}; # Returns all elements in xs that occur at least twice - duplicates = - xs: - let - occurrences = countOccurrences xs; - in + duplicates = xs: let + occurrences = countOccurrences xs; + in unique (filter (x: occurrences.${x} > 1) xs); # Concatenates all given attrsets as if calling a // b in order. - concatAttrs = foldl' mergeAttrs { }; + concatAttrs = foldl' mergeAttrs {}; # True if the path or string starts with / isAbsolutePath = x: substring 0 1 x == "/"; # Merges all given attributes from the given attrsets using mkMerge. # Useful to merge several top-level configs in a module. - mergeToplevelConfigs = keys: attrs: genAttrs keys (attr: mkMerge (map (x: x.${attr} or { }) attrs)); + mergeToplevelConfigs = keys: attrs: + genAttrs keys (attr: mkMerge (map (x: x.${attr} or {}) attrs)); + + # Calculates base^exp, but careful, this overflows for results > 2^62 + pow = base: exp: foldl' (a: x: x * a) 1 (genList (_: base) exp); hexLiteralValues = { "0" = 0; @@ -63,17 +66,19 @@ let # Converts the given hex string to an integer. Only reliable for inputs in [0, 2^63), # after that the sign bit will overflow. - hexToDec = v: foldl' (acc: x: (bit.left acc 4) + hexLiteralValues.${x}) 0 (stringToCharacters v); -in -{ - lib = prev.lib // { - inherit - hexToDec - concatAttrs - countOccurrences - duplicates - isAbsolutePath - mergeToplevelConfigs - ; - }; + hexToDec = v: foldl' (acc: x: acc * 16 + hexLiteralValues.${x}) 0 (stringToCharacters v); +in { + lib = + prev.lib + // { + inherit + concatAttrs + countOccurrences + duplicates + hexToDec + isAbsolutePath + mergeToplevelConfigs + pow + ; + }; } diff --git a/lib/net.nix b/lib/net.nix index 41ee4f1..3713f09 100644 --- a/lib/net.nix +++ b/lib/net.nix @@ -1,6 +1,6 @@ -inputs: _final: prev: -let - inherit (prev.lib) +inputs: _final: prev: let + inherit + (prev.lib) all any assertMsg @@ -22,29 +22,24 @@ let ; # From misc.nix - inherit (prev.lib) + inherit + (prev.lib) hexToDec + pow ; # IP address math library # https://gist.github.com/duairc/5c9bb3c922e5d501a1edb9e7b3b845ba # Plus some extensions by us libNet = - (import ./netu.nix { + (import "${inputs.lib-net}/net.nix" { inherit (inputs.nixpkgs) lib; - }).lib; -in -{ + }) + .lib + .net; +in { lib = recursiveUpdate prev.lib { - inherit (libNet) - arithmetic - typechecks - bit - implementations - parsers - ; - - net = recursiveUpdate (removeAttrs libNet.net [ "types" ]) { + net = recursiveUpdate (removeAttrs libNet ["types"]) { cidr = rec { # host :: (ip | mac | integer) -> cidr -> ip # @@ -63,17 +58,11 @@ in # "192.168.1.0" # > net.cidr.host (-257) "192.168.1.0/24" # - host = - i: n: - let - cap = libNet.net.cidr.capacity n; - intCheck = builtins.isInt i -> (i >= (-cap) && i < cap); - ipCheck = libNet.net.types.ip.check i -> ((libNet.net.types.ip-in n).check result); - - result = libNet.net.cidr.host i n; - in - assert assertMsg (ipCheck && intCheck) "The host ${toString i} lies outside of ${n}"; - result; + host = i: n: let + cap = libNet.cidr.capacity n; + in + assert assertMsg (i >= (-cap) && i < cap) "The host ${toString i} lies outside of ${n}"; + libNet.cidr.host i n; # hostCidr :: (ip | mac | integer) -> cidr -> cidr # # Returns the nth host in the given cidr range (like cidr.host) @@ -83,7 +72,7 @@ in # # > net.cidr.hostCidr 2 "192.168.1.0/24" # "192.168.1.2/24" - hostCidr = n: x: "${libNet.net.cidr.host n x}/${toString (libNet.net.cidr.length x)}"; + hostCidr = n: x: "${libNet.cidr.host n x}/${toString (libNet.cidr.length x)}"; # ip :: (cidr | ip) -> ip # # Returns just the ip part of the cidr. @@ -104,7 +93,7 @@ in # # > net.cidr.canonicalize "192.168.1.100/24" # "192.168.1.0/24" - canonicalize = x: libNet.net.cidr.make (libNet.net.cidr.length x) (ip x); + canonicalize = x: libNet.cidr.make (libNet.cidr.length x) (ip x); # mergev4 :: [cidrv4 | ipv4] -> (cidrv4 | null) # # Returns the smallest cidr network that includes all given networks. @@ -114,30 +103,37 @@ in # # > net.cidr.mergev4 ["192.168.1.1/24" "192.168.6.1/32"] # "192.168.0.0/21" - mergev4 = - addrs_: - let - # Append /32 if necessary - addrs = map (x: if hasInfix "/" x then x else "${x}/32") addrs_; - # The smallest occurring length is the first we need to start checking, since - # any greater cidr length represents a smaller address range which - # wouldn't contain all of the original addresses. - startLength = foldl' min 32 (map libNet.net.cidr.length addrs); - possibleLengths = reverseList (range 0 startLength); - # The first ip address will be "expanded" in cidr length until it covers all other - # used addresses. - firstIp = ip (head addrs); - # Return the first (i.e. greatest length -> smallest prefix) cidr length - # in the list that covers all used addresses - bestLength = head ( - filter - # All given addresses must be contained by the generated address. - (len: all (x: libNet.net.cidr.contains (ip x) (libNet.net.cidr.make len firstIp)) addrs) - possibleLengths - ); - in + mergev4 = addrs_: let + # Append /32 if necessary + addrs = map (x: + if hasInfix "/" x + then x + else "${x}/32") + addrs_; + # The smallest occurring length is the first we need to start checking, since + # any greater cidr length represents a smaller address range which + # wouldn't contain all of the original addresses. + startLength = foldl' min 32 (map libNet.cidr.length addrs); + possibleLengths = reverseList (range 0 startLength); + # The first ip address will be "expanded" in cidr length until it covers all other + # used addresses. + firstIp = ip (head addrs); + # Return the first (i.e. greatest length -> smallest prefix) cidr length + # in the list that covers all used addresses + bestLength = head (filter + # All given addresses must be contained by the generated address. + (len: + all (x: + libNet.cidr.contains + (ip x) + (libNet.cidr.make len firstIp)) + addrs) + possibleLengths); + in assert assertMsg (!any (hasInfix ":") addrs) "mergev4 cannot operate on ipv6 addresses"; - if addrs == [ ] then null else libNet.net.cidr.make bestLength firstIp; + if addrs == [] + then null + else libNet.cidr.make bestLength firstIp; # mergev6 :: [cidrv6 | ipv6] -> (cidrv6 | null) # # Returns the smallest cidr network that includes all given networks. @@ -147,44 +143,48 @@ in # # > net.cidr.mergev6 ["fd00:dead:cafe::/64" "fd00:fd12:3456:7890::/56"] # "fd00:c000::/18" - mergev6 = - addrs_: - let - # Append /128 if necessary - addrs = map (x: if hasInfix "/" x then x else "${x}/128") addrs_; - # The smallest occurring length is the first we need to start checking, since - # any greater cidr length represents a smaller address range which - # wouldn't contain all of the original addresses. - startLength = foldl' min 128 (map libNet.net.cidr.length addrs); - possibleLengths = reverseList (range 0 startLength); - # The first ip address will be "expanded" in cidr length until it covers all other - # used addresses. - firstIp = ip (head addrs); - # Return the first (i.e. greatest length -> smallest prefix) cidr length - # in the list that covers all used addresses - bestLength = head ( - filter - # All given addresses must be contained by the generated address. - (len: all (x: libNet.net.cidr.contains (ip x) (libNet.net.cidr.make len firstIp)) addrs) - possibleLengths - ); - in + mergev6 = addrs_: let + # Append /128 if necessary + addrs = map (x: + if hasInfix "/" x + then x + else "${x}/128") + addrs_; + # The smallest occurring length is the first we need to start checking, since + # any greater cidr length represents a smaller address range which + # wouldn't contain all of the original addresses. + startLength = foldl' min 128 (map libNet.cidr.length addrs); + possibleLengths = reverseList (range 0 startLength); + # The first ip address will be "expanded" in cidr length until it covers all other + # used addresses. + firstIp = ip (head addrs); + # Return the first (i.e. greatest length -> smallest prefix) cidr length + # in the list that covers all used addresses + bestLength = head (filter + # All given addresses must be contained by the generated address. + (len: + all (x: + libNet.cidr.contains + (ip x) + (libNet.cidr.make len firstIp)) + addrs) + possibleLengths); + in assert assertMsg (all (hasInfix ":") addrs) "mergev6 cannot operate on ipv4 addresses"; - if addrs == [ ] then null else libNet.net.cidr.make bestLength firstIp; + if addrs == [] + then null + else libNet.cidr.make bestLength firstIp; # merge :: [cidr] -> { cidrv4 = (cidrv4 | null); cidrv6 = (cidrv4 | null); } # # Returns the smallest cidr network that includes all given networks, # but yields two separate result for all given ipv4 and ipv6 addresses. # Equivalent to calling mergev4 and mergev6 on a partition individually. - merge = - addrs: - let - v4_and_v6 = partition (hasInfix ":") addrs; - in - { - cidrv4 = mergev4 v4_and_v6.wrong; - cidrv6 = mergev6 v4_and_v6.right; - }; + merge = addrs: let + v4_and_v6 = partition (hasInfix ":") addrs; + in { + cidrv4 = mergev4 v4_and_v6.wrong; + cidrv6 = mergev6 v4_and_v6.right; + }; # assignIps :: cidr -> [int | ip] -> [string] -> [ip] # # Assigns a semi-stable ip address from the given cidr network to each hostname. @@ -203,76 +203,68 @@ in # # > net.cidr.assignIps "192.168.100.1/24" [202 "192.168.100.74"] ["a" "b" "c"] # { a = "192.168.100.203"; b = "192.168.100.75"; c = "192.168.100.226"; } - assignIps = - net: reserved: hosts: - let - cidrSize = libNet.net.cidr.size net; - capacity = libNet.net.cidr.capacity net; - # The base address of the network. Used to convert ip-based reservations to offsets - baseAddr = host 0 net; - # Reserve some values for the network, host and broadcast address. - # The network and broadcast address should never be used, and we - # want to reserve the host address for the host. We also convert - # any ips to offsets here. - init = unique ( - [ - 0 - (capacity - 1) - ] - ++ flip map reserved (x: if builtins.typeOf x == "int" then x else -(libNet.net.ip.diff baseAddr x)) - ); - nHosts = builtins.length hosts; - nInit = builtins.length init; - # Pre-sort all hosts, to ensure ordering invariance - sortedHosts = - warnIf ((nInit + nHosts) > 0.3 * capacity) - "assignIps: hash stability may be degraded since utilization is >30%" - (builtins.sort builtins.lessThan hosts); - # Generates a hash (i.e. offset value) for a given hostname - hashElem = - x: - builtins.bitAnd (capacity - 1) ( - hexToDec (builtins.substring 0 16 (builtins.hashString "sha256" x)) - ); - # Do linear probing. Returns the first unused value at or after the given value. - probe = - avoid: value: - if - elem value avoid - # TODO lib.mod - # Poor man's modulo, because nix has no modulo. Luckily we operate on a residue - # class of x modulo 2^n, so we can use bitAnd instead. - then - probe avoid (builtins.bitAnd (capacity - 1) (value + 1)) - else - value; - # Hash a new element and avoid assigning any existing values. - assignOne = - { - assigned, - used, - }: - x: - let - value = probe used (hashElem x); - in - { - assigned = assigned // { - ${x} = host value net; - }; - used = [ value ] ++ used; + assignIps = net: reserved: hosts: let + cidrSize = libNet.cidr.size net; + capacity = libNet.cidr.capacity net; + # The base address of the network. Used to convert ip-based reservations to offsets + baseAddr = host 0 net; + # Reserve some values for the network, host and broadcast address. + # The network and broadcast address should never be used, and we + # want to reserve the host address for the host. We also convert + # any ips to offsets here. + init = unique ( + [0 (capacity - 1)] + ++ flip map reserved (x: + if builtins.typeOf x == "int" + then x + else -(libNet.ip.diff baseAddr x)) + ); + nHosts = builtins.length hosts; + nInit = builtins.length init; + # Pre-sort all hosts, to ensure ordering invariance + sortedHosts = + warnIf + ((nInit + nHosts) > 0.3 * capacity) + "assignIps: hash stability may be degraded since utilization is >30%" + (builtins.sort builtins.lessThan hosts); + # Generates a hash (i.e. offset value) for a given hostname + hashElem = x: + builtins.bitAnd (capacity - 1) + (hexToDec (builtins.substring 0 16 (builtins.hashString "sha256" x))); + # Do linear probing. Returns the first unused value at or after the given value. + probe = avoid: value: + if elem value avoid + # TODO lib.mod + # Poor man's modulo, because nix has no modulo. Luckily we operate on a residue + # class of x modulo 2^n, so we can use bitAnd instead. + then probe avoid (builtins.bitAnd (capacity - 1) (value + 1)) + else value; + # Hash a new element and avoid assigning any existing values. + assignOne = { + assigned, + used, + }: x: let + value = probe used (hashElem x); + in { + assigned = + assigned + // { + ${x} = host value net; }; - in - assert assertMsg ( - cidrSize >= 2 && cidrSize <= 62 - ) "assignIps: cidrSize=${toString cidrSize} is not in [2, 62]."; + used = [value] ++ used; + }; + in + assert assertMsg (cidrSize >= 2 && cidrSize <= 62) + "assignIps: cidrSize=${toString cidrSize} is not in [2, 62]."; assert assertMsg (nHosts <= capacity - nInit) - "assignIps: number of hosts (${toString nHosts}) must be <= capacity (${toString capacity}) - reserved (${toString nInit})"; + "assignIps: number of hosts (${toString nHosts}) must be <= capacity (${toString capacity}) - reserved (${toString nInit})"; # Assign an ip in the subnet to each element, in order - (foldl' assignOne { - assigned = { }; - used = init; - } sortedHosts).assigned; + (foldl' assignOne { + assigned = {}; + used = init; + } + sortedHosts) + .assigned; }; ip = rec { # Checks whether the given address (with or without cidr notation) is an ipv4 address. @@ -283,14 +275,11 @@ in mac = { # Adds offset to the given base address and ensures the result is in # a locally administered range by replacing the second nibble with a 2. - addPrivate = - base: offset: - let - added = libNet.net.mac.add base offset; - pre = substring 0 1 added; - suf = substring 2 (-1) added; - in - "${pre}2${suf}"; + addPrivate = base: offset: let + added = libNet.mac.add base offset; + pre = substring 0 1 added; + suf = substring 2 (-1) added; + in "${pre}2${suf}"; # assignMacs :: mac (base) -> int (size) -> [int | mac] (reserved) -> [string] (hosts) -> [mac] # # Assigns a semi-stable MAC address starting in [base, base + 2^size) to each hostname. @@ -308,66 +297,65 @@ in # # > net.mac.assignMacs "11:22:33:00:00:00" 24 ["11:22:33:1b:bd:ca"] ["a" "b" "c"] # { a = "11:22:33:1b:bd:cb"; b = "11:22:33:39:59:4a"; c = "11:22:33:50:7a:e2"; } - assignMacs = - base: size: reserved: hosts: - let - capacity = libNet.bit.left 1 size; - baseAsInt = libNet.net.mac.diff base "00:00:00:00:00:00"; - init = unique ( - flip map reserved (x: if builtins.typeOf x == "int" then x else libNet.net.mac.diff x base) - ); - nHosts = builtins.length hosts; - nInit = builtins.length init; - # Pre-sort all hosts, to ensure ordering invariance - sortedHosts = - warnIf ((nInit + nHosts) > 0.3 * capacity) - "assignMacs: hash stability may be degraded since utilization is >30%" - (builtins.sort builtins.lessThan hosts); - # Generates a hash (i.e. offset value) for a given hostname - hashElem = - x: builtins.bitAnd (capacity - 1) (hexToDec (substring 0 16 (builtins.hashString "sha256" x))); - # Do linear probing. Returns the first unused value at or after the given value. - probe = - avoid: value: - if - elem value avoid - # TODO lib.mod - # Poor man's modulo, because nix has no modulo. Luckily we operate on a residue - # class of x modulo 2^n, so we can use bitAnd instead. - then - probe avoid (builtins.bitAnd (capacity - 1) (value + 1)) - else - value; - # Hash a new element and avoid assigning any existing values. - assignOne = - { - assigned, - used, - }: - x: - let - value = probe used (hashElem x); - in - { - assigned = assigned // { - ${x} = libNet.net.mac.add value base; - }; - used = [ value ] ++ used; + assignMacs = base: size: reserved: hosts: let + capacity = pow 2 size; + baseAsInt = libNet.mac.diff base "00:00:00:00:00:00"; + init = unique ( + flip map reserved (x: + if builtins.typeOf x == "int" + then x + else libNet.mac.diff x base) + ); + nHosts = builtins.length hosts; + nInit = builtins.length init; + # Pre-sort all hosts, to ensure ordering invariance + sortedHosts = + warnIf + ((nInit + nHosts) > 0.3 * capacity) + "assignMacs: hash stability may be degraded since utilization is >30%" + (builtins.sort builtins.lessThan hosts); + # Generates a hash (i.e. offset value) for a given hostname + hashElem = x: + builtins.bitAnd (capacity - 1) + (hexToDec (substring 0 16 (builtins.hashString "sha256" x))); + # Do linear probing. Returns the first unused value at or after the given value. + probe = avoid: value: + if elem value avoid + # TODO lib.mod + # Poor man's modulo, because nix has no modulo. Luckily we operate on a residue + # class of x modulo 2^n, so we can use bitAnd instead. + then probe avoid (builtins.bitAnd (capacity - 1) (value + 1)) + else value; + # Hash a new element and avoid assigning any existing values. + assignOne = { + assigned, + used, + }: x: let + value = probe used (hashElem x); + in { + assigned = + assigned + // { + ${x} = libNet.mac.add value base; }; - in - assert assertMsg (size >= 2 && size <= 62) "assignMacs: size=${toString size} is not in [2, 62]."; - assert assertMsg ( - builtins.bitAnd (capacity - 1) baseAsInt == 0 - ) "assignMacs: the size=${toString size} least significant bits of the base mac address must be 0."; + used = [value] ++ used; + }; + in + assert assertMsg (size >= 2 && size <= 62) + "assignMacs: size=${toString size} is not in [2, 62]."; + assert assertMsg (builtins.bitAnd (capacity - 1) baseAsInt == 0) + "assignMacs: the size=${toString size} least significant bits of the base mac address must be 0."; assert assertMsg (nHosts <= capacity - nInit) - "assignMacs: number of hosts (${toString nHosts}) must be <= capacity (${toString capacity}) - reserved (${toString nInit})"; + "assignMacs: number of hosts (${toString nHosts}) must be <= capacity (${toString capacity}) - reserved (${toString nInit})"; # Assign an ip in the subnet to each element, in order - (foldl' assignOne { - assigned = { }; - used = init; - } sortedHosts).assigned; + (foldl' assignOne { + assigned = {}; + used = init; + } + sortedHosts) + .assigned; }; }; - types.net = libNet.net.types; + types.net = libNet.types; }; } diff --git a/lib/netu.nix b/lib/netu.nix deleted file mode 100644 index cd9d8e2..0000000 --- a/lib/netu.nix +++ /dev/null @@ -1,1349 +0,0 @@ -{ - lib ? null, - ... -}: - -let - - net = - { - ip = { - - # add :: (ip | mac | integer) -> ip -> ip - # - # Examples: - # - # Adding integer to IPv4: - # > net.ip.add 100 "10.0.0.1" - # "10.0.0.101" - # - # Adding IPv4 to IPv4: - # > net.ip.add "127.0.0.1" "10.0.0.1" - # "137.0.0.2" - # - # Adding IPv6 to IPv4: - # > net.ip.add "::cafe:beef" "10.0.0.1" - # "212.254.186.191" - # - # Adding MAC to IPv4 (overflows): - # > net.ip.add "fe:ed:fa:ce:f0:0d" "10.0.0.1" - # "4.206.240.14" - # - # Adding integer to IPv6: - # > net.ip.add 100 "dead:cafe:beef::" - # "dead:cafe:beef::64" - # - # Adding IPv4 to to IPv6: - # > net.ip.add "127.0.0.1" "dead:cafe:beef::" - # "dead:cafe:beef::7f00:1" - # - # Adding MAC to IPv6: - # > net.ip.add "fe:ed:fa:ce:f0:0d" "dead:cafe:beef::" - # "dead:cafe:beef::feed:face:f00d" - add = - delta: ip: - let - function = "net.ip.add"; - delta' = typechecks.numeric function "delta" delta; - ip' = typechecks.ip function "ip" ip; - in - builders.ip (implementations.ip.add delta' ip'); - - # diff :: ip -> ip -> (integer | ipv6) - # - # net.ip.diff is the reverse of net.ip.add: - # - # net.ip.diff (net.ip.add a b) a = b - # net.ip.diff (net.ip.add a b) b = a - # - # The difference between net.ip.diff and net.ip.subtract is that - # net.ip.diff will try its best to return an integer (falling back - # to an IPv6 if the result is too big to fit in an integer). This is - # useful if you have two hosts that you know are on the same network - # and you just want to calculate the offset between them — a result - # like "0.0.0.10" is not very useful (which is what you would get - # from net.ip.subtract). - diff = - minuend: subtrahend: - let - function = "net.ip.diff"; - minuend' = typechecks.ip function "minuend" minuend; - subtrahend' = typechecks.ip function "subtrahend" subtrahend; - result = implementations.ip.diff minuend' subtrahend'; - in - if result ? ipv6 then builders.ipv6 result else result; - - # subtract :: (ip | mac | integer) -> ip -> ip - # - # net.ip.subtract is also the reverse of net.ip.add: - # - # net.ip.subtract a (net.ip.add a b) = b - # net.ip.subtract b (net.ip.add a b) = a - # - # The difference between net.ip.subtract and net.ip.diff is that - # net.ip.subtract will always return the same type as its "ip" - # parameter. Its implementation takes the "delta" parameter, - # coerces it to be the same type as the "ip" paramter, negates it - # (using two's complement), and then adds it to "ip". - subtract = - delta: ip: - let - function = "net.ip.subtract"; - delta' = typechecks.numeric function "delta" delta; - ip' = typechecks.ip function "ip" ip; - in - builders.ip (implementations.ip.subtract delta' ip'); - }; - - mac = { - - # add :: (ip | mac | integer) -> mac -> mac - # - # Examples: - # - # Adding integer to MAC: - # > net.mac.add 100 "fe:ed:fa:ce:f0:0d" - # "fe:ed:fa:ce:f0:71" - # - # Adding IPv4 to MAC: - # > net.mac.add "127.0.0.1" "fe:ed:fa:ce:f0:0d" - # "fe:ee:79:ce:f0:0e" - # - # Adding IPv6 to MAC: - # > net.mac.add "::cafe:beef" "fe:ed:fa:ce:f0:0d" - # "fe:ee:c5:cd:aa:cb - # - # Adding MAC to MAC: - # > net.mac.add "fe:ed:fa:00:00:00" "00:00:00:ce:f0:0d" - # "fe:ed:fa:ce:f0:0d" - add = - delta: mac: - let - function = "net.mac.add"; - delta' = typechecks.numeric function "delta" delta; - mac' = typechecks.mac function "mac" mac; - in - builders.mac (arithmetic.add delta' mac'); - - # diff :: mac -> mac -> integer - # - # net.mac.diff is the reverse of net.mac.add: - # - # net.mac.diff (net.mac.add a b) a = b - # net.mac.diff (net.mac.add a b) b = a - # - # The difference between net.mac.diff and net.mac.subtract is that - # net.mac.diff will always return an integer. - diff = - minuend: subtrahend: - let - function = "net.mac.diff"; - minuend' = typechecks.mac function "minuend" minuend; - subtrahend' = typechecks.mac function "subtrahend" subtrahend; - in - arithmetic.diff minuend' subtrahend'; - - # subtract :: (ip | mac | integer) -> mac -> mac - # - # net.mac.subtract is also the reverse of net.ip.add: - # - # net.mac.subtract a (net.mac.add a b) = b - # net.mac.subtract b (net.mac.add a b) = a - # - # The difference between net.mac.subtract and net.mac.diff is that - # net.mac.subtract will always return a MAC address. - subtract = - delta: mac: - let - function = "net.mac.subtract"; - delta' = typechecks.numeric function "delta" delta; - mac' = typechecks.mac function "mac" mac; - in - builders.mac (arithmetic.subtract delta' mac'); - }; - - cidr = { - # add :: (ip | mac | integer) -> cidr -> cidr - # - # > net.cidr.add 2 "127.0.0.0/8" - # "129.0.0.0/8" - # - # > net.cidr.add (-2) "127.0.0.0/8" - # "125.0.0.0/8" - add = - delta: cidr: - let - function = "net.cidr.add"; - delta' = typechecks.numeric function "delta" delta; - cidr' = typechecks.cidr function "cidr" cidr; - in - builders.cidr (implementations.cidr.add delta' cidr'); - - # child :: cidr -> cidr -> bool - # - # > net.cidr.child "10.10.10.0/24" "10.0.0.0/8" - # true - # - # > net.cidr.child "127.0.0.0/8" "10.0.0.0/8" - # false - child = - subcidr: cidr: - let - function = "net.cidr.child"; - subcidr' = typechecks.cidr function "subcidr" subcidr; - cidr' = typechecks.cidr function "cidr" cidr; - in - implementations.cidr.child subcidr' cidr'; - - # contains :: ip -> cidr -> bool - # - # > net.cidr.contains "127.0.0.1" "127.0.0.0/8" - # true - # - # > net.cidr.contains "127.0.0.1" "192.168.0.0/16" - # false - contains = - ip: cidr: - let - function = "net.cidr.contains"; - ip' = typechecks.ip function "ip" ip; - cidr' = typechecks.cidr function "cidr" cidr; - in - implementations.cidr.contains ip' cidr'; - - # capacity :: cidr -> integer - # - # > net.cidr.capacity "172.16.0.0/12" - # 1048576 - # - # > net.cidr.capacity "dead:cafe:beef::/96" - # 4294967296 - # - # > net.cidr.capacity "dead:cafe:beef::/48" (saturates to maxBound) - # 9223372036854775807 - capacity = - cidr: - let - function = "net.cidr.capacity"; - cidr' = typechecks.cidr function "cidr" cidr; - in - implementations.cidr.capacity cidr'; - - # host :: (ip | mac | integer) -> cidr -> ip - # - # > net.cidr.host 10000 "10.0.0.0/8" - # 10.0.39.16 - # - # > net.cidr.host 10000 "dead:cafe:beef::/64" - # "dead:cafe:beef::2710" - # - # net.cidr.host "127.0.0.1" "dead:cafe:beef::/48" - # > "dead:cafe:beef::7f00:1" - # - # Inpsired by: - # https://www.terraform.io/docs/configuration/functions/cidrhost.html - host = - hostnum: cidr: - let - function = "net.cidr.host"; - hostnum' = typechecks.numeric function "hostnum" hostnum; - cidr' = typechecks.cidr function "cidr" cidr; - in - builders.ip (implementations.cidr.host hostnum' cidr'); - - # length :: cidr -> integer - # - # > net.cidr.prefix "127.0.0.0/8" - # 8 - # - # > net.cidr.prefix "dead:cafe:beef::/48" - # 48 - length = - cidr: - let - function = "net.cidr.length"; - cidr' = typechecks.cidr function "cidr" cidr; - in - implementations.cidr.length cidr'; - - # make :: integer -> ip -> cidr - # - # > net.cidr.make 24 "192.168.0.150" - # "192.168.0.0/24" - # - # > net.cidr.make 40 "dead:cafe:beef::feed:face:f00d" - # "dead:cafe:be00::/40" - make = - length: base: - let - function = "net.cidr.make"; - length' = typechecks.int function "length" length; - base' = typechecks.ip function "base" base; - in - builders.cidr (implementations.cidr.make length' base'); - - # netmask :: cidr -> ip - # - # > net.cidr.netmask "192.168.0.0/24" - # "255.255.255.0" - # - # > net.cidr.netmask "dead:cafe:beef::/64" - # "ffff:ffff:ffff:ffff::" - netmask = - cidr: - let - function = "net.cidr.netmask"; - cidr' = typechecks.cidr function "cidr" cidr; - in - builders.ip (implementations.cidr.netmask cidr'); - - # size :: cidr -> integer - # - # > net.cidr.prefix "127.0.0.0/8" - # 24 - # - # > net.cidr.prefix "dead:cafe:beef::/48" - # 80 - size = - cidr: - let - function = "net.cidr.size"; - cidr' = typechecks.cidr function "cidr" cidr; - in - implementations.cidr.size cidr'; - - # subnet :: integer -> (ip | mac | integer) -> cidr -> cidr - # - # > net.cidr.subnet 4 2 "172.16.0.0/12" - # "172.18.0.0/16" - # - # > net.cidr.subnet 4 15 "10.1.2.0/24" - # "10.1.2.240/28" - # - # > net.cidr.subnet 16 162 "fd00:fd12:3456:7890::/56" - # "fd00:fd12:3456:7800:a200::/72" - # - # Inspired by: - # https://www.terraform.io/docs/configuration/functions/cidrsubnet.html - subnet = - length: netnum: cidr: - let - function = "net.cidr.subnet"; - length' = typechecks.int function "length" length; - netnum' = typechecks.numeric function "netnum" netnum; - cidr' = typechecks.cidr function "cidr" cidr; - in - builders.cidr (implementations.cidr.subnet length' netnum' cidr'); - - }; - } - // ( - if builtins.isNull lib then - { } - else - { - types = - let - - mkParsedOptionType = - { - name, - description, - parser, - builder, - }: - let - normalize = - def: - def - // { - value = builder (parser def.value); - }; - in - lib.mkOptionType { - inherit name description; - check = x: builtins.isString x && parser x != null; - merge = loc: defs: lib.mergeEqualOption loc (map normalize defs); - }; - - dependent-ip = - type: cidr: - let - cidrs = if builtins.isList cidr then cidr else [ cidr ]; - in - lib.types.addCheck type (i: lib.any (net.cidr.contains i) cidrs) - // { - description = type.description + " in ${builtins.concatStringsSep " or " cidrs}"; - }; - - dependent-cidr = - type: cidr: - let - cidrs = if builtins.isList cidr then cidr else [ cidr ]; - in - lib.types.addCheck type (i: lib.any (net.cidr.child i) cidrs) - // { - description = type.description + " in ${builtins.concatStringsSep " or " cidrs}"; - }; - - in - rec { - - ip = mkParsedOptionType { - name = "ip"; - description = "IPv4 or IPv6 address"; - parser = parsers.ip; - builder = builders.ip; - }; - - ip-in = dependent-ip ip; - - ipv4 = mkParsedOptionType { - name = "ipv4"; - description = "IPv4 address"; - parser = parsers.ipv4; - builder = builders.ipv4; - }; - - ipv4-in = dependent-ip ipv4; - - ipv6 = mkParsedOptionType { - name = "ipv6"; - description = "IPv6 address"; - parser = parsers.ipv6; - builder = builders.ipv6; - }; - - ipv6-in = dependent-ip ipv6; - - cidr = mkParsedOptionType { - name = "cidr"; - description = "IPv4 or IPv6 address range in CIDR notation"; - parser = parsers.cidr; - builder = builders.cidr; - }; - - cidr-in = dependent-cidr cidr; - - cidrv4 = mkParsedOptionType { - name = "cidrv4"; - description = "IPv4 address range in CIDR notation"; - parser = parsers.cidrv4; - builder = builders.cidrv4; - }; - - cidrv4-in = dependent-cidr cidrv4; - - cidrv6 = mkParsedOptionType { - name = "cidrv6"; - description = "IPv6 address range in CIDR notation"; - parser = parsers.cidrv6; - builder = builders.cidrv6; - }; - - cidrv6-in = dependent-cidr cidrv6; - - mac = mkParsedOptionType { - name = "mac"; - description = "MAC address"; - parser = parsers.mac; - builder = builders.mac; - }; - - }; - } - ); - - list = { - cons = a: b: [ a ] ++ b; - }; - - bit = - let - inherit (import ./shift.nix) left arithmeticRight logicalRight; - leftOrArithRight = a: if a > 0 then left a else arithmeticRight (-a); - arithRightOrLeft = a: if a > 0 then arithmeticRight a else left (-a); - - not = builtins.bitXor (-1); - - mask = n: builtins.bitAnd (left n 1 - 1); - in - { - inherit - left - arithmeticRight - logicalRight - not - mask - leftOrArithRight - arithRightOrLeft - ; - }; - - math = rec { - max = a: b: if a > b then a else b; - - min = a: b: if a < b then a else b; - - clamp = - a: b: c: - max a (min b c); - }; - - parsers = - let - - # fmap :: (a -> b) -> parser a -> parser b - fmap = f: ma: bind ma (a: pure (f a)); - - # pure :: a -> parser a - pure = a: string: { - leftovers = string; - result = a; - }; - - # liftA2 :: (a -> b -> c) -> parser a -> parser b -> parser c - liftA2 = - f: ma: mb: - bind ma (a: bind mb (b: pure (f a b))); - liftA3 = - f: a: b: - ap (liftA2 f a b); - liftA4 = - f: a: b: c: - ap (liftA3 f a b c); - liftA5 = - f: a: b: c: d: - ap (liftA4 f a b c d); - liftA6 = - f: a: b: c: d: e: - ap (liftA5 f a b c d e); - - # ap :: parser (a -> b) -> parser a -> parser b - ap = liftA2 (a: a); - - # then_ :: parser a -> parser b -> parser b - then_ = liftA2 (_: b: b); - - # empty :: parser a - empty = _: null; - - # alt :: parser a -> parser a -> parser a - alt = - left: right: string: - let - result = left string; - in - if builtins.isNull result then right string else result; - - # guard :: bool -> parser {} - guard = condition: if condition then pure { } else empty; - - # mfilter :: (a -> bool) -> parser a -> parser a - mfilter = f: parser: bind parser (a: then_ (guard (f a)) (pure a)); - - # some :: parser a -> parser [a] - some = v: liftA2 list.cons v (many v); - - # many :: parser a -> parser [a] - many = v: alt (some v) (pure [ ]); - - # bind :: parser a -> (a -> parser b) -> parser b - bind = - parser: f: string: - let - a = parser string; - in - if builtins.isNull a then null else f a.result a.leftovers; - - # run :: parser a -> string -> maybe a - run = - parser: string: - let - result = parser string; - in - if builtins.isNull result || result.leftovers != "" then null else result.result; - - next = - string: - if string == "" then - null - else - { - leftovers = builtins.substring 1 (-1) string; - result = builtins.substring 0 1 string; - }; - - # Count how many characters were consumed by a parser - count = - parser: string: - let - result = parser string; - in - if builtins.isNull result then - null - else - result - // { - result = { - inherit (result) result; - count = with result; builtins.stringLength string - builtins.stringLength leftovers; - }; - }; - - # Limit the parser to n characters at most - limit = n: parser: fmap (a: a.result) (mfilter (a: a.count <= n) (count parser)); - - # Ensure the parser consumes exactly n characters - exactly = n: parser: fmap (a: a.result) (mfilter (a: a.count == n) (count parser)); - - char = c: bind next (c': guard (c == c')); - - string = - css: - if css == "" then - pure { } - else - let - c = builtins.substring 0 1 css; - cs = builtins.substring 1 (-1) css; - in - then_ (char c) (string cs); - - digit = set: bind next (c: then_ (guard (builtins.hasAttr c set)) (pure (builtins.getAttr c set))); - - decimalDigits = { - "0" = 0; - "1" = 1; - "2" = 2; - "3" = 3; - "4" = 4; - "5" = 5; - "6" = 6; - "7" = 7; - "8" = 8; - "9" = 9; - }; - - hexadecimalDigits = decimalDigits // { - "a" = 10; - "b" = 11; - "c" = 12; - "d" = 13; - "e" = 14; - "f" = 15; - "A" = 10; - "B" = 11; - "C" = 12; - "D" = 13; - "E" = 14; - "F" = 15; - }; - - fromDecimalDigits = builtins.foldl' (a: c: a * 10 + c) 0; - fromHexadecimalDigits = builtins.foldl' (a: builtins.bitOr (bit.left 4 a)) 0; - - # disallow leading zeros - decimal = bind (digit decimalDigits) ( - n: - if n == 0 then - pure 0 - else - fmap (ns: fromDecimalDigits (list.cons n ns)) (many (digit decimalDigits)) - ); - - hexadecimal = fmap fromHexadecimalDigits (some (digit hexadecimalDigits)); - - ipv4 = - let - dot = char "."; - - octet = mfilter (n: n < 256) decimal; - - octet' = then_ dot octet; - - fromOctets = a: b: c: d: { - ipv4 = builtins.bitOr (bit.left 8 (builtins.bitOr (bit.left 8 (builtins.bitOr (bit.left 8 a) b)) c)) d; - }; - in - liftA4 fromOctets octet octet' octet' octet'; - - # This is more or less a literal translation of - # https://hackage.haskell.org/package/ip/docs/src/Net.IPv6.html#parser - ipv6 = - let - colon = char ":"; - - hextet = limit 4 hexadecimal; - - fromHextets = - hextets: - if builtins.length hextets != 8 then - empty - else - let - a = builtins.elemAt hextets 0; - b = builtins.elemAt hextets 1; - c = builtins.elemAt hextets 2; - d = builtins.elemAt hextets 3; - e = builtins.elemAt hextets 4; - f = builtins.elemAt hextets 5; - g = builtins.elemAt hextets 6; - h = builtins.elemAt hextets 7; - in - pure { - ipv6 = { - a = builtins.bitOr (bit.left 16 a) b; - b = builtins.bitOr (bit.left 16 c) d; - c = builtins.bitOr (bit.left 16 e) f; - d = builtins.bitOr (bit.left 16 g) h; - }; - }; - - ipv4' = fmap ( - address: - let - upper = bit.arithmeticRight 16 address.ipv4; - lower = bit.mask 16 address.ipv4; - in - [ - upper - lower - ] - ) ipv4; - - part = - n: - let - n' = n + 1; - hex = liftA2 list.cons hextet (then_ colon (alt (then_ colon (doubleColon n')) (part n'))); - in - if n == 7 then - fmap (a: [ a ]) hextet - else if n == 6 then - alt ipv4' hex - else - hex; - - doubleColon = - n: - bind (alt afterDoubleColon (pure [ ])) ( - rest: - let - missing = 8 - n - builtins.length rest; - in - if missing < 0 then empty else pure (builtins.genList (_: 0) missing ++ rest) - ); - - afterDoubleColon = alt ipv4' ( - liftA2 list.cons hextet (alt (then_ colon afterDoubleColon) (pure [ ])) - ); - - in - bind (alt (then_ (string "::") (doubleColon 0)) (part 0)) fromHextets; - - cidrv4 = liftA2 (base: length: implementations.cidr.make length base) ipv4 ( - then_ (char "/") (mfilter (n: n <= 32) decimal) - ); - - cidrv6 = liftA2 (base: length: implementations.cidr.make length base) ipv6 ( - then_ (char "/") (mfilter (n: n <= 128) decimal) - ); - - mac = - let - colon = char ":"; - - octet = exactly 2 hexadecimal; - - octet' = then_ colon octet; - - fromOctets = a: b: c: d: e: f: { - mac = builtins.bitOr (bit.left 8 (builtins.bitOr (bit.left 8 (builtins.bitOr (bit.left 8 (builtins.bitOr (bit.left 8 (builtins.bitOr (bit.left 8 a) b)) c)) d)) e)) f; - }; - in - liftA6 fromOctets octet octet' octet' octet' octet' octet'; - - in - { - ipv4 = run ipv4; - ipv6 = run ipv6; - ip = run (alt ipv4 ipv6); - cidrv4 = run cidrv4; - cidrv6 = run cidrv6; - cidr = run (alt cidrv4 cidrv6); - mac = run mac; - numeric = run (alt (alt ipv4 ipv6) mac); - }; - - builders = - let - - ipv4 = - address: - let - abcd = address.ipv4; - abc = bit.arithmeticRight 8 abcd; - ab = bit.arithmeticRight 8 abc; - a = bit.arithmeticRight 8 ab; - b = bit.mask 8 ab; - c = bit.mask 8 abc; - d = bit.mask 8 abcd; - in - builtins.concatStringsSep "." ( - map toString [ - a - b - c - d - ] - ); - - # This is more or less a literal translation of - # https://hackage.haskell.org/package/ip/docs/src/Net.IPv6.html#encode - ipv6 = - address: - let - - digits = "0123456789abcdef"; - - toHexString = - n: - let - rest = bit.arithmeticRight 4 n; - current = bit.mask 4 n; - prefix = if rest == 0 then "" else toHexString rest; - in - "${prefix}${builtins.substring current 1 digits}"; - - in - if (with address.ipv6; a == 0 && b == 0 && c == 0 && d > 65535) then - "::${ipv4 { ipv4 = address.ipv6.d; }}" - else if (with address.ipv6; a == 0 && b == 0 && c == 65535) then - "::ffff:${ipv4 { ipv4 = address.ipv6.d; }}" - else - let - - a = bit.arithmeticRight 16 address.ipv6.a; - b = bit.mask 16 address.ipv6.a; - c = bit.arithmeticRight 16 address.ipv6.b; - d = bit.mask 16 address.ipv6.b; - e = bit.arithmeticRight 16 address.ipv6.c; - f = bit.mask 16 address.ipv6.c; - g = bit.arithmeticRight 16 address.ipv6.d; - h = bit.mask 16 address.ipv6.d; - - hextets = [ - a - b - c - d - e - f - g - h - ]; - - # calculate the position and size of the longest sequence of - # zeroes within the list of hextets - longest = - let - go = - i: current: best: - if i < builtins.length hextets then - let - n = builtins.elemAt hextets i; - - current' = - if n == 0 then - if builtins.isNull current then - { - size = 1; - position = i; - } - else - current - // { - size = current.size + 1; - } - else - null; - - best' = - if n == 0 then - if builtins.isNull best then - current' - else if current'.size > best.size then - current' - else - best - else - best; - in - go (i + 1) current' best' - else - best; - in - go 0 null null; - - format = hextets: builtins.concatStringsSep ":" (map toHexString hextets); - in - if builtins.isNull longest then - format hextets - else - let - sublist = - i: length: xs: - map (builtins.elemAt xs) (builtins.genList (x: x + i) length); - - end = longest.position + longest.size; - - before = sublist 0 longest.position hextets; - - after = sublist end (builtins.length hextets - end) hextets; - in - "${format before}::${format after}"; - - ip = address: if address ? ipv4 then ipv4 address else ipv6 address; - - cidrv4 = cidr: "${ipv4 cidr.base}/${toString cidr.length}"; - - cidrv6 = cidr: "${ipv6 cidr.base}/${toString cidr.length}"; - - cidr = cidr: "${ip cidr.base}/${toString cidr.length}"; - - mac = - address: - let - digits = "0123456789abcdef"; - octet = - n: - let - upper = bit.arithmeticRight 4 n; - lower = bit.mask 4 n; - in - "${builtins.substring upper 1 digits}${builtins.substring lower 1 digits}"; - a = bit.mask 8 (bit.arithmeticRight 40 address.mac); - b = bit.mask 8 (bit.arithmeticRight 32 address.mac); - c = bit.mask 8 (bit.arithmeticRight 24 address.mac); - d = bit.mask 8 (bit.arithmeticRight 16 address.mac); - e = bit.mask 8 (bit.arithmeticRight 8 address.mac); - f = bit.mask 8 (bit.arithmeticRight 0 address.mac); - in - "${octet a}:${octet b}:${octet c}:${octet d}:${octet e}:${octet f}"; - - in - { - inherit - ipv4 - ipv6 - ip - cidrv4 - cidrv6 - cidr - mac - ; - }; - - arithmetic = rec { - # or :: (ip | mac | integer) -> (ip | mac | integer) -> (ip | mac | integer) - or = - a_: b: - let - a = coerce b a_; - in - if a ? ipv6 then - { - ipv6 = { - a = builtins.bitOr a.ipv6.a b.ipv6.a; - b = builtins.bitOr a.ipv6.b b.ipv6.b; - c = builtins.bitOr a.ipv6.c b.ipv6.c; - d = builtins.bitOr a.ipv6.d b.ipv6.d; - }; - } - else if a ? ipv4 then - { - ipv4 = builtins.bitOr a.ipv4 b.ipv4; - } - else if a ? mac then - { - mac = builtins.bitOr a.mac b.mac; - } - else - builtins.bitOr a b; - - # and :: (ip | mac | integer) -> (ip | mac | integer) -> (ip | mac | integer) - and = - a_: b: - let - a = coerce b a_; - in - if a ? ipv6 then - { - ipv6 = { - a = builtins.bitAnd a.ipv6.a b.ipv6.a; - b = builtins.bitAnd a.ipv6.b b.ipv6.b; - c = builtins.bitAnd a.ipv6.c b.ipv6.c; - d = builtins.bitAnd a.ipv6.d b.ipv6.d; - }; - } - else if a ? ipv4 then - { - ipv4 = builtins.bitAnd a.ipv4 b.ipv4; - } - else if a ? mac then - { - mac = builtins.bitAnd a.mac b.mac; - } - else - builtins.bitAnd a b; - - # not :: (ip | mac | integer) -> (ip | mac | integer) - not = - a: - if a ? ipv6 then - { - ipv6 = { - a = bit.mask 32 (bit.not a.ipv6.a); - b = bit.mask 32 (bit.not a.ipv6.b); - c = bit.mask 32 (bit.not a.ipv6.c); - d = bit.mask 32 (bit.not a.ipv6.d); - }; - } - else if a ? ipv4 then - { - ipv4 = bit.mask 32 (bit.not a.ipv4); - } - else if a ? mac then - { - mac = bit.mask 48 (bit.not a.mac); - } - else - bit.not a; - - # add :: (ip | mac | integer) -> (ip | mac | integer) -> (ip | mac | integer) - add = - let - split = a: { - fst = bit.mask 32 (bit.arithmeticRight 32 a); - snd = bit.mask 32 a; - }; - in - a_: b: - let - a = coerce b a_; - in - if a ? ipv6 then - let - a' = split (a.ipv6.a + b.ipv6.a + b'.fst); - b' = split (a.ipv6.b + b.ipv6.b + c'.fst); - c' = split (a.ipv6.c + b.ipv6.c + d'.fst); - d' = split (a.ipv6.d + b.ipv6.d); - in - { - ipv6 = { - a = a'.snd; - b = b'.snd; - c = c'.snd; - d = d'.snd; - }; - } - else if a ? ipv4 then - { - ipv4 = bit.mask 32 (a.ipv4 + b.ipv4); - } - else if a ? mac then - { - mac = bit.mask 48 (a.mac + b.mac); - } - else - a + b; - - # subtract :: (ip | mac | integer) -> (ip | mac | integer) -> (ip | mac | integer) - subtract = a: b: add (add 1 (not (coerce b a))) b; - - # diff :: (ip | mac | integer) -> (ip | mac | integer) -> (ipv6 | integer) - diff = - a: b: - let - toIPv6 = coerce { ipv6.a = 0; }; - result = (subtract b (toIPv6 a)).ipv6; - max32 = bit.left 32 1 - 1; - in - if - result.a == 0 && result.b == 0 && bit.arithmeticRight 31 result.c == 0 - || result.a == max32 && result.b == max32 && bit.arithmeticRight 31 result.c == 1 - then - builtins.bitOr (bit.left 32 result.c) result.d - else - { - ipv6 = result; - }; - - # left :: integer -> (ip | mac | integer) -> (ip | mac | integer) - left = i: right (-i); - - # right :: integer -> (ip | mac | integer) -> (ip | mac | integer) - right = - let - step = i: x: { - _1 = bit.mask 32 (bit.arithRightOrLeft (i + 96) x); - _2 = bit.mask 32 (bit.arithRightOrLeft (i + 64) x); - _3 = bit.mask 32 (bit.arithRightOrLeft (i + 32) x); - _4 = bit.mask 32 (bit.arithRightOrLeft i x); - _5 = bit.mask 32 (bit.arithRightOrLeft (i - 32) x); - _6 = bit.mask 32 (bit.arithRightOrLeft (i - 64) x); - _7 = bit.mask 32 (bit.arithRightOrLeft (i - 96) x); - }; - ors = builtins.foldl' builtins.bitOr 0; - in - i: x: - if x ? ipv6 then - let - a' = step i x.ipv6.a; - b' = step i x.ipv6.b; - c' = step i x.ipv6.c; - d' = step i x.ipv6.d; - in - { - ipv6 = { - a = ors [ - a'._4 - b'._3 - c'._2 - d'._1 - ]; - b = ors [ - a'._5 - b'._4 - c'._3 - d'._2 - ]; - c = ors [ - a'._6 - b'._5 - c'._4 - d'._3 - ]; - d = ors [ - a'._7 - b'._6 - c'._5 - d'._4 - ]; - }; - } - else if x ? ipv4 then - { - ipv4 = bit.mask 32 (bit.arithRightOrLeft i x.ipv4); - } - else if x ? mac then - { - mac = bit.mask 48 (bit.arithRightOrLeft i x.mac); - } - else - bit.arithRightOrLeft i x; - - # shadow :: integer -> (ip | mac | integer) -> (ip | mac | integer) - shadow = n: a: and (right n (left n (coerce a (-1)))) a; - - # coshadow :: integer -> (ip | mac | integer) -> (ip | mac | integer) - coshadow = n: a: and (not (right n (left n (coerce a (-1))))) a; - - # coerce target value - # coerce value to the type of target - # coerce :: A -> (ip | mac | integer) -> A - # where A :: (ip | mac | integer) - coerce = - target: value: - if target ? ipv6 then - if value ? ipv6 then - value - else if value ? ipv4 then - { - ipv6 = { - a = 0; - b = 0; - c = 0; - d = value.ipv4; - }; - } - else if value ? mac then - { - ipv6 = { - a = 0; - b = 0; - c = bit.arithmeticRight 32 value.mac; - d = bit.mask 32 value.mac; - }; - } - else - { - ipv6 = { - a = bit.mask 32 (bit.arithmeticRight 96 value); - b = bit.mask 32 (bit.arithmeticRight 64 value); - c = bit.mask 32 (bit.arithmeticRight 32 value); - d = bit.mask 32 value; - }; - } - else if target ? ipv4 then - if value ? ipv6 then - { - ipv4 = value.ipv6.d; - } - else if value ? ipv4 then - value - else if value ? mac then - { - ipv4 = bit.mask 32 value.mac; - } - else - { - ipv4 = bit.mask 32 value; - } - else if target ? mac then - if value ? ipv6 then - { - mac = builtins.bitOr (bit.left 32 (bit.mask 16 value.ipv6.c)) value.ipv6.d; - } - else if value ? ipv4 then - { - mac = value.ipv4; - } - else if value ? mac then - value - else - { - mac = bit.mask 48 value; - } - else if value ? ipv6 then - builtins.foldl' builtins.bitOr 0 [ - (bit.left 96 value.ipv6.a) - (bit.left 64 value.ipv6.b) - (bit.left 32 value.ipv6.c) - value.ipv6.d - ] - else - value.ipv4 or value.mac or value; - }; - - implementations = { - cidr = rec { - # add :: (ip | mac | integer) -> cidr -> cidr - add = - delta: cidr: - let - size' = size cidr; - in - { - base = arithmetic.left size' (arithmetic.add delta (arithmetic.arithRightOrLeft size' cidr.base)); - inherit (cidr) length; - }; - - # capacity :: cidr -> integer - capacity = - cidr: - let - size' = size cidr; - in - if size' > 62 then - 9223372036854775807 # maxBound to prevent overflow - else - bit.left size' 1; - - # child :: cidr -> cidr -> bool - child = subcidr: cidr: length subcidr > length cidr && contains (host 0 subcidr) cidr; - - # contains :: ip -> cidr -> bool - contains = ip: cidr: host 0 (make cidr.length ip) == host 0 cidr; - - # host :: (ip | mac | integer) -> cidr -> ip - host = - index: cidr: - let - index' = arithmetic.coerce cidr.base index; - in - arithmetic.or (arithmetic.shadow cidr.length index') cidr.base; - - # length :: cidr -> integer - length = cidr: cidr.length; - - # netmask :: cidr -> ip - netmask = cidr: arithmetic.coshadow cidr.length (arithmetic.coerce cidr.base (-1)); - - # size :: cidr -> integer - size = cidr: (if cidr.base ? ipv6 then 128 else 32) - cidr.length; - - # subnet :: integer -> (ip | mac | integer) -> cidr -> cidr - subnet = - length: index: cidr: - let - length' = cidr.length + length; - index' = arithmetic.coerce cidr.base index; - size = (if cidr.base ? ipv6 then 128 else 32) - length'; - in - make length' (host (arithmetic.left size index') cidr); - - # make :: integer -> ip -> cidr - make = - length: base: - let - length' = math.clamp 0 (if base ? ipv6 then 128 else 32) length; - in - { - base = arithmetic.coshadow length' base; - length = length'; - }; - }; - }; - - typechecks = - let - - fail = - description: function: argument: - builtins.throw "${function}: ${argument} parameter must be ${description}"; - - meta = - parser: description: function: argument: input: - let - error = fail description function argument; - in - if !builtins.isString input then - error - else - let - result = parser input; - in - if builtins.isNull result then error else result; - - in - { - int = - function: argument: input: - if builtins.isInt input then input else fail "an integer" function argument; - ip = meta parsers.ip "an IPv4 or IPv6 address"; - cidr = meta parsers.cidr "an IPv4 or IPv6 address range in CIDR notation"; - mac = meta parsers.mac "a MAC address"; - numeric = - function: argument: input: - if builtins.isInt input then - input - else - meta parsers.numeric "an integer or IPv4, IPv6 or MAC address" function argument input; - }; - -in - -{ - lib = { - inherit - arithmetic - net - typechecks - parsers - implementations - bit - ; - }; -} diff --git a/lib/shift.nix b/lib/shift.nix deleted file mode 100644 index 1e2576e..0000000 --- a/lib/shift.nix +++ /dev/null @@ -1,128 +0,0 @@ -let - # lut = [ - # 1 # 0 - # 2 # 1 - # 4 # 2 - # 8 # 3 - # 16 # 4 - # 32 # 5 - # 64 # 6 - # 128 # 7 - # 256 # 8 - # 512 # 9 - # 1024 # 10 - # 2048 # 11 - # 4096 # 12 - # 8192 # 13 - # 16384 # 14 - # 32768 # 15 - # 65536 # 16 - # 131072 # 17 - # 262144 # 18 - # 524288 # 19 - # 1048576 # 20 - # 2097152 # 21 - # 4194304 # 22 - # 8388608 # 23 - # 16777216 # 24 - # 33554432 # 25 - # 67108864 # 26 - # 134217728 # 27 - # 268435456 # 28 - # 536870912 # 29 - # 1073741824 # 30 - # 2147483648 # 31 - # 4294967296 # 32 - # 8589934592 # 33 - # 17179869184 # 34 - # 34359738368 # 35 - # 68719476736 # 36 - # 137438953472 # 37 - # 274877906944 # 38 - # 549755813888 # 39 - # 1099511627776 # 40 - # 2199023255552 # 41 - # 4398046511104 # 42 - # 8796093022208 # 43 - # 17592186044416 # 44 - # 35184372088832 # 45 - # 70368744177664 # 46 - # 140737488355328 # 47 - # 281474976710656 # 48 - # 562949953421312 # 49 - # 1125899906842624 # 50 - # 2251799813685248 # 51 - # 4503599627370496 # 52 - # 9007199254740992 # 53 - # 18014398509481984 # 54 - # 36028797018963968 # 55 - # 72057594037927936 # 56 - # 144115188075855872 # 57 - # 288230376151711744 # 58 - # 576460752303423488 # 59 - # 1152921504606846976 # 60 - # 2305843009213693952 # 61 - # 4611686018427387904 # 62 - # ]; - lut = builtins.foldl' (l: n: l ++ [ (2 * builtins.elemAt l n) ]) [ 1 ] (builtins.genList (x: x) 62); - intmin = (-9223372036854775807) - 1; - intmax = 9223372036854775807; - left = - a: b: - if a >= 64 then - # It's allowed to shift out all bits - 0 - else if a == 0 then - b - else if a < 0 then - throw "Inverse Left Shift not supported" - else - let - inv = 63 - a; - mask = if inv == 63 then intmax else (builtins.elemAt lut inv) - 1; - masked = builtins.bitAnd b mask; - checker = if inv == 63 then intmin else builtins.elemAt lut inv; - negate = (builtins.bitAnd b checker) != 0; - mult = if a == 63 then intmin else builtins.elemAt lut a; - result = masked * mult; - in - if !negate then result else intmin + result; - logicalRight = - a: b: - if a >= 64 then - 0 - else if a == 0 then - b - else if a < 0 then - throw "Inverse right Shift not supported" - else - let - masked = builtins.bitAnd b intmax; - negate = b < 0; - # Split division to prevent having to divide by a negative number for - # shifts of 63 bit - result = masked / 2 / (builtins.elemAt lut (a - 1)); - inv = 63 - a; - highest_bit = builtins.elemAt lut inv; - in - if !negate then result else result + highest_bit; - arithmeticRight = - a: b: - if a >= 64 then - if b < 0 then -1 else 0 - else if a == 0 then - b - else if a < 0 then - throw "Inverse right Shift not supported" - else - let - negate = b < 0; - mask = if a == 63 then intmax else (builtins.elemAt lut a) - 1; - round_down = negate && (builtins.bitAnd mask b != 0); - result = b / 2 / (builtins.elemAt lut (a - 1)); - in - if round_down then result - 1 else result; -in -{ - inherit left logicalRight arithmeticRight; -} diff --git a/modules/globals.nix b/modules/globals.nix index 073b3e7..f4d99fe 100644 --- a/modules/globals.nix +++ b/modules/globals.nix @@ -1,9 +1,18 @@ { lib, options, ... }: +let + inherit (lib) mkOption types; +in { - options._globalsDefs = lib.mkOption { - type = lib.types.unspecified; - default = options.globals.definitions; - readOnly = true; - internal = true; + options = { + globals = mkOption { + default = { }; + type = types.submodule { }; + }; + _globalsDefs = mkOption { + type = types.unspecified; + default = options.globals.definitions; + readOnly = true; + internal = true; + }; }; } diff --git a/modules/nginx.nix b/modules/nginx.nix index 5ce30f2..3625318 100644 --- a/modules/nginx.nix +++ b/modules/nginx.nix @@ -2,57 +2,52 @@ config, lib, ... -}: -let - inherit (lib) +}: let + inherit + (lib) mkBefore mkEnableOption mkIf mkOption types ; -in -{ +in { options.services.nginx = { recommendedSetup = mkEnableOption "recommended setup parameters."; recommendedSecurityHeaders = mkEnableOption "additional security headers by default in each location block. Can be overwritten in each location with `recommendedSecurityHeaders`."; virtualHosts = mkOption { - type = types.attrsOf ( - types.submodule { - options.locations = mkOption { - type = types.attrsOf ( - types.submodule (submod: { - options = { - recommendedSecurityHeaders = mkOption { - type = types.bool; - default = config.services.nginx.recommendedSecurityHeaders; - description = "Whether to add additional security headers to this location."; - }; + type = types.attrsOf (types.submodule { + options.locations = mkOption { + type = types.attrsOf (types.submodule (submod: { + options = { + recommendedSecurityHeaders = mkOption { + type = types.bool; + default = config.services.nginx.recommendedSecurityHeaders; + description = "Whether to add additional security headers to this location."; + }; - X-Frame-Options = mkOption { - type = types.str; - default = "DENY"; - description = "The value to use for X-Frame-Options"; - }; - }; - config = mkIf submod.config.recommendedSecurityHeaders { - extraConfig = mkBefore '' - # Enable HTTP Strict Transport Security (HSTS) - add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"; + X-Frame-Options = mkOption { + type = types.str; + default = "DENY"; + description = "The value to use for X-Frame-Options"; + }; + }; + config = mkIf submod.config.recommendedSecurityHeaders { + extraConfig = mkBefore '' + # Enable HTTP Strict Transport Security (HSTS) + add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"; - # Minimize information leaked to other domains - add_header Referrer-Policy "origin-when-cross-origin"; + # Minimize information leaked to other domains + add_header Referrer-Policy "origin-when-cross-origin"; - add_header X-XSS-Protection "1; mode=block"; - add_header X-Frame-Options "${submod.config.X-Frame-Options}"; - add_header X-Content-Type-Options "nosniff"; - ''; - }; - }) - ); - }; - } - ); + add_header X-XSS-Protection "1; mode=block"; + add_header X-Frame-Options "${submod.config.X-Frame-Options}"; + add_header X-Content-Type-Options "nosniff"; + ''; + }; + })); + }; + }); }; }; @@ -63,12 +58,7 @@ in group = "nginx"; }; - networking.firewall.allowedTCPPorts = [ - 80 - 443 - ]; - # QUIC - networking.firewall.allowedUDPPorts = [ 443 ]; + networking.firewall.allowedTCPPorts = [80 443]; # Sensible defaults for nginx services.nginx = { @@ -98,6 +88,7 @@ in '}'; error_log syslog:server=unix:/dev/log,nohostname; access_log syslog:server=unix:/dev/log,nohostname json_combined; + ssl_ecdh_curve secp384r1; ''; # Default host that rejects everything. diff --git a/modules/wireguard.nix b/modules/wireguard.nix index eedbdf3..59bd5ab 100644 --- a/modules/wireguard.nix +++ b/modules/wireguard.nix @@ -36,7 +36,7 @@ in flip mapAttrsToList memberWG ( networkName: networkCfg: let - assertionPrefix = "While evaluating the wireguard network ${networkName}:"; + assertionPrefix = "While evaluation the wireguard network ${networkName}:"; hostCfg = networkCfg.hosts.${config.node.name}; in [ diff --git a/modules/wireguardGlobals.nix b/modules/wireguardGlobals.nix index 1626cc2..d2d83d3 100644 --- a/modules/wireguardGlobals.nix +++ b/modules/wireguardGlobals.nix @@ -23,7 +23,7 @@ in options = { host = mkOption { type = types.str; - description = "The host name or IP address under which the server node is reachable from any client."; + description = "The host name or IP addresse for reaching the server node."; }; idFile = mkOption { type = types.nullOr types.path; @@ -61,9 +61,16 @@ in config.id = let inherit (wgConf) idFile; - idFromFile = if (idFile == null) then null else (importJSON idFile).${name} or null; in - lib.mkIf (idFromFile != null) idFromFile; + if (idFile == null) then + null + else + ( + let + conf = importJSON idFile; + in + conf.${name} or null + ); options = { server = mkOption { default = false; diff --git a/tests/default.nix b/tests/default.nix deleted file mode 100644 index a8520ce..0000000 --- a/tests/default.nix +++ /dev/null @@ -1,9 +0,0 @@ -{ - nixt, - pkgs, - ... -}: -[ - (import ./shift.nix { inherit pkgs nixt; }) - (import ./net.nix { inherit pkgs nixt; }) -] diff --git a/tests/net.nix b/tests/net.nix deleted file mode 100644 index 663c28d..0000000 --- a/tests/net.nix +++ /dev/null @@ -1,101 +0,0 @@ -{ - nixt, - pkgs, - ... -}: -let - inherit (nixt.lib) block describe it; - inherit (pkgs) lib; - expected = { - cidrv6 = { - empty = { - base = { - ipv6 = { - a = 0; - b = 0; - c = 0; - d = 0; - }; - }; - length = 0; - }; - base4 = { - base = { - ipv6 = { - a = 65536; - b = 0; - c = 0; - d = 0; - }; - }; - length = 4; - }; - }; - }; -in -block ./net.nix [ - (describe "cidrv6" [ - (it "child 1" (lib.net.cidr.child "1::/4" "0::/0")) - (it "child 2" (lib.net.cidr.child "1::/4" "::/0")) - (it "child 3" (!lib.net.cidr.child "::/0" "::/4")) - (it "child 4" (lib.net.cidr.child "1100::/8" "1000::/4")) - (it "child 5" (!lib.net.cidr.child "1100::/16" "1000::/8")) - (it "child 6" (lib.net.cidr.child "0:1::/24" "0:1::/8")) - - (it "typechecks 1" (lib.typechecks.cidr "" "" "::/0" == expected.cidrv6.empty)) - (it "typechecks 2" (lib.typechecks.cidr "" "" "0::/0" == expected.cidrv6.empty)) - (it "typechecks 3" (lib.typechecks.cidr "" "" "1::/4" == expected.cidrv6.empty // { length = 4; })) - - (it "impl child" (lib.implementations.cidr.child expected.cidrv6.base4 expected.cidrv6.empty)) - - (it "cidr length 0" (lib.implementations.cidr.length expected.cidrv6.empty == 0)) - (it "cidr length 4" (lib.implementations.cidr.length expected.cidrv6.base4 == 4)) - - (it "contains 4" ( - lib.implementations.cidr.contains expected.cidrv6.base4.base expected.cidrv6.empty - )) - - (it "host 4" (lib.implementations.cidr.host 0 expected.cidrv6.base4 == expected.cidrv6.base4.base)) - (it "host 0" (lib.implementations.cidr.host 0 expected.cidrv6.empty == expected.cidrv6.empty.base)) - - (it "make len 0" ( - lib.implementations.cidr.make 0 expected.cidrv6.base4.base == expected.cidrv6.empty - )) - (it "make base 4 len 0 length" ( - (lib.implementations.cidr.make 0 expected.cidrv6.base4.base).length == 0 - )) - (it "make base 4 len 0 base" ( - (lib.implementations.cidr.make 0 expected.cidrv6.base4.base).base == expected.cidrv6.empty.base - )) - ]) - (describe "cidrv4" [ - (it "child 1" (lib.net.cidr.child "10.10.10.0/24" "10.0.0.0/8")) - (it "child 2" (!lib.net.cidr.child "127.0.0.0/24" "10.0.0.0/8")) - ]) - (describe "cidr" [ - (it "host 255" (lib.net.cidr.host 255 "192.168.1.0/24" == "192.168.1.255")) - (it "host err" ((builtins.tryEval (lib.net.cidr.host 256 "192.168.1.0/24")).success == false)) - (it "host -1" (lib.net.cidr.host (-1) "192.168.1.0/24" == "192.168.1.255")) - (it "host -256" (lib.net.cidr.host (-256) "192.168.1.0/24" == "192.168.1.0")) - (it "host -err" ((builtins.tryEval (lib.net.cidr.host (-257) "192.168.1.0/24")).success == false)) - (it "host ip" (lib.net.cidr.host "0.0.0.1" "192.168.1.0/24" == "192.168.1.1")) - ]) - (describe "arithmetic" [ - (it "coshadow 1" ( - (lib.arithmetic.coshadow 0 expected.cidrv6.base4.base) == expected.cidrv6.empty.base - )) - (it "coerce 1" ( - (lib.arithmetic.coerce expected.cidrv6.base4.base (-1)) == { - ipv6 = { - a = 4294967295; - b = 4294967295; - c = 4294967295; - d = 4294967295; - }; - } - )) - ]) - (describe "bit" [ - (it "mask 32 " ((lib.bit.mask 32 (-1)) == 4294967295)) - ]) -] diff --git a/tests/shift.nix b/tests/shift.nix deleted file mode 100644 index f814f19..0000000 --- a/tests/shift.nix +++ /dev/null @@ -1,399 +0,0 @@ -{ - nixt, - pkgs, - ... -}: -let - inherit (nixt.lib) block describe it; - inherit (pkgs.lib.bit) left logicalRight arithmeticRight; -in -block ./shift.nix [ - (describe "" [ - (it "left shift 31065 << 63" (left 63 31065 == -9223372036854775807 - 1)) - (it "negative left shift 31065 << 63" (left 63 (-31065) == -9223372036854775807 - 1)) - (it "logical right shift 31065 >> 63" (logicalRight 63 31065 == 0)) - (it "negative logical right shift 31065 >> 63" (logicalRight 63 (-31065) == 1)) - (it "arithmetic right shift 31065 >> 63" (arithmeticRight 63 31065 == 0)) - (it "negative arithmetic right shift 31065 >> 63" (arithmeticRight 63 (-31065) == -1)) - (it "left shift 25624 << 62" (left 62 25624 == 0)) - (it "negative left shift 25624 << 62" (left 62 (-25624) == 0)) - (it "logical right shift 25624 >> 62" (logicalRight 62 25624 == 0)) - (it "negative logical right shift 25624 >> 62" (logicalRight 62 (-25624) == 3)) - (it "arithmetic right shift 25624 >> 62" (arithmeticRight 62 25624 == 0)) - (it "negative arithmetic right shift 25624 >> 62" (arithmeticRight 62 (-25624) == -1)) - (it "left shift 308 << 61" (left 61 308 == -9223372036854775807 - 1)) - (it "negative left shift 308 << 61" (left 61 (-308) == -9223372036854775807 - 1)) - (it "logical right shift 308 >> 61" (logicalRight 61 308 == 0)) - (it "negative logical right shift 308 >> 61" (logicalRight 61 (-308) == 7)) - (it "arithmetic right shift 308 >> 61" (arithmeticRight 61 308 == 0)) - (it "negative arithmetic right shift 308 >> 61" (arithmeticRight 61 (-308) == -1)) - (it "left shift 16712 << 60" (left 60 16712 == -9223372036854775807 - 1)) - (it "negative left shift 16712 << 60" (left 60 (-16712) == -9223372036854775807 - 1)) - (it "logical right shift 16712 >> 60" (logicalRight 60 16712 == 0)) - (it "negative logical right shift 16712 >> 60" (logicalRight 60 (-16712) == 15)) - (it "arithmetic right shift 16712 >> 60" (arithmeticRight 60 16712 == 0)) - (it "negative arithmetic right shift 16712 >> 60" (arithmeticRight 60 (-16712) == -1)) - (it "left shift 5852 << 59" (left 59 5852 == -2305843009213693952)) - (it "negative left shift 5852 << 59" (left 59 (-5852) == 2305843009213693952)) - (it "logical right shift 5852 >> 59" (logicalRight 59 5852 == 0)) - (it "negative logical right shift 5852 >> 59" (logicalRight 59 (-5852) == 31)) - (it "arithmetic right shift 5852 >> 59" (arithmeticRight 59 5852 == 0)) - (it "negative arithmetic right shift 5852 >> 59" (arithmeticRight 59 (-5852) == -1)) - (it "left shift 389 << 58" (left 58 389 == 1441151880758558720)) - (it "negative left shift 389 << 58" (left 58 (-389) == -1441151880758558720)) - (it "logical right shift 389 >> 58" (logicalRight 58 389 == 0)) - (it "negative logical right shift 389 >> 58" (logicalRight 58 (-389) == 63)) - (it "arithmetic right shift 389 >> 58" (arithmeticRight 58 389 == 0)) - (it "negative arithmetic right shift 389 >> 58" (arithmeticRight 58 (-389) == -1)) - (it "left shift 13663 << 57" (left 57 13663 == -4755801206503243776)) - (it "negative left shift 13663 << 57" (left 57 (-13663) == 4755801206503243776)) - (it "logical right shift 13663 >> 57" (logicalRight 57 13663 == 0)) - (it "negative logical right shift 13663 >> 57" (logicalRight 57 (-13663) == 127)) - (it "arithmetic right shift 13663 >> 57" (arithmeticRight 57 13663 == 0)) - (it "negative arithmetic right shift 13663 >> 57" (arithmeticRight 57 (-13663) == -1)) - (it "left shift 15349 << 56" (left 56 15349 == -792633534417207296)) - (it "negative left shift 15349 << 56" (left 56 (-15349) == 792633534417207296)) - (it "logical right shift 15349 >> 56" (logicalRight 56 15349 == 0)) - (it "negative logical right shift 15349 >> 56" (logicalRight 56 (-15349) == 255)) - (it "arithmetic right shift 15349 >> 56" (arithmeticRight 56 15349 == 0)) - (it "negative arithmetic right shift 15349 >> 56" (arithmeticRight 56 (-15349) == -1)) - (it "left shift 25817 << 55" (left 55 25817 == 7818248953115181056)) - (it "negative left shift 25817 << 55" (left 55 (-25817) == -7818248953115181056)) - (it "logical right shift 25817 >> 55" (logicalRight 55 25817 == 0)) - (it "negative logical right shift 25817 >> 55" (logicalRight 55 (-25817) == 511)) - (it "arithmetic right shift 25817 >> 55" (arithmeticRight 55 25817 == 0)) - (it "negative arithmetic right shift 25817 >> 55" (arithmeticRight 55 (-25817) == -1)) - (it "left shift 896 << 54" (left 54 896 == -2305843009213693952)) - (it "negative left shift 896 << 54" (left 54 (-896) == 2305843009213693952)) - (it "logical right shift 896 >> 54" (logicalRight 54 896 == 0)) - (it "negative logical right shift 896 >> 54" (logicalRight 54 (-896) == 1023)) - (it "arithmetic right shift 896 >> 54" (arithmeticRight 54 896 == 0)) - (it "negative arithmetic right shift 896 >> 54" (arithmeticRight 54 (-896) == -1)) - (it "left shift 14592 << 53" (left 53 14592 == 2305843009213693952)) - (it "negative left shift 14592 << 53" (left 53 (-14592) == -2305843009213693952)) - (it "logical right shift 14592 >> 53" (logicalRight 53 14592 == 0)) - (it "negative logical right shift 14592 >> 53" (logicalRight 53 (-14592) == 2047)) - (it "arithmetic right shift 14592 >> 53" (arithmeticRight 53 14592 == 0)) - (it "negative arithmetic right shift 14592 >> 53" (arithmeticRight 53 (-14592) == -1)) - (it "left shift 8533 << 52" (left 52 8533 == 1535727472933339136)) - (it "negative left shift 8533 << 52" (left 52 (-8533) == -1535727472933339136)) - (it "logical right shift 8533 >> 52" (logicalRight 52 8533 == 0)) - (it "negative logical right shift 8533 >> 52" (logicalRight 52 (-8533) == 4095)) - (it "arithmetic right shift 8533 >> 52" (arithmeticRight 52 8533 == 0)) - (it "negative arithmetic right shift 8533 >> 52" (arithmeticRight 52 (-8533) == -1)) - (it "left shift 30180 << 51" (left 51 30180 == -5827657917817421824)) - (it "negative left shift 30180 << 51" (left 51 (-30180) == 5827657917817421824)) - (it "logical right shift 30180 >> 51" (logicalRight 51 30180 == 0)) - (it "negative logical right shift 30180 >> 51" (logicalRight 51 (-30180) == 8191)) - (it "arithmetic right shift 30180 >> 51" (arithmeticRight 51 30180 == 0)) - (it "negative arithmetic right shift 30180 >> 51" (arithmeticRight 51 (-30180) == -1)) - (it "left shift 24903 << 50" (left 50 24903 == -8855202767317237760)) - (it "negative left shift 24903 << 50" (left 50 (-24903) == 8855202767317237760)) - (it "logical right shift 24903 >> 50" (logicalRight 50 24903 == 0)) - (it "negative logical right shift 24903 >> 50" (logicalRight 50 (-24903) == 16383)) - (it "arithmetic right shift 24903 >> 50" (arithmeticRight 50 24903 == 0)) - (it "negative arithmetic right shift 24903 >> 50" (arithmeticRight 50 (-24903) == -1)) - (it "left shift 14440 << 49" (left 49 14440 == 8128997327403745280)) - (it "negative left shift 14440 << 49" (left 49 (-14440) == -8128997327403745280)) - (it "logical right shift 14440 >> 49" (logicalRight 49 14440 == 0)) - (it "negative logical right shift 14440 >> 49" (logicalRight 49 (-14440) == 32767)) - (it "arithmetic right shift 14440 >> 49" (arithmeticRight 49 14440 == 0)) - (it "negative arithmetic right shift 14440 >> 49" (arithmeticRight 49 (-14440) == -1)) - (it "left shift 7398 << 48" (left 48 7398 == 2082351877705433088)) - (it "negative left shift 7398 << 48" (left 48 (-7398) == -2082351877705433088)) - (it "logical right shift 7398 >> 48" (logicalRight 48 7398 == 0)) - (it "negative logical right shift 7398 >> 48" (logicalRight 48 (-7398) == 65535)) - (it "arithmetic right shift 7398 >> 48" (arithmeticRight 48 7398 == 0)) - (it "negative arithmetic right shift 7398 >> 48" (arithmeticRight 48 (-7398) == -1)) - (it "left shift 10215 << 47" (left 47 10215 == 1437633443549675520)) - (it "negative left shift 10215 << 47" (left 47 (-10215) == -1437633443549675520)) - (it "logical right shift 10215 >> 47" (logicalRight 47 10215 == 0)) - (it "negative logical right shift 10215 >> 47" (logicalRight 47 (-10215) == 131071)) - (it "arithmetic right shift 10215 >> 47" (arithmeticRight 47 10215 == 0)) - (it "negative arithmetic right shift 10215 >> 47" (arithmeticRight 47 (-10215) == -1)) - (it "left shift 10172 << 46" (left 46 10172 == 715790865775198208)) - (it "negative left shift 10172 << 46" (left 46 (-10172) == -715790865775198208)) - (it "logical right shift 10172 >> 46" (logicalRight 46 10172 == 0)) - (it "negative logical right shift 10172 >> 46" (logicalRight 46 (-10172) == 262143)) - (it "arithmetic right shift 10172 >> 46" (arithmeticRight 46 10172 == 0)) - (it "negative arithmetic right shift 10172 >> 46" (arithmeticRight 46 (-10172) == -1)) - (it "left shift 15671 << 45" (left 45 15671 == 551374295004086272)) - (it "negative left shift 15671 << 45" (left 45 (-15671) == -551374295004086272)) - (it "logical right shift 15671 >> 45" (logicalRight 45 15671 == 0)) - (it "negative logical right shift 15671 >> 45" (logicalRight 45 (-15671) == 524287)) - (it "arithmetic right shift 15671 >> 45" (arithmeticRight 45 15671 == 0)) - (it "negative arithmetic right shift 15671 >> 45" (arithmeticRight 45 (-15671) == -1)) - (it "left shift 22286 << 44" (left 44 22286 == 392059458185854976)) - (it "negative left shift 22286 << 44" (left 44 (-22286) == -392059458185854976)) - (it "logical right shift 22286 >> 44" (logicalRight 44 22286 == 0)) - (it "negative logical right shift 22286 >> 44" (logicalRight 44 (-22286) == 1048575)) - (it "arithmetic right shift 22286 >> 44" (arithmeticRight 44 22286 == 0)) - (it "negative arithmetic right shift 22286 >> 44" (arithmeticRight 44 (-22286) == -1)) - (it "left shift 29742 << 43" (left 43 29742 == 261613398666510336)) - (it "negative left shift 29742 << 43" (left 43 (-29742) == -261613398666510336)) - (it "logical right shift 29742 >> 43" (logicalRight 43 29742 == 0)) - (it "negative logical right shift 29742 >> 43" (logicalRight 43 (-29742) == 2097151)) - (it "arithmetic right shift 29742 >> 43" (arithmeticRight 43 29742 == 0)) - (it "negative arithmetic right shift 29742 >> 43" (arithmeticRight 43 (-29742) == -1)) - (it "left shift 13223 << 42" (left 42 13223 == 58155369016328192)) - (it "negative left shift 13223 << 42" (left 42 (-13223) == -58155369016328192)) - (it "logical right shift 13223 >> 42" (logicalRight 42 13223 == 0)) - (it "negative logical right shift 13223 >> 42" (logicalRight 42 (-13223) == 4194303)) - (it "arithmetic right shift 13223 >> 42" (arithmeticRight 42 13223 == 0)) - (it "negative arithmetic right shift 13223 >> 42" (arithmeticRight 42 (-13223) == -1)) - (it "left shift 27362 << 41" (left 41 27362 == 60169674318413824)) - (it "negative left shift 27362 << 41" (left 41 (-27362) == -60169674318413824)) - (it "logical right shift 27362 >> 41" (logicalRight 41 27362 == 0)) - (it "negative logical right shift 27362 >> 41" (logicalRight 41 (-27362) == 8388607)) - (it "arithmetic right shift 27362 >> 41" (arithmeticRight 41 27362 == 0)) - (it "negative arithmetic right shift 27362 >> 41" (arithmeticRight 41 (-27362) == -1)) - (it "left shift 9358 << 40" (left 40 9358 == 10289229812727808)) - (it "negative left shift 9358 << 40" (left 40 (-9358) == -10289229812727808)) - (it "logical right shift 9358 >> 40" (logicalRight 40 9358 == 0)) - (it "negative logical right shift 9358 >> 40" (logicalRight 40 (-9358) == 16777215)) - (it "arithmetic right shift 9358 >> 40" (arithmeticRight 40 9358 == 0)) - (it "negative arithmetic right shift 9358 >> 40" (arithmeticRight 40 (-9358) == -1)) - (it "left shift 11691 << 39" (left 39 11691 == 6427195220164608)) - (it "negative left shift 11691 << 39" (left 39 (-11691) == -6427195220164608)) - (it "logical right shift 11691 >> 39" (logicalRight 39 11691 == 0)) - (it "negative logical right shift 11691 >> 39" (logicalRight 39 (-11691) == 33554431)) - (it "arithmetic right shift 11691 >> 39" (arithmeticRight 39 11691 == 0)) - (it "negative arithmetic right shift 11691 >> 39" (arithmeticRight 39 (-11691) == -1)) - (it "left shift 18608 << 38" (left 38 18608 == 5114928092413952)) - (it "negative left shift 18608 << 38" (left 38 (-18608) == -5114928092413952)) - (it "logical right shift 18608 >> 38" (logicalRight 38 18608 == 0)) - (it "negative logical right shift 18608 >> 38" (logicalRight 38 (-18608) == 67108863)) - (it "arithmetic right shift 18608 >> 38" (arithmeticRight 38 18608 == 0)) - (it "negative arithmetic right shift 18608 >> 38" (arithmeticRight 38 (-18608) == -1)) - (it "left shift 30802 << 37" (left 37 30802 == 4233394644844544)) - (it "negative left shift 30802 << 37" (left 37 (-30802) == -4233394644844544)) - (it "logical right shift 30802 >> 37" (logicalRight 37 30802 == 0)) - (it "negative logical right shift 30802 >> 37" (logicalRight 37 (-30802) == 134217727)) - (it "arithmetic right shift 30802 >> 37" (arithmeticRight 37 30802 == 0)) - (it "negative arithmetic right shift 30802 >> 37" (arithmeticRight 37 (-30802) == -1)) - (it "left shift 25321 << 36" (left 36 25321 == 1740045870432256)) - (it "negative left shift 25321 << 36" (left 36 (-25321) == -1740045870432256)) - (it "logical right shift 25321 >> 36" (logicalRight 36 25321 == 0)) - (it "negative logical right shift 25321 >> 36" (logicalRight 36 (-25321) == 268435455)) - (it "arithmetic right shift 25321 >> 36" (arithmeticRight 36 25321 == 0)) - (it "negative arithmetic right shift 25321 >> 36" (arithmeticRight 36 (-25321) == -1)) - (it "left shift 21777 << 35" (left 35 21777 == 748252022439936)) - (it "negative left shift 21777 << 35" (left 35 (-21777) == -748252022439936)) - (it "logical right shift 21777 >> 35" (logicalRight 35 21777 == 0)) - (it "negative logical right shift 21777 >> 35" (logicalRight 35 (-21777) == 536870911)) - (it "arithmetic right shift 21777 >> 35" (arithmeticRight 35 21777 == 0)) - (it "negative arithmetic right shift 21777 >> 35" (arithmeticRight 35 (-21777) == -1)) - (it "left shift 19037 << 34" (left 34 19037 == 327053169655808)) - (it "negative left shift 19037 << 34" (left 34 (-19037) == -327053169655808)) - (it "logical right shift 19037 >> 34" (logicalRight 34 19037 == 0)) - (it "negative logical right shift 19037 >> 34" (logicalRight 34 (-19037) == 1073741823)) - (it "arithmetic right shift 19037 >> 34" (arithmeticRight 34 19037 == 0)) - (it "negative arithmetic right shift 19037 >> 34" (arithmeticRight 34 (-19037) == -1)) - (it "left shift 23041 << 33" (left 33 23041 == 197920682934272)) - (it "negative left shift 23041 << 33" (left 33 (-23041) == -197920682934272)) - (it "logical right shift 23041 >> 33" (logicalRight 33 23041 == 0)) - (it "negative logical right shift 23041 >> 33" (logicalRight 33 (-23041) == 2147483647)) - (it "arithmetic right shift 23041 >> 33" (arithmeticRight 33 23041 == 0)) - (it "negative arithmetic right shift 23041 >> 33" (arithmeticRight 33 (-23041) == -1)) - (it "left shift 13483 << 32" (left 32 13483 == 57909044051968)) - (it "negative left shift 13483 << 32" (left 32 (-13483) == -57909044051968)) - (it "logical right shift 13483 >> 32" (logicalRight 32 13483 == 0)) - (it "negative logical right shift 13483 >> 32" (logicalRight 32 (-13483) == 4294967295)) - (it "arithmetic right shift 13483 >> 32" (arithmeticRight 32 13483 == 0)) - (it "negative arithmetic right shift 13483 >> 32" (arithmeticRight 32 (-13483) == -1)) - (it "left shift 12790 << 31" (left 31 12790 == 27466315857920)) - (it "negative left shift 12790 << 31" (left 31 (-12790) == -27466315857920)) - (it "logical right shift 12790 >> 31" (logicalRight 31 12790 == 0)) - (it "negative logical right shift 12790 >> 31" (logicalRight 31 (-12790) == 8589934591)) - (it "arithmetic right shift 12790 >> 31" (arithmeticRight 31 12790 == 0)) - (it "negative arithmetic right shift 12790 >> 31" (arithmeticRight 31 (-12790) == -1)) - (it "left shift 29648 << 30" (left 30 29648 == 31834297597952)) - (it "negative left shift 29648 << 30" (left 30 (-29648) == -31834297597952)) - (it "logical right shift 29648 >> 30" (logicalRight 30 29648 == 0)) - (it "negative logical right shift 29648 >> 30" (logicalRight 30 (-29648) == 17179869183)) - (it "arithmetic right shift 29648 >> 30" (arithmeticRight 30 29648 == 0)) - (it "negative arithmetic right shift 29648 >> 30" (arithmeticRight 30 (-29648) == -1)) - (it "left shift 31723 << 29" (left 29 31723 == 17031155941376)) - (it "negative left shift 31723 << 29" (left 29 (-31723) == -17031155941376)) - (it "logical right shift 31723 >> 29" (logicalRight 29 31723 == 0)) - (it "negative logical right shift 31723 >> 29" (logicalRight 29 (-31723) == 34359738367)) - (it "arithmetic right shift 31723 >> 29" (arithmeticRight 29 31723 == 0)) - (it "negative arithmetic right shift 31723 >> 29" (arithmeticRight 29 (-31723) == -1)) - (it "left shift 429 << 28" (left 28 429 == 115158810624)) - (it "negative left shift 429 << 28" (left 28 (-429) == -115158810624)) - (it "logical right shift 429 >> 28" (logicalRight 28 429 == 0)) - (it "negative logical right shift 429 >> 28" (logicalRight 28 (-429) == 68719476735)) - (it "arithmetic right shift 429 >> 28" (arithmeticRight 28 429 == 0)) - (it "negative arithmetic right shift 429 >> 28" (arithmeticRight 28 (-429) == -1)) - (it "left shift 3138 << 27" (left 27 3138 == 421175230464)) - (it "negative left shift 3138 << 27" (left 27 (-3138) == -421175230464)) - (it "logical right shift 3138 >> 27" (logicalRight 27 3138 == 0)) - (it "negative logical right shift 3138 >> 27" (logicalRight 27 (-3138) == 137438953471)) - (it "arithmetic right shift 3138 >> 27" (arithmeticRight 27 3138 == 0)) - (it "negative arithmetic right shift 3138 >> 27" (arithmeticRight 27 (-3138) == -1)) - (it "left shift 20136 << 26" (left 26 20136 == 1351304085504)) - (it "negative left shift 20136 << 26" (left 26 (-20136) == -1351304085504)) - (it "logical right shift 20136 >> 26" (logicalRight 26 20136 == 0)) - (it "negative logical right shift 20136 >> 26" (logicalRight 26 (-20136) == 274877906943)) - (it "arithmetic right shift 20136 >> 26" (arithmeticRight 26 20136 == 0)) - (it "negative arithmetic right shift 20136 >> 26" (arithmeticRight 26 (-20136) == -1)) - (it "left shift 27841 << 25" (left 25 27841 == 934188941312)) - (it "negative left shift 27841 << 25" (left 25 (-27841) == -934188941312)) - (it "logical right shift 27841 >> 25" (logicalRight 25 27841 == 0)) - (it "negative logical right shift 27841 >> 25" (logicalRight 25 (-27841) == 549755813887)) - (it "arithmetic right shift 27841 >> 25" (arithmeticRight 25 27841 == 0)) - (it "negative arithmetic right shift 27841 >> 25" (arithmeticRight 25 (-27841) == -1)) - (it "left shift 23965 << 24" (left 24 23965 == 402065981440)) - (it "negative left shift 23965 << 24" (left 24 (-23965) == -402065981440)) - (it "logical right shift 23965 >> 24" (logicalRight 24 23965 == 0)) - (it "negative logical right shift 23965 >> 24" (logicalRight 24 (-23965) == 1099511627775)) - (it "arithmetic right shift 23965 >> 24" (arithmeticRight 24 23965 == 0)) - (it "negative arithmetic right shift 23965 >> 24" (arithmeticRight 24 (-23965) == -1)) - (it "left shift 9647 << 23" (left 23 9647 == 80924901376)) - (it "negative left shift 9647 << 23" (left 23 (-9647) == -80924901376)) - (it "logical right shift 9647 >> 23" (logicalRight 23 9647 == 0)) - (it "negative logical right shift 9647 >> 23" (logicalRight 23 (-9647) == 2199023255551)) - (it "arithmetic right shift 9647 >> 23" (arithmeticRight 23 9647 == 0)) - (it "negative arithmetic right shift 9647 >> 23" (arithmeticRight 23 (-9647) == -1)) - (it "left shift 13329 << 22" (left 22 13329 == 55905878016)) - (it "negative left shift 13329 << 22" (left 22 (-13329) == -55905878016)) - (it "logical right shift 13329 >> 22" (logicalRight 22 13329 == 0)) - (it "negative logical right shift 13329 >> 22" (logicalRight 22 (-13329) == 4398046511103)) - (it "arithmetic right shift 13329 >> 22" (arithmeticRight 22 13329 == 0)) - (it "negative arithmetic right shift 13329 >> 22" (arithmeticRight 22 (-13329) == -1)) - (it "left shift 32694 << 21" (left 21 32694 == 68564287488)) - (it "negative left shift 32694 << 21" (left 21 (-32694) == -68564287488)) - (it "logical right shift 32694 >> 21" (logicalRight 21 32694 == 0)) - (it "negative logical right shift 32694 >> 21" (logicalRight 21 (-32694) == 8796093022207)) - (it "arithmetic right shift 32694 >> 21" (arithmeticRight 21 32694 == 0)) - (it "negative arithmetic right shift 32694 >> 21" (arithmeticRight 21 (-32694) == -1)) - (it "left shift 17805 << 20" (left 20 17805 == 18669895680)) - (it "negative left shift 17805 << 20" (left 20 (-17805) == -18669895680)) - (it "logical right shift 17805 >> 20" (logicalRight 20 17805 == 0)) - (it "negative logical right shift 17805 >> 20" (logicalRight 20 (-17805) == 17592186044415)) - (it "arithmetic right shift 17805 >> 20" (arithmeticRight 20 17805 == 0)) - (it "negative arithmetic right shift 17805 >> 20" (arithmeticRight 20 (-17805) == -1)) - (it "left shift 32292 << 19" (left 19 32292 == 16930308096)) - (it "negative left shift 32292 << 19" (left 19 (-32292) == -16930308096)) - (it "logical right shift 32292 >> 19" (logicalRight 19 32292 == 0)) - (it "negative logical right shift 32292 >> 19" (logicalRight 19 (-32292) == 35184372088831)) - (it "arithmetic right shift 32292 >> 19" (arithmeticRight 19 32292 == 0)) - (it "negative arithmetic right shift 32292 >> 19" (arithmeticRight 19 (-32292) == -1)) - (it "left shift 16841 << 18" (left 18 16841 == 4414767104)) - (it "negative left shift 16841 << 18" (left 18 (-16841) == -4414767104)) - (it "logical right shift 16841 >> 18" (logicalRight 18 16841 == 0)) - (it "negative logical right shift 16841 >> 18" (logicalRight 18 (-16841) == 70368744177663)) - (it "arithmetic right shift 16841 >> 18" (arithmeticRight 18 16841 == 0)) - (it "negative arithmetic right shift 16841 >> 18" (arithmeticRight 18 (-16841) == -1)) - (it "left shift 18798 << 17" (left 17 18798 == 2463891456)) - (it "negative left shift 18798 << 17" (left 17 (-18798) == -2463891456)) - (it "logical right shift 18798 >> 17" (logicalRight 17 18798 == 0)) - (it "negative logical right shift 18798 >> 17" (logicalRight 17 (-18798) == 140737488355327)) - (it "arithmetic right shift 18798 >> 17" (arithmeticRight 17 18798 == 0)) - (it "negative arithmetic right shift 18798 >> 17" (arithmeticRight 17 (-18798) == -1)) - (it "left shift 2511 << 16" (left 16 2511 == 164560896)) - (it "negative left shift 2511 << 16" (left 16 (-2511) == -164560896)) - (it "logical right shift 2511 >> 16" (logicalRight 16 2511 == 0)) - (it "negative logical right shift 2511 >> 16" (logicalRight 16 (-2511) == 281474976710655)) - (it "arithmetic right shift 2511 >> 16" (arithmeticRight 16 2511 == 0)) - (it "negative arithmetic right shift 2511 >> 16" (arithmeticRight 16 (-2511) == -1)) - (it "left shift 933 << 15" (left 15 933 == 30572544)) - (it "negative left shift 933 << 15" (left 15 (-933) == -30572544)) - (it "logical right shift 933 >> 15" (logicalRight 15 933 == 0)) - (it "negative logical right shift 933 >> 15" (logicalRight 15 (-933) == 562949953421311)) - (it "arithmetic right shift 933 >> 15" (arithmeticRight 15 933 == 0)) - (it "negative arithmetic right shift 933 >> 15" (arithmeticRight 15 (-933) == -1)) - (it "left shift 26861 << 14" (left 14 26861 == 440090624)) - (it "negative left shift 26861 << 14" (left 14 (-26861) == -440090624)) - (it "logical right shift 26861 >> 14" (logicalRight 14 26861 == 1)) - (it "negative logical right shift 26861 >> 14" (logicalRight 14 (-26861) == 1125899906842622)) - (it "arithmetic right shift 26861 >> 14" (arithmeticRight 14 26861 == 1)) - (it "negative arithmetic right shift 26861 >> 14" (arithmeticRight 14 (-26861) == -2)) - (it "left shift 13766 << 13" (left 13 13766 == 112771072)) - (it "negative left shift 13766 << 13" (left 13 (-13766) == -112771072)) - (it "logical right shift 13766 >> 13" (logicalRight 13 13766 == 1)) - (it "negative logical right shift 13766 >> 13" (logicalRight 13 (-13766) == 2251799813685246)) - (it "arithmetic right shift 13766 >> 13" (arithmeticRight 13 13766 == 1)) - (it "negative arithmetic right shift 13766 >> 13" (arithmeticRight 13 (-13766) == -2)) - (it "left shift 21344 << 12" (left 12 21344 == 87425024)) - (it "negative left shift 21344 << 12" (left 12 (-21344) == -87425024)) - (it "logical right shift 21344 >> 12" (logicalRight 12 21344 == 5)) - (it "negative logical right shift 21344 >> 12" (logicalRight 12 (-21344) == 4503599627370490)) - (it "arithmetic right shift 21344 >> 12" (arithmeticRight 12 21344 == 5)) - (it "negative arithmetic right shift 21344 >> 12" (arithmeticRight 12 (-21344) == -6)) - (it "left shift 8246 << 11" (left 11 8246 == 16887808)) - (it "negative left shift 8246 << 11" (left 11 (-8246) == -16887808)) - (it "logical right shift 8246 >> 11" (logicalRight 11 8246 == 4)) - (it "negative logical right shift 8246 >> 11" (logicalRight 11 (-8246) == 9007199254740987)) - (it "arithmetic right shift 8246 >> 11" (arithmeticRight 11 8246 == 4)) - (it "negative arithmetic right shift 8246 >> 11" (arithmeticRight 11 (-8246) == -5)) - (it "left shift 18044 << 10" (left 10 18044 == 18477056)) - (it "negative left shift 18044 << 10" (left 10 (-18044) == -18477056)) - (it "logical right shift 18044 >> 10" (logicalRight 10 18044 == 17)) - (it "negative logical right shift 18044 >> 10" (logicalRight 10 (-18044) == 18014398509481966)) - (it "arithmetic right shift 18044 >> 10" (arithmeticRight 10 18044 == 17)) - (it "negative arithmetic right shift 18044 >> 10" (arithmeticRight 10 (-18044) == -18)) - (it "left shift 11554 << 9" (left 9 11554 == 5915648)) - (it "negative left shift 11554 << 9" (left 9 (-11554) == -5915648)) - (it "logical right shift 11554 >> 9" (logicalRight 9 11554 == 22)) - (it "negative logical right shift 11554 >> 9" (logicalRight 9 (-11554) == 36028797018963945)) - (it "arithmetic right shift 11554 >> 9" (arithmeticRight 9 11554 == 22)) - (it "negative arithmetic right shift 11554 >> 9" (arithmeticRight 9 (-11554) == -23)) - (it "left shift 19651 << 8" (left 8 19651 == 5030656)) - (it "negative left shift 19651 << 8" (left 8 (-19651) == -5030656)) - (it "logical right shift 19651 >> 8" (logicalRight 8 19651 == 76)) - (it "negative logical right shift 19651 >> 8" (logicalRight 8 (-19651) == 72057594037927859)) - (it "arithmetic right shift 19651 >> 8" (arithmeticRight 8 19651 == 76)) - (it "negative arithmetic right shift 19651 >> 8" (arithmeticRight 8 (-19651) == -77)) - (it "left shift 32588 << 7" (left 7 32588 == 4171264)) - (it "negative left shift 32588 << 7" (left 7 (-32588) == -4171264)) - (it "logical right shift 32588 >> 7" (logicalRight 7 32588 == 254)) - (it "negative logical right shift 32588 >> 7" (logicalRight 7 (-32588) == 144115188075855617)) - (it "arithmetic right shift 32588 >> 7" (arithmeticRight 7 32588 == 254)) - (it "negative arithmetic right shift 32588 >> 7" (arithmeticRight 7 (-32588) == -255)) - (it "left shift 23333 << 6" (left 6 23333 == 1493312)) - (it "negative left shift 23333 << 6" (left 6 (-23333) == -1493312)) - (it "logical right shift 23333 >> 6" (logicalRight 6 23333 == 364)) - (it "negative logical right shift 23333 >> 6" (logicalRight 6 (-23333) == 288230376151711379)) - (it "arithmetic right shift 23333 >> 6" (arithmeticRight 6 23333 == 364)) - (it "negative arithmetic right shift 23333 >> 6" (arithmeticRight 6 (-23333) == -365)) - (it "left shift 13058 << 5" (left 5 13058 == 417856)) - (it "negative left shift 13058 << 5" (left 5 (-13058) == -417856)) - (it "logical right shift 13058 >> 5" (logicalRight 5 13058 == 408)) - (it "negative logical right shift 13058 >> 5" (logicalRight 5 (-13058) == 576460752303423079)) - (it "arithmetic right shift 13058 >> 5" (arithmeticRight 5 13058 == 408)) - (it "negative arithmetic right shift 13058 >> 5" (arithmeticRight 5 (-13058) == -409)) - (it "left shift 10754 << 4" (left 4 10754 == 172064)) - (it "negative left shift 10754 << 4" (left 4 (-10754) == -172064)) - (it "logical right shift 10754 >> 4" (logicalRight 4 10754 == 672)) - (it "negative logical right shift 10754 >> 4" (logicalRight 4 (-10754) == 1152921504606846303)) - (it "arithmetic right shift 10754 >> 4" (arithmeticRight 4 10754 == 672)) - (it "negative arithmetic right shift 10754 >> 4" (arithmeticRight 4 (-10754) == -673)) - (it "left shift 22538 << 3" (left 3 22538 == 180304)) - (it "negative left shift 22538 << 3" (left 3 (-22538) == -180304)) - (it "logical right shift 22538 >> 3" (logicalRight 3 22538 == 2817)) - (it "negative logical right shift 22538 >> 3" (logicalRight 3 (-22538) == 2305843009213691134)) - (it "arithmetic right shift 22538 >> 3" (arithmeticRight 3 22538 == 2817)) - (it "negative arithmetic right shift 22538 >> 3" (arithmeticRight 3 (-22538) == -2818)) - (it "left shift 1792 << 2" (left 2 1792 == 7168)) - (it "negative left shift 1792 << 2" (left 2 (-1792) == -7168)) - (it "logical right shift 1792 >> 2" (logicalRight 2 1792 == 448)) - (it "negative logical right shift 1792 >> 2" (logicalRight 2 (-1792) == 4611686018427387456)) - (it "arithmetic right shift 1792 >> 2" (arithmeticRight 2 1792 == 448)) - (it "negative arithmetic right shift 1792 >> 2" (arithmeticRight 2 (-1792) == -448)) - (it "left shift 29700 << 1" (left 1 29700 == 59400)) - (it "negative left shift 29700 << 1" (left 1 (-29700) == -59400)) - (it "logical right shift 29700 >> 1" (logicalRight 1 29700 == 14850)) - (it "negative logical right shift 29700 >> 1" (logicalRight 1 (-29700) == 9223372036854760958)) - (it "arithmetic right shift 29700 >> 1" (arithmeticRight 1 29700 == 14850)) - (it "negative arithmetic right shift 29700 >> 1" (arithmeticRight 1 (-29700) == -14850)) - (it "left shift 21068 << 0" (left 0 21068 == 21068)) - (it "negative left shift 21068 << 0" (left 0 (-21068) == -21068)) - (it "logical right shift 21068 >> 0" (logicalRight 0 21068 == 21068)) - (it "negative logical right shift 21068 >> 0" (logicalRight 0 (-21068) == -21068)) - (it "arithmetic right shift 21068 >> 0" (arithmeticRight 0 21068 == 21068)) - (it "negative arithmetic right shift 21068 >> 0" (arithmeticRight 0 (-21068) == -21068)) - (it "arithmetic right shift -1 >> 32" (arithmeticRight 32 (-1) == (-1))) - (it "arithmetic right shift -1 >> 102" (arithmeticRight 102 (-1) == (-1))) - ]) -]