summaryrefslogtreecommitdiff
path: root/vendor/deranged
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
committermo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
commit8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch)
tree22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/deranged
parent4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff)
chore: add vendor directory
Diffstat (limited to 'vendor/deranged')
-rw-r--r--vendor/deranged/.cargo-checksum.json1
-rw-r--r--vendor/deranged/Cargo.lock347
-rw-r--r--vendor/deranged/Cargo.toml203
-rw-r--r--vendor/deranged/LICENSE-Apache202
-rw-r--r--vendor/deranged/LICENSE-MIT19
-rw-r--r--vendor/deranged/README.md3
-rw-r--r--vendor/deranged/src/lib.rs1617
-rw-r--r--vendor/deranged/src/tests.rs716
-rw-r--r--vendor/deranged/src/traits.rs123
-rw-r--r--vendor/deranged/src/unsafe_wrapper.rs36
10 files changed, 3267 insertions, 0 deletions
diff --git a/vendor/deranged/.cargo-checksum.json b/vendor/deranged/.cargo-checksum.json
new file mode 100644
index 00000000..1d07cbe0
--- /dev/null
+++ b/vendor/deranged/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.lock":"757a23868a83af5a992c9ef414caec3a429444637d4b6661f80fd600122d90f7","Cargo.toml":"121e144fad418c6a6389dbf18eeccfa9f3463cefad0c45165d903493782c0041","LICENSE-Apache":"edd65bdd88957a205c47d53fa499eed8865a70320f0f03f6391668cb304ea376","LICENSE-MIT":"231c837c45eb53f108fb48929e488965bc4fcc14e9ea21d35f50e6b99d98685b","README.md":"fc4c9482d9e5225630da44e5371d6fa3f37220e2f4da2dac076cf4cd4f9592e7","src/lib.rs":"322568a529a257e432c17e66de4a6a70ea8b049924109f5935a69ffa2dce72bb","src/tests.rs":"26f95b8d0dd3e01ed25141bb40d412331f4ae97abf5a2cb21c831a910d71a7bf","src/traits.rs":"d30bc35a0b238a216671fa2a200211a1a0ad966bd21c0ed63621f90a85f2f475","src/unsafe_wrapper.rs":"76e67ff03b31f0b97849f0e6c3131f1cb213fc25a11ed259664f48a6901c623e"},"package":"9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"} \ No newline at end of file
diff --git a/vendor/deranged/Cargo.lock b/vendor/deranged/Cargo.lock
new file mode 100644
index 00000000..a9c32d37
--- /dev/null
+++ b/vendor/deranged/Cargo.lock
@@ -0,0 +1,347 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "bitflags"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "deranged"
+version = "0.4.0"
+dependencies = [
+ "deranged-macros",
+ "num-traits",
+ "powerfmt",
+ "quickcheck",
+ "rand 0.8.5",
+ "rand 0.9.0",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "deranged-macros"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16bb9aa094461caab2e48a161407cc7f48923afa48d36324b6d23ab61688b78f"
+
+[[package]]
+name = "getrandom"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi 0.13.3+wasi-0.2.2",
+ "windows-targets",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
+
+[[package]]
+name = "libc"
+version = "0.2.170"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
+
+[[package]]
+name = "num-traits"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "powerfmt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quickcheck"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
+dependencies = [
+ "rand 0.8.5",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha 0.3.1",
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rand"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
+dependencies = [
+ "rand_chacha 0.9.0",
+ "rand_core 0.9.2",
+ "zerocopy",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.9.2",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom 0.2.12",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a509b1a2ffbe92afab0e55c8fd99dea1c280e8171bd2d88682bb20bc41cbc2c"
+dependencies = [
+ "getrandom 0.3.1",
+ "zerocopy",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
+
+[[package]]
+name = "serde"
+version = "1.0.197"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.197"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.114"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.52"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wasi"
+version = "0.13.3+wasi-0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
+dependencies = [
+ "wit-bindgen-rt",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "wit-bindgen-rt"
+version = "0.33.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.8.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dde3bb8c68a8f3f1ed4ac9221aad6b10cece3e60a8e2ea54a6a2dec806d0084c"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eea57037071898bf96a6da35fd626f4f27e9cee3ead2a6c703cf09d472b2e700"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/vendor/deranged/Cargo.toml b/vendor/deranged/Cargo.toml
new file mode 100644
index 00000000..220c983a
--- /dev/null
+++ b/vendor/deranged/Cargo.toml
@@ -0,0 +1,203 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2021"
+rust-version = "1.67.0"
+name = "deranged"
+version = "0.4.0"
+authors = ["Jacob Pratt <jacob@jhpratt.dev>"]
+build = false
+include = [
+ "src/**/*",
+ "LICENSE-*",
+ "README.md",
+]
+autolib = false
+autobins = false
+autoexamples = false
+autotests = false
+autobenches = false
+description = "Ranged integers"
+readme = "README.md"
+keywords = [
+ "integer",
+ "int",
+ "range",
+]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/jhpratt/deranged"
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = ["--generate-link-to-definition"]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[features]
+alloc = []
+default = ["std"]
+macros = ["dep:deranged-macros"]
+num = ["dep:num-traits"]
+powerfmt = ["dep:powerfmt"]
+quickcheck = [
+ "dep:quickcheck",
+ "alloc",
+]
+rand = [
+ "rand08",
+ "rand09",
+]
+rand08 = ["dep:rand08"]
+rand09 = ["dep:rand09"]
+serde = ["dep:serde"]
+std = ["alloc"]
+
+[lib]
+name = "deranged"
+path = "src/lib.rs"
+
+[dependencies.deranged-macros]
+version = "=0.2.0"
+optional = true
+
+[dependencies.num-traits]
+version = "0.2.15"
+optional = true
+default-features = false
+
+[dependencies.powerfmt]
+version = "0.2.0"
+optional = true
+default-features = false
+
+[dependencies.quickcheck]
+version = "1.0.3"
+optional = true
+default-features = false
+
+[dependencies.rand08]
+version = "0.8.4"
+optional = true
+default-features = false
+package = "rand"
+
+[dependencies.rand09]
+version = "0.9.0"
+optional = true
+default-features = false
+package = "rand"
+
+[dependencies.serde]
+version = "1.0.126"
+optional = true
+default-features = false
+
+[dev-dependencies.rand08]
+version = "0.8.4"
+package = "rand"
+
+[dev-dependencies.rand09]
+version = "0.9.0"
+package = "rand"
+
+[dev-dependencies.serde_json]
+version = "1.0.86"
+
+[lints.clippy]
+alloc-instead-of-core = "deny"
+dbg-macro = "warn"
+decimal-literal-representation = "warn"
+explicit-auto-deref = "warn"
+get-unwrap = "warn"
+manual-let-else = "warn"
+missing-docs-in-private-items = "warn"
+missing-enforced-import-renames = "warn"
+obfuscated-if-else = "warn"
+option-if-let-else = "allow"
+print-stdout = "warn"
+redundant-pub-crate = "allow"
+semicolon-outside-block = "warn"
+std-instead-of-core = "deny"
+todo = "warn"
+undocumented-unsafe-blocks = "deny"
+unimplemented = "warn"
+uninlined-format-args = "warn"
+unnested-or-patterns = "warn"
+unwrap-in-result = "warn"
+unwrap-used = "warn"
+use-debug = "warn"
+
+[lints.clippy.all]
+level = "warn"
+priority = -1
+
+[lints.clippy.nursery]
+level = "warn"
+priority = -1
+
+[lints.rust]
+ambiguous-glob-reexports = "deny"
+clashing-extern-declarations = "deny"
+const-item-mutation = "deny"
+dangling-pointers-from-temporaries = "deny"
+deref-nullptr = "deny"
+drop-bounds = "deny"
+future-incompatible = "deny"
+hidden-glob-reexports = "deny"
+improper-ctypes = "deny"
+improper-ctypes-definitions = "deny"
+invalid-from-utf8 = "deny"
+invalid-macro-export-arguments = "deny"
+invalid-nan-comparisons = "deny"
+invalid-reference-casting = "deny"
+invalid-value = "deny"
+keyword-idents = "warn"
+let-underscore = "warn"
+macro-use-extern-crate = "warn"
+meta-variable-misuse = "warn"
+missing-abi = "warn"
+missing-copy-implementations = "warn"
+missing-debug-implementations = "warn"
+missing-docs = "warn"
+named-arguments-used-positionally = "deny"
+non-ascii-idents = "deny"
+noop-method-call = "warn"
+opaque-hidden-inferred-bound = "deny"
+overlapping-range-endpoints = "deny"
+single-use-lifetimes = "warn"
+suspicious-double-ref-op = "deny"
+trivial-casts = "warn"
+trivial-numeric-casts = "warn"
+unconditional-recursion = "deny"
+unnameable-test-items = "deny"
+unreachable-pub = "warn"
+unsafe-op-in-unsafe-fn = "deny"
+unstable-syntax-pre-expansion = "deny"
+unused-import-braces = "warn"
+unused-lifetimes = "warn"
+unused-qualifications = "warn"
+variant-size-differences = "warn"
+
+[lints.rust.path-statements]
+level = "allow"
+priority = 1
+
+[lints.rust.unstable-name-collisions]
+level = "warn"
+priority = 1
+
+[lints.rust.unused]
+level = "warn"
+priority = -1
+
+[lints.rustdoc]
+private-doc-tests = "warn"
+unescaped-backticks = "warn"
diff --git a/vendor/deranged/LICENSE-Apache b/vendor/deranged/LICENSE-Apache
new file mode 100644
index 00000000..c763a0c9
--- /dev/null
+++ b/vendor/deranged/LICENSE-Apache
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2024 Jacob Pratt et al.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/deranged/LICENSE-MIT b/vendor/deranged/LICENSE-MIT
new file mode 100644
index 00000000..5cc097f1
--- /dev/null
+++ b/vendor/deranged/LICENSE-MIT
@@ -0,0 +1,19 @@
+Copyright (c) 2024 Jacob Pratt et al.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/deranged/README.md b/vendor/deranged/README.md
new file mode 100644
index 00000000..eddc4b99
--- /dev/null
+++ b/vendor/deranged/README.md
@@ -0,0 +1,3 @@
+# Deranged
+
+This crate is a proof-of-concept implementation of ranged integers.
diff --git a/vendor/deranged/src/lib.rs b/vendor/deranged/src/lib.rs
new file mode 100644
index 00000000..059fac74
--- /dev/null
+++ b/vendor/deranged/src/lib.rs
@@ -0,0 +1,1617 @@
+//! `deranged` is a proof-of-concept implementation of ranged integers.
+
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
+#![no_std]
+#![doc(test(attr(deny(warnings))))]
+
+#[cfg(feature = "std")]
+extern crate std;
+
+#[cfg(all(feature = "alloc", any(feature = "serde", feature = "quickcheck")))]
+extern crate alloc;
+
+#[cfg(test)]
+mod tests;
+mod traits;
+mod unsafe_wrapper;
+
+use core::borrow::Borrow;
+use core::cmp::Ordering;
+use core::fmt;
+use core::num::IntErrorKind;
+use core::str::FromStr;
+#[cfg(feature = "std")]
+use std::error::Error;
+
+/// A macro to define a ranged integer with an automatically computed inner type.
+///
+/// The minimum and maximum values are provided as integer literals, and the macro will compute an
+/// appropriate inner type to represent the range. This will be the smallest integer type that can
+/// store both the minimum and maximum values, with a preference for unsigned types if both are
+/// possible. To specifically request a signed or unsigned type, you can append a `i` or `u` suffix
+/// to either or both of the minimum and maximum values, respectively.
+///
+/// # Examples
+///
+/// ```rust,ignore
+/// int!(0, 100); // RangedU8<0, 100>
+/// int!(0i, 100); // RangedI8<0, 100>
+/// int!(-5, 5); // RangedI8<-5, 5>
+/// int!(-5u, 5); // compile error (-5 cannot be unsigned)
+/// ```
+#[cfg(all(docsrs, feature = "macros"))]
+#[macro_export]
+macro_rules! int {
+ ($min:literal, $max:literal) => {};
+}
+
+/// A macro to define an optional ranged integer with an automatically computed inner type.
+///
+/// The minimum and maximum values are provided as integer literals, and the macro will compute an
+/// appropriate inner type to represent the range. This will be the smallest integer type that can
+/// store both the minimum and maximum values, with a preference for unsigned types if both are
+/// possible. To specifically request a signed or unsigned type, you can append a `i` or `u` suffix
+/// to either or both of the minimum and maximum values, respectively.
+///
+/// # Examples
+///
+/// ```rust,ignore
+/// opt_int!(0, 100); // OptionRangedU8<0, 100>
+/// opt_int!(0i, 100); // OptionRangedI8<0, 100>
+/// opt_int!(-5, 5); // OptionRangedI8<-5, 5>
+/// opt_int!(-5u, 5); // compile error (-5 cannot be unsigned)
+/// ```
+#[cfg(all(docsrs, feature = "macros"))]
+#[macro_export]
+macro_rules! opt_int {
+ ($min:literal, $max:literal) => {};
+}
+
+#[cfg(all(not(docsrs), feature = "macros"))]
+pub use deranged_macros::int;
+#[cfg(all(not(docsrs), feature = "macros"))]
+pub use deranged_macros::opt_int;
+#[cfg(feature = "powerfmt")]
+use powerfmt::smart_display;
+
+use crate::unsafe_wrapper::Unsafe;
+
+/// The error type returned when a checked integral type conversion fails.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct TryFromIntError;
+
+impl fmt::Display for TryFromIntError {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("out of range integral type conversion attempted")
+ }
+}
+#[cfg(feature = "std")]
+impl Error for TryFromIntError {}
+
+/// An error which can be returned when parsing an integer.
+///
+/// This error is used as the error type for the `from_str_radix()` functions on ranged integer
+/// types, such as [`RangedI8::from_str_radix`].
+///
+/// # Potential causes
+///
+/// Among other causes, `ParseIntError` can be thrown because of leading or trailing whitespace
+/// in the string e.g., when it is obtained from the standard input.
+/// Using the [`str::trim()`] method ensures that no whitespace remains before parsing.
+///
+/// # Example
+///
+/// ```rust
+/// # use deranged::RangedI32;
+/// if let Err(e) = RangedI32::<0, 10>::from_str_radix("a12", 10) {
+/// println!("Failed conversion to RangedI32: {e}");
+/// }
+/// ```
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct ParseIntError {
+ #[allow(clippy::missing_docs_in_private_items)]
+ kind: IntErrorKind,
+}
+
+impl ParseIntError {
+ /// Outputs the detailed cause of parsing an integer failing.
+ // This function is not const because the counterpart of stdlib isn't
+ #[allow(clippy::missing_const_for_fn)]
+ #[inline(always)]
+ pub fn kind(&self) -> &IntErrorKind {
+ &self.kind
+ }
+}
+
+impl fmt::Display for ParseIntError {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self.kind {
+ IntErrorKind::Empty => "cannot parse integer from empty string",
+ IntErrorKind::InvalidDigit => "invalid digit found in string",
+ IntErrorKind::PosOverflow => "number too large to fit in target type",
+ IntErrorKind::NegOverflow => "number too small to fit in target type",
+ IntErrorKind::Zero => "number would be zero for non-zero type",
+ _ => "Unknown Int error kind",
+ }
+ .fmt(f)
+ }
+}
+
+#[cfg(feature = "std")]
+impl Error for ParseIntError {}
+
+/// `?` for `Option` types, usable in `const` contexts.
+macro_rules! const_try_opt {
+ ($e:expr) => {
+ match $e {
+ Some(value) => value,
+ None => return None,
+ }
+ };
+}
+
+/// Output the given tokens if the type is signed, otherwise output nothing.
+macro_rules! if_signed {
+ (true $($x:tt)*) => { $($x)*};
+ (false $($x:tt)*) => {};
+}
+
+/// Output the given tokens if the type is unsigned, otherwise output nothing.
+macro_rules! if_unsigned {
+ (true $($x:tt)*) => {};
+ (false $($x:tt)*) => { $($x)* };
+}
+
+/// `"A"` if `true`, `"An"` if `false`.
+macro_rules! article {
+ (true) => {
+ "An"
+ };
+ (false) => {
+ "A"
+ };
+}
+
+/// `Option::unwrap_unchecked`, but usable in `const` contexts.
+macro_rules! unsafe_unwrap_unchecked {
+ ($e:expr) => {{
+ let opt = $e;
+ debug_assert!(opt.is_some());
+ match $e {
+ Some(value) => value,
+ None => core::hint::unreachable_unchecked(),
+ }
+ }};
+}
+
+/// Informs the optimizer that a condition is always true. If the condition is false, the behavior
+/// is undefined.
+///
+/// # Safety
+///
+/// `b` must be `true`.
+// TODO remove in favor of `core::hint::assert_unchecked` when MSRV is ≥1.81
+#[inline]
+const unsafe fn assert_unchecked(b: bool) {
+ debug_assert!(b);
+ if !b {
+ // Safety: The caller must ensure that `b` is true.
+ unsafe { core::hint::unreachable_unchecked() }
+ }
+}
+
+/// Output the provided code if and only if the list does not include `rand_09`.
+#[allow(unused_macro_rules)]
+macro_rules! if_not_manual_rand_09 {
+ ([rand_09 $($rest:ident)*] $($output:tt)*) => {};
+ ([] $($output:tt)*) => {
+ $($output)*
+ };
+ ([$first:ident $($rest:ident)*] $($output:tt)*) => {
+ if_not_manual_rand_09!([$($rest)*] $($output)*);
+ };
+}
+
+/// Implement a ranged integer type.
+macro_rules! impl_ranged {
+ ($(
+ $type:ident {
+ mod_name: $mod_name:ident
+ internal: $internal:ident
+ signed: $is_signed:ident
+ unsigned: $unsigned_type:ident
+ optional: $optional_type:ident
+ $(manual: [$($skips:ident)+])?
+ }
+ )*) => {$(
+ #[doc = concat!(
+ article!($is_signed),
+ " `",
+ stringify!($internal),
+ "` that is known to be in the range `MIN..=MAX`.",
+ )]
+ #[repr(transparent)]
+ #[derive(Clone, Copy, Eq, Ord, Hash)]
+ pub struct $type<const MIN: $internal, const MAX: $internal>(
+ Unsafe<$internal>,
+ );
+
+ #[doc = concat!(
+ "An optional `",
+ stringify!($type),
+ "`; similar to `Option<",
+ stringify!($type),
+ ">` with better optimization.",
+ )]
+ ///
+ #[doc = concat!(
+ "If `MIN` is [`",
+ stringify!($internal),
+ "::MIN`] _and_ `MAX` is [`",
+ stringify!($internal)
+ ,"::MAX`] then compilation will fail. This is because there is no way to represent \
+ the niche value.",
+ )]
+ ///
+ /// This type is useful when you need to store an optional ranged value in a struct, but
+ /// do not want the overhead of an `Option` type. This reduces the size of the struct
+ /// overall, and is particularly useful when you have a large number of optional fields.
+ /// Note that most operations must still be performed on the [`Option`] type, which is
+ #[doc = concat!("obtained with [`", stringify!($optional_type), "::get`].")]
+ #[repr(transparent)]
+ #[derive(Clone, Copy, Eq, Hash)]
+ pub struct $optional_type<const MIN: $internal, const MAX: $internal>(
+ $internal,
+ );
+
+ impl $type<0, 0> {
+ #[doc = concat!("A ", stringify!($type), " that is always `VALUE`.")]
+ #[inline(always)]
+ pub const fn exact<const VALUE: $internal>() -> $type<VALUE, VALUE> {
+ // Safety: The value is the only one in range.
+ unsafe { $type::new_unchecked(VALUE) }
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> $type<MIN, MAX> {
+ /// The smallest value that can be represented by this type.
+ // Safety: `MIN` is in range by definition.
+ pub const MIN: Self = Self::new_static::<MIN>();
+
+ /// The largest value that can be represented by this type.
+ // Safety: `MAX` is in range by definition.
+ pub const MAX: Self = Self::new_static::<MAX>();
+
+ /// Creates a ranged integer without checking the value.
+ ///
+ /// # Safety
+ ///
+ /// The value must be within the range `MIN..=MAX`.
+ #[inline(always)]
+ pub const unsafe fn new_unchecked(value: $internal) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: The caller must ensure that the value is in range.
+ unsafe {
+ $crate::assert_unchecked(MIN <= value && value <= MAX);
+ Self(Unsafe::new(value))
+ }
+ }
+
+ /// Returns the value as a primitive type.
+ #[inline(always)]
+ pub const fn get(self) -> $internal {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: A stored value is always in range.
+ unsafe { $crate::assert_unchecked(MIN <= *self.0.get() && *self.0.get() <= MAX) };
+ *self.0.get()
+ }
+
+ #[inline(always)]
+ pub(crate) const fn get_ref(&self) -> &$internal {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ let value = self.0.get();
+ // Safety: A stored value is always in range.
+ unsafe { $crate::assert_unchecked(MIN <= *value && *value <= MAX) };
+ value
+ }
+
+ /// Creates a ranged integer if the given value is in the range `MIN..=MAX`.
+ #[inline(always)]
+ pub const fn new(value: $internal) -> Option<Self> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ if value < MIN || value > MAX {
+ None
+ } else {
+ // Safety: The value is in range.
+ Some(unsafe { Self::new_unchecked(value) })
+ }
+ }
+
+ /// Creates a ranged integer with a statically known value. **Fails to compile** if the
+ /// value is not in range.
+ #[inline(always)]
+ pub const fn new_static<const VALUE: $internal>() -> Self {
+ <($type<MIN, VALUE>, $type<VALUE, MAX>) as $crate::traits::StaticIsValid>::ASSERT;
+ // Safety: The value is in range.
+ unsafe { Self::new_unchecked(VALUE) }
+ }
+
+ /// Creates a ranged integer with the given value, saturating if it is out of range.
+ #[inline]
+ pub const fn new_saturating(value: $internal) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ if value < MIN {
+ Self::MIN
+ } else if value > MAX {
+ Self::MAX
+ } else {
+ // Safety: The value is in range.
+ unsafe { Self::new_unchecked(value) }
+ }
+ }
+
+ /// Expand the range that the value may be in. **Fails to compile** if the new range is
+ /// not a superset of the current range.
+ #[inline(always)]
+ pub const fn expand<const NEW_MIN: $internal, const NEW_MAX: $internal>(
+ self,
+ ) -> $type<NEW_MIN, NEW_MAX> {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ <$type<NEW_MIN, NEW_MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ <($type<MIN, MAX>, $type<NEW_MIN, NEW_MAX>) as $crate::traits::ExpandIsValid>
+ ::ASSERT;
+ // Safety: The range is widened.
+ unsafe { $type::new_unchecked(self.get()) }
+ }
+
+ /// Attempt to narrow the range that the value may be in. Returns `None` if the value
+ /// is outside the new range. **Fails to compile** if the new range is not a subset of
+ /// the current range.
+ #[inline(always)]
+ pub const fn narrow<
+ const NEW_MIN: $internal,
+ const NEW_MAX: $internal,
+ >(self) -> Option<$type<NEW_MIN, NEW_MAX>> {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ <$type<NEW_MIN, NEW_MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ <($type<MIN, MAX>, $type<NEW_MIN, NEW_MAX>) as $crate::traits::NarrowIsValid>
+ ::ASSERT;
+ $type::<NEW_MIN, NEW_MAX>::new(self.get())
+ }
+
+ /// Converts a string slice in a given base to an integer.
+ ///
+ /// The string is expected to be an optional `+` or `-` sign followed by digits. Leading
+ /// and trailing whitespace represent an error. Digits are a subset of these characters,
+ /// depending on `radix`:
+ ///
+ /// - `0-9`
+ /// - `a-z`
+ /// - `A-Z`
+ ///
+ /// # Panics
+ ///
+ /// Panics if `radix` is not in the range `2..=36`.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```rust
+ #[doc = concat!("# use deranged::", stringify!($type), ";")]
+ #[doc = concat!(
+ "assert_eq!(",
+ stringify!($type),
+ "::<5, 10>::from_str_radix(\"A\", 16), Ok(",
+ stringify!($type),
+ "::new_static::<10>()));",
+ )]
+ /// ```
+ #[inline]
+ pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ match $internal::from_str_radix(src, radix) {
+ Ok(value) if value > MAX => {
+ Err(ParseIntError { kind: IntErrorKind::PosOverflow })
+ }
+ Ok(value) if value < MIN => {
+ Err(ParseIntError { kind: IntErrorKind::NegOverflow })
+ }
+ // Safety: If the value was out of range, it would have been caught in a
+ // previous arm.
+ Ok(value) => Ok(unsafe { Self::new_unchecked(value) }),
+ Err(e) => Err(ParseIntError { kind: e.kind().clone() }),
+ }
+ }
+
+ /// Checked integer addition. Computes `self + rhs`, returning `None` if the resulting
+ /// value is out of range.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn checked_add(self, rhs: $internal) -> Option<Self> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new(const_try_opt!(self.get().checked_add(rhs)))
+ }
+
+ /// Unchecked integer addition. Computes `self + rhs`, assuming that the result is in
+ /// range.
+ ///
+ /// # Safety
+ ///
+ /// The result of `self + rhs` must be in the range `MIN..=MAX`.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline(always)]
+ pub const unsafe fn unchecked_add(self, rhs: $internal) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: The caller must ensure that the result is in range.
+ unsafe {
+ Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_add(rhs)))
+ }
+ }
+
+ /// Checked integer addition. Computes `self - rhs`, returning `None` if the resulting
+ /// value is out of range.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn checked_sub(self, rhs: $internal) -> Option<Self> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new(const_try_opt!(self.get().checked_sub(rhs)))
+ }
+
+ /// Unchecked integer subtraction. Computes `self - rhs`, assuming that the result is in
+ /// range.
+ ///
+ /// # Safety
+ ///
+ /// The result of `self - rhs` must be in the range `MIN..=MAX`.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline(always)]
+ pub const unsafe fn unchecked_sub(self, rhs: $internal) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: The caller must ensure that the result is in range.
+ unsafe {
+ Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_sub(rhs)))
+ }
+ }
+
+ /// Checked integer addition. Computes `self * rhs`, returning `None` if the resulting
+ /// value is out of range.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn checked_mul(self, rhs: $internal) -> Option<Self> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new(const_try_opt!(self.get().checked_mul(rhs)))
+ }
+
+ /// Unchecked integer multiplication. Computes `self * rhs`, assuming that the result is
+ /// in range.
+ ///
+ /// # Safety
+ ///
+ /// The result of `self * rhs` must be in the range `MIN..=MAX`.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline(always)]
+ pub const unsafe fn unchecked_mul(self, rhs: $internal) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: The caller must ensure that the result is in range.
+ unsafe {
+ Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_mul(rhs)))
+ }
+ }
+
+ /// Checked integer addition. Computes `self / rhs`, returning `None` if `rhs == 0` or
+ /// if the resulting value is out of range.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn checked_div(self, rhs: $internal) -> Option<Self> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new(const_try_opt!(self.get().checked_div(rhs)))
+ }
+
+ /// Unchecked integer division. Computes `self / rhs`, assuming that `rhs != 0` and that
+ /// the result is in range.
+ ///
+ /// # Safety
+ ///
+ /// `self` must not be zero and the result of `self / rhs` must be in the range
+ /// `MIN..=MAX`.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline(always)]
+ pub const unsafe fn unchecked_div(self, rhs: $internal) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: The caller must ensure that the result is in range and that `rhs` is not
+ // zero.
+ unsafe {
+ Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_div(rhs)))
+ }
+ }
+
+ /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` if
+ /// `rhs == 0` or if the resulting value is out of range.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn checked_div_euclid(self, rhs: $internal) -> Option<Self> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new(const_try_opt!(self.get().checked_div_euclid(rhs)))
+ }
+
+ /// Unchecked Euclidean division. Computes `self.div_euclid(rhs)`, assuming that
+ /// `rhs != 0` and that the result is in range.
+ ///
+ /// # Safety
+ ///
+ /// `self` must not be zero and the result of `self.div_euclid(rhs)` must be in the
+ /// range `MIN..=MAX`.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline(always)]
+ pub const unsafe fn unchecked_div_euclid(self, rhs: $internal) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: The caller must ensure that the result is in range and that `rhs` is not
+ // zero.
+ unsafe {
+ Self::new_unchecked(
+ unsafe_unwrap_unchecked!(self.get().checked_div_euclid(rhs))
+ )
+ }
+ }
+
+ if_unsigned!($is_signed
+ /// Remainder. Computes `self % rhs`, statically guaranteeing that the returned value
+ /// is in range.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn rem<const RHS_VALUE: $internal>(
+ self,
+ rhs: $type<RHS_VALUE, RHS_VALUE>,
+ ) -> $type<0, RHS_VALUE> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: The result is guaranteed to be in range due to the nature of remainder on
+ // unsigned integers.
+ unsafe { $type::new_unchecked(self.get() % rhs.get()) }
+ });
+
+ /// Checked integer remainder. Computes `self % rhs`, returning `None` if `rhs == 0` or
+ /// if the resulting value is out of range.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn checked_rem(self, rhs: $internal) -> Option<Self> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new(const_try_opt!(self.get().checked_rem(rhs)))
+ }
+
+ /// Unchecked remainder. Computes `self % rhs`, assuming that `rhs != 0` and that the
+ /// result is in range.
+ ///
+ /// # Safety
+ ///
+ /// `self` must not be zero and the result of `self % rhs` must be in the range
+ /// `MIN..=MAX`.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline(always)]
+ pub const unsafe fn unchecked_rem(self, rhs: $internal) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: The caller must ensure that the result is in range and that `rhs` is not
+ // zero.
+ unsafe {
+ Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_rem(rhs)))
+ }
+ }
+
+ /// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` if
+ /// `rhs == 0` or if the resulting value is out of range.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn checked_rem_euclid(self, rhs: $internal) -> Option<Self> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new(const_try_opt!(self.get().checked_rem_euclid(rhs)))
+ }
+
+ /// Unchecked Euclidean remainder. Computes `self.rem_euclid(rhs)`, assuming that
+ /// `rhs != 0` and that the result is in range.
+ ///
+ /// # Safety
+ ///
+ /// `self` must not be zero and the result of `self.rem_euclid(rhs)` must be in the
+ /// range `MIN..=MAX`.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline(always)]
+ pub const unsafe fn unchecked_rem_euclid(self, rhs: $internal) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: The caller must ensure that the result is in range and that `rhs` is not
+ // zero.
+ unsafe {
+ Self::new_unchecked(
+ unsafe_unwrap_unchecked!(self.get().checked_rem_euclid(rhs))
+ )
+ }
+ }
+
+ /// Checked negation. Computes `-self`, returning `None` if the resulting value is out
+ /// of range.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn checked_neg(self) -> Option<Self> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new(const_try_opt!(self.get().checked_neg()))
+ }
+
+ /// Unchecked negation. Computes `-self`, assuming that `-self` is in range.
+ ///
+ /// # Safety
+ ///
+ /// The result of `-self` must be in the range `MIN..=MAX`.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline(always)]
+ pub const unsafe fn unchecked_neg(self) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: The caller must ensure that the result is in range.
+ unsafe { Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_neg())) }
+ }
+
+ /// Negation. Computes `self.neg()`, **failing to compile** if the result is not
+ /// guaranteed to be in range.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline(always)]
+ pub const fn neg(self) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ <Self as $crate::traits::NegIsSafe>::ASSERT;
+ // Safety: The compiler asserts that the result is in range.
+ unsafe { self.unchecked_neg() }
+ }
+
+ /// Checked shift left. Computes `self << rhs`, returning `None` if the resulting value
+ /// is out of range.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new(const_try_opt!(self.get().checked_shl(rhs)))
+ }
+
+ /// Unchecked shift left. Computes `self << rhs`, assuming that the result is in range.
+ ///
+ /// # Safety
+ ///
+ /// The result of `self << rhs` must be in the range `MIN..=MAX`.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline(always)]
+ pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: The caller must ensure that the result is in range.
+ unsafe {
+ Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_shl(rhs)))
+ }
+ }
+
+ /// Checked shift right. Computes `self >> rhs`, returning `None` if
+ /// the resulting value is out of range.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new(const_try_opt!(self.get().checked_shr(rhs)))
+ }
+
+ /// Unchecked shift right. Computes `self >> rhs`, assuming that the result is in range.
+ ///
+ /// # Safety
+ ///
+ /// The result of `self >> rhs` must be in the range `MIN..=MAX`.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline(always)]
+ pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: The caller must ensure that the result is in range.
+ unsafe {
+ Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_shr(rhs)))
+ }
+ }
+
+ if_signed!($is_signed
+ /// Checked absolute value. Computes `self.abs()`, returning `None` if the resulting
+ /// value is out of range.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn checked_abs(self) -> Option<Self> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new(const_try_opt!(self.get().checked_abs()))
+ }
+
+ /// Unchecked absolute value. Computes `self.abs()`, assuming that the result is in
+ /// range.
+ ///
+ /// # Safety
+ ///
+ /// The result of `self.abs()` must be in the range `MIN..=MAX`.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline(always)]
+ pub const unsafe fn unchecked_abs(self) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: The caller must ensure that the result is in range.
+ unsafe { Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_abs())) }
+ }
+
+ /// Absolute value. Computes `self.abs()`, **failing to compile** if the result is not
+ /// guaranteed to be in range.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline(always)]
+ pub const fn abs(self) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ <Self as $crate::traits::AbsIsSafe>::ASSERT;
+ // Safety: The compiler asserts that the result is in range.
+ unsafe { self.unchecked_abs() }
+ });
+
+ /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if the resulting
+ /// value is out of range.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn checked_pow(self, exp: u32) -> Option<Self> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new(const_try_opt!(self.get().checked_pow(exp)))
+ }
+
+ /// Unchecked exponentiation. Computes `self.pow(exp)`, assuming that the result is in
+ /// range.
+ ///
+ /// # Safety
+ ///
+ /// The result of `self.pow(exp)` must be in the range `MIN..=MAX`.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline(always)]
+ pub const unsafe fn unchecked_pow(self, exp: u32) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: The caller must ensure that the result is in range.
+ unsafe {
+ Self::new_unchecked(unsafe_unwrap_unchecked!(self.get().checked_pow(exp)))
+ }
+ }
+
+ /// Saturating integer addition. Computes `self + rhs`, saturating at the numeric
+ /// bounds.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn saturating_add(self, rhs: $internal) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new_saturating(self.get().saturating_add(rhs))
+ }
+
+ /// Saturating integer subtraction. Computes `self - rhs`, saturating at the numeric
+ /// bounds.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn saturating_sub(self, rhs: $internal) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new_saturating(self.get().saturating_sub(rhs))
+ }
+
+ if_signed!($is_signed
+ /// Saturating integer negation. Computes `self - rhs`, saturating at the numeric
+ /// bounds.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn saturating_neg(self) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new_saturating(self.get().saturating_neg())
+ });
+
+ if_signed!($is_signed
+ /// Saturating absolute value. Computes `self.abs()`, saturating at the numeric bounds.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn saturating_abs(self) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new_saturating(self.get().saturating_abs())
+ });
+
+ /// Saturating integer multiplication. Computes `self * rhs`, saturating at the numeric
+ /// bounds.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn saturating_mul(self, rhs: $internal) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new_saturating(self.get().saturating_mul(rhs))
+ }
+
+ /// Saturating integer exponentiation. Computes `self.pow(exp)`, saturating at the
+ /// numeric bounds.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ pub const fn saturating_pow(self, exp: u32) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new_saturating(self.get().saturating_pow(exp))
+ }
+
+ /// Compute the `rem_euclid` of this type with its unsigned type equivalent
+ // Not public because it doesn't match stdlib's "method_unsigned implemented only for signed type" tradition.
+ // Also because this isn't implemented for normal types in std.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
+ const fn rem_euclid_unsigned(
+ rhs: $internal,
+ range_len: $unsigned_type
+ ) -> $unsigned_type {
+ #[allow(unused_comparisons)]
+ if rhs >= 0 {
+ (rhs as $unsigned_type) % range_len
+ } else {
+ // Let ux refer to an n bit unsigned and ix refer to an n bit signed integer.
+ // Can't write -ux or ux::abs() method. This gets around compilation error.
+ // `wrapping_sub` is to handle rhs = ix::MIN since ix::MIN = -ix::MAX-1
+ let rhs_abs = ($internal::wrapping_sub(0, rhs)) as $unsigned_type;
+ // Largest multiple of range_len <= type::MAX is lowest if range_len * 2 > ux::MAX -> range_len >= ux::MAX / 2 + 1
+ // Also = 0 in mod range_len arithmetic.
+ // Sub from this large number rhs_abs (same as sub -rhs = -(-rhs) = add rhs) to get rhs % range_len
+ // ix::MIN = -2^(n-1) so 0 <= rhs_abs <= 2^(n-1)
+ // ux::MAX / 2 + 1 = 2^(n-1) so this subtraction will always be a >= 0 after subtraction
+ // Thus converting rhs signed negative to equivalent positive value in mod range_len arithmetic
+ ((($unsigned_type::MAX / range_len) * range_len) - (rhs_abs)) % range_len
+ }
+ }
+
+ /// Wrapping integer addition. Computes `self + rhs`, wrapping around the numeric
+ /// bounds.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
+ pub const fn wrapping_add(self, rhs: $internal) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Forward to internal type's impl if same as type.
+ if MIN == $internal::MIN && MAX == $internal::MAX {
+ // Safety: std's wrapping methods match ranged arithmetic when the range is the internal datatype's range.
+ return unsafe { Self::new_unchecked(self.get().wrapping_add(rhs)) }
+ }
+
+ let inner = self.get();
+
+ // Won't overflow because of std impl forwarding.
+ let range_len = MAX.abs_diff(MIN) + 1;
+
+ // Calculate the offset with proper handling for negative rhs
+ let offset = Self::rem_euclid_unsigned(rhs, range_len);
+
+ let greater_vals = MAX.abs_diff(inner);
+ // No wrap
+ if offset <= greater_vals {
+ // Safety:
+ // if inner >= 0 -> No overflow beyond range (offset <= greater_vals)
+ // if inner < 0: Same as >=0 with caveat:
+ // `(signed as unsigned).wrapping_add(unsigned) as signed` is the same as
+ // `signed::checked_add_unsigned(unsigned).unwrap()` or `wrapping_add_unsigned`
+ // (the difference doesn't matter since it won't overflow),
+ // but unsigned integers don't have either method so it won't compile that way.
+ unsafe { Self::new_unchecked(
+ ((inner as $unsigned_type).wrapping_add(offset)) as $internal
+ ) }
+ }
+ // Wrap
+ else {
+ // Safety:
+ // - offset < range_len by rem_euclid (MIN + ... safe)
+ // - offset > greater_vals from if statement (offset - (greater_vals + 1) safe)
+ //
+ // again using `(signed as unsigned).wrapping_add(unsigned) as signed` = `checked_add_unsigned` trick
+ unsafe { Self::new_unchecked(
+ ((MIN as $unsigned_type).wrapping_add(
+ offset - (greater_vals + 1)
+ )) as $internal
+ ) }
+ }
+ }
+
+ /// Wrapping integer subtraction. Computes `self - rhs`, wrapping around the numeric
+ /// bounds.
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[inline]
+ #[allow(trivial_numeric_casts)] // needed since some casts have to send unsigned -> unsigned to handle signed -> unsigned
+ pub const fn wrapping_sub(self, rhs: $internal) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Forward to internal type's impl if same as type.
+ if MIN == $internal::MIN && MAX == $internal::MAX {
+ // Safety: std's wrapping methods match ranged arithmetic when the range is the internal datatype's range.
+ return unsafe { Self::new_unchecked(self.get().wrapping_sub(rhs)) }
+ }
+
+ let inner = self.get();
+
+ // Won't overflow because of std impl forwarding.
+ let range_len = MAX.abs_diff(MIN) + 1;
+
+ // Calculate the offset with proper handling for negative rhs
+ let offset = Self::rem_euclid_unsigned(rhs, range_len);
+
+ let lesser_vals = MIN.abs_diff(inner);
+ // No wrap
+ if offset <= lesser_vals {
+ // Safety:
+ // if inner >= 0 -> No overflow beyond range (offset <= greater_vals)
+ // if inner < 0: Same as >=0 with caveat:
+ // `(signed as unsigned).wrapping_sub(unsigned) as signed` is the same as
+ // `signed::checked_sub_unsigned(unsigned).unwrap()` or `wrapping_sub_unsigned`
+ // (the difference doesn't matter since it won't overflow below 0),
+ // but unsigned integers don't have either method so it won't compile that way.
+ unsafe { Self::new_unchecked(
+ ((inner as $unsigned_type).wrapping_sub(offset)) as $internal
+ ) }
+ }
+ // Wrap
+ else {
+ // Safety:
+ // - offset < range_len by rem_euclid (MAX - ... safe)
+ // - offset > lesser_vals from if statement (offset - (lesser_vals + 1) safe)
+ //
+ // again using `(signed as unsigned).wrapping_sub(unsigned) as signed` = `checked_sub_unsigned` trick
+ unsafe { Self::new_unchecked(
+ ((MAX as $unsigned_type).wrapping_sub(
+ offset - (lesser_vals + 1)
+ )) as $internal
+ ) }
+ }
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> $optional_type<MIN, MAX> {
+ /// The value used as the niche. Must not be in the range `MIN..=MAX`.
+ const NICHE: $internal = match (MIN, MAX) {
+ ($internal::MIN, $internal::MAX) => panic!("type has no niche"),
+ ($internal::MIN, _) => $internal::MAX,
+ (_, _) => $internal::MIN,
+ };
+
+ /// An optional ranged value that is not present.
+ #[allow(non_upper_case_globals)]
+ pub const None: Self = Self(Self::NICHE);
+
+ /// Creates an optional ranged value that is present.
+ #[allow(non_snake_case)]
+ #[inline(always)]
+ pub const fn Some(value: $type<MIN, MAX>) -> Self {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ Self(value.get())
+ }
+
+ /// Returns the value as the standard library's [`Option`] type.
+ #[inline(always)]
+ pub const fn get(self) -> Option<$type<MIN, MAX>> {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ if self.0 == Self::NICHE {
+ None
+ } else {
+ // Safety: A stored value that is not the niche is always in range.
+ Some(unsafe { $type::new_unchecked(self.0) })
+ }
+ }
+
+ /// Creates an optional ranged integer without checking the value.
+ ///
+ /// # Safety
+ ///
+ /// The value must be within the range `MIN..=MAX`. As the value used for niche
+ /// value optimization is unspecified, the provided value must not be the niche
+ /// value.
+ #[inline(always)]
+ pub const unsafe fn some_unchecked(value: $internal) -> Self {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: The caller must ensure that the value is in range.
+ unsafe { $crate::assert_unchecked(MIN <= value && value <= MAX) };
+ Self(value)
+ }
+
+ /// Obtain the inner value of the struct. This is useful for comparisons.
+ #[inline(always)]
+ pub(crate) const fn inner(self) -> $internal {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ self.0
+ }
+
+ /// Obtain the value of the struct as an `Option` of the primitive type.
+ #[inline(always)]
+ pub const fn get_primitive(self) -> Option<$internal> {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ Some(const_try_opt!(self.get()).get())
+ }
+
+ /// Returns `true` if the value is the niche value.
+ #[inline(always)]
+ pub const fn is_none(&self) -> bool {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ self.get().is_none()
+ }
+
+ /// Returns `true` if the value is not the niche value.
+ #[inline(always)]
+ pub const fn is_some(&self) -> bool {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ self.get().is_some()
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> fmt::Debug for $type<MIN, MAX> {
+ #[inline(always)]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ self.get().fmt(f)
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> fmt::Debug for $optional_type<MIN, MAX> {
+ #[inline(always)]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ self.get().fmt(f)
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> fmt::Display for $type<MIN, MAX> {
+ #[inline(always)]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ self.get().fmt(f)
+ }
+ }
+
+ #[cfg(feature = "powerfmt")]
+ impl<
+ const MIN: $internal,
+ const MAX: $internal,
+ > smart_display::SmartDisplay for $type<MIN, MAX> {
+ type Metadata = <$internal as smart_display::SmartDisplay>::Metadata;
+
+ #[inline(always)]
+ fn metadata(
+ &self,
+ f: smart_display::FormatterOptions,
+ ) -> smart_display::Metadata<'_, Self> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ self.get_ref().metadata(f).reuse()
+ }
+
+ #[inline(always)]
+ fn fmt_with_metadata(
+ &self,
+ f: &mut fmt::Formatter<'_>,
+ metadata: smart_display::Metadata<'_, Self>,
+ ) -> fmt::Result {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ self.get().fmt_with_metadata(f, metadata.reuse())
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> Default for $optional_type<MIN, MAX> {
+ #[inline(always)]
+ fn default() -> Self {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ Self::None
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> AsRef<$internal> for $type<MIN, MAX> {
+ #[inline(always)]
+ fn as_ref(&self) -> &$internal {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ &self.get_ref()
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> Borrow<$internal> for $type<MIN, MAX> {
+ #[inline(always)]
+ fn borrow(&self) -> &$internal {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ &self.get_ref()
+ }
+ }
+
+ impl<
+ const MIN_A: $internal,
+ const MAX_A: $internal,
+ const MIN_B: $internal,
+ const MAX_B: $internal,
+ > PartialEq<$type<MIN_B, MAX_B>> for $type<MIN_A, MAX_A> {
+ #[inline(always)]
+ fn eq(&self, other: &$type<MIN_B, MAX_B>) -> bool {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ <$type<MIN_B, MAX_B> as $crate::traits::RangeIsValid>::ASSERT;
+ self.get() == other.get()
+ }
+ }
+
+ impl<
+ const MIN_A: $internal,
+ const MAX_A: $internal,
+ const MIN_B: $internal,
+ const MAX_B: $internal,
+ > PartialEq<$optional_type<MIN_B, MAX_B>> for $optional_type<MIN_A, MAX_A> {
+ #[inline(always)]
+ fn eq(&self, other: &$optional_type<MIN_B, MAX_B>) -> bool {
+ <$type<MIN_A, MAX_A> as $crate::traits::RangeIsValid>::ASSERT;
+ <$type<MIN_B, MAX_B> as $crate::traits::RangeIsValid>::ASSERT;
+ self.inner() == other.inner()
+ }
+ }
+
+ impl<
+ const MIN_A: $internal,
+ const MAX_A: $internal,
+ const MIN_B: $internal,
+ const MAX_B: $internal,
+ > PartialOrd<$type<MIN_B, MAX_B>> for $type<MIN_A, MAX_A> {
+ #[inline(always)]
+ fn partial_cmp(&self, other: &$type<MIN_B, MAX_B>) -> Option<Ordering> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ <$type<MIN_B, MAX_B> as $crate::traits::RangeIsValid>::ASSERT;
+ self.get().partial_cmp(&other.get())
+ }
+ }
+
+ impl<
+ const MIN_A: $internal,
+ const MAX_A: $internal,
+ const MIN_B: $internal,
+ const MAX_B: $internal,
+ > PartialOrd<$optional_type<MIN_B, MAX_B>> for $optional_type<MIN_A, MAX_A> {
+ #[inline]
+ fn partial_cmp(&self, other: &$optional_type<MIN_B, MAX_B>) -> Option<Ordering> {
+ <$type<MIN_A, MAX_A> as $crate::traits::RangeIsValid>::ASSERT;
+ <$type<MIN_B, MAX_B> as $crate::traits::RangeIsValid>::ASSERT;
+ if self.is_none() && other.is_none() {
+ Some(Ordering::Equal)
+ } else if self.is_none() {
+ Some(Ordering::Less)
+ } else if other.is_none() {
+ Some(Ordering::Greater)
+ } else {
+ self.inner().partial_cmp(&other.inner())
+ }
+ }
+ }
+
+ impl<
+ const MIN: $internal,
+ const MAX: $internal,
+ > Ord for $optional_type<MIN, MAX> {
+ #[inline]
+ fn cmp(&self, other: &Self) -> Ordering {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ if self.is_none() && other.is_none() {
+ Ordering::Equal
+ } else if self.is_none() {
+ Ordering::Less
+ } else if other.is_none() {
+ Ordering::Greater
+ } else {
+ self.inner().cmp(&other.inner())
+ }
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> fmt::Binary for $type<MIN, MAX> {
+ #[inline(always)]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ self.get().fmt(f)
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> fmt::LowerHex for $type<MIN, MAX> {
+ #[inline(always)]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ self.get().fmt(f)
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> fmt::UpperHex for $type<MIN, MAX> {
+ #[inline(always)]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ self.get().fmt(f)
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> fmt::LowerExp for $type<MIN, MAX> {
+ #[inline(always)]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ self.get().fmt(f)
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> fmt::UpperExp for $type<MIN, MAX> {
+ #[inline(always)]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ self.get().fmt(f)
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> fmt::Octal for $type<MIN, MAX> {
+ #[inline(always)]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ self.get().fmt(f)
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> From<$type<MIN, MAX>> for $internal {
+ #[inline(always)]
+ fn from(value: $type<MIN, MAX>) -> Self {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ value.get()
+ }
+ }
+
+ impl<
+ const MIN: $internal,
+ const MAX: $internal,
+ > From<$type<MIN, MAX>> for $optional_type<MIN, MAX> {
+ #[inline(always)]
+ fn from(value: $type<MIN, MAX>) -> Self {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ Self::Some(value)
+ }
+ }
+
+ impl<
+ const MIN: $internal,
+ const MAX: $internal,
+ > From<Option<$type<MIN, MAX>>> for $optional_type<MIN, MAX> {
+ #[inline(always)]
+ fn from(value: Option<$type<MIN, MAX>>) -> Self {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ match value {
+ Some(value) => Self::Some(value),
+ None => Self::None,
+ }
+ }
+ }
+
+ impl<
+ const MIN: $internal,
+ const MAX: $internal,
+ > From<$optional_type<MIN, MAX>> for Option<$type<MIN, MAX>> {
+ #[inline(always)]
+ fn from(value: $optional_type<MIN, MAX>) -> Self {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ value.get()
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> TryFrom<$internal> for $type<MIN, MAX> {
+ type Error = TryFromIntError;
+
+ #[inline]
+ fn try_from(value: $internal) -> Result<Self, Self::Error> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::new(value).ok_or(TryFromIntError)
+ }
+ }
+
+ impl<const MIN: $internal, const MAX: $internal> FromStr for $type<MIN, MAX> {
+ type Err = ParseIntError;
+
+ #[inline]
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ let value = s.parse::<$internal>().map_err(|e| ParseIntError {
+ kind: e.kind().clone()
+ })?;
+ if value < MIN {
+ Err(ParseIntError { kind: IntErrorKind::NegOverflow })
+ } else if value > MAX {
+ Err(ParseIntError { kind: IntErrorKind::PosOverflow })
+ } else {
+ // Safety: The value was previously checked for validity.
+ Ok(unsafe { Self::new_unchecked(value) })
+ }
+ }
+ }
+
+ #[cfg(feature = "serde")]
+ impl<const MIN: $internal, const MAX: $internal> serde::Serialize for $type<MIN, MAX> {
+ #[inline(always)]
+ fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ self.get().serialize(serializer)
+ }
+ }
+
+ #[cfg(feature = "serde")]
+ impl<
+ const MIN: $internal,
+ const MAX: $internal,
+ > serde::Serialize for $optional_type<MIN, MAX> {
+ #[inline(always)]
+ fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ self.get().serialize(serializer)
+ }
+ }
+
+ #[cfg(feature = "serde")]
+ impl<
+ 'de,
+ const MIN: $internal,
+ const MAX: $internal,
+ > serde::Deserialize<'de> for $type<MIN, MAX> {
+ #[inline]
+ fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ let internal = <$internal>::deserialize(deserializer)?;
+ Self::new(internal).ok_or_else(|| <D::Error as serde::de::Error>::invalid_value(
+ serde::de::Unexpected::Other("integer"),
+ #[cfg(feature = "alloc")] {
+ &alloc::format!("an integer in the range {}..={}", MIN, MAX).as_ref()
+ },
+ #[cfg(not(feature = "alloc"))] {
+ &"an integer in the valid range"
+ }
+ ))
+ }
+ }
+
+ #[cfg(feature = "serde")]
+ impl<
+ 'de,
+ const MIN: $internal,
+ const MAX: $internal,
+ > serde::Deserialize<'de> for $optional_type<MIN, MAX> {
+ #[inline]
+ fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ Ok(Self::Some($type::<MIN, MAX>::deserialize(deserializer)?))
+ }
+ }
+
+ #[cfg(feature = "rand08")]
+ impl<
+ const MIN: $internal,
+ const MAX: $internal,
+ > rand08::distributions::Distribution<$type<MIN, MAX>> for rand08::distributions::Standard {
+ #[inline]
+ fn sample<R: rand08::Rng + ?Sized>(&self, rng: &mut R) -> $type<MIN, MAX> {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ $type::new(rng.gen_range(MIN..=MAX)).expect("rand failed to generate a valid value")
+ }
+ }
+
+ if_not_manual_rand_09! {
+ [$($($skips)+)?]
+ #[cfg(feature = "rand09")]
+ impl<
+ const MIN: $internal,
+ const MAX: $internal,
+ > rand09::distr::Distribution<$type<MIN, MAX>> for rand09::distr::StandardUniform {
+ #[inline]
+ fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> $type<MIN, MAX> {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ $type::new(rng.random_range(MIN..=MAX)).expect("rand failed to generate a valid value")
+ }
+ }
+ }
+
+ #[cfg(feature = "rand08")]
+ impl<
+ const MIN: $internal,
+ const MAX: $internal,
+ > rand08::distributions::Distribution<$optional_type<MIN, MAX>>
+ for rand08::distributions::Standard {
+ #[inline]
+ fn sample<R: rand08::Rng + ?Sized>(&self, rng: &mut R) -> $optional_type<MIN, MAX> {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ rng.r#gen::<Option<$type<MIN, MAX>>>().into()
+ }
+ }
+
+ #[cfg(feature = "rand09")]
+ impl<
+ const MIN: $internal,
+ const MAX: $internal,
+ > rand09::distr::Distribution<$optional_type<MIN, MAX>>
+ for rand09::distr::StandardUniform {
+ #[inline]
+ fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> $optional_type<MIN, MAX> {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ if rng.random() {
+ $optional_type::None
+ } else {
+ $optional_type::Some(rng.random::<$type<MIN, MAX>>())
+ }
+ }
+ }
+
+ #[cfg(feature = "num")]
+ impl<const MIN: $internal, const MAX: $internal> num_traits::Bounded for $type<MIN, MAX> {
+ #[inline(always)]
+ fn min_value() -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::MIN
+ }
+
+ #[inline(always)]
+ fn max_value() -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ Self::MAX
+ }
+ }
+
+ #[cfg(feature = "quickcheck")]
+ impl<const MIN: $internal, const MAX: $internal> quickcheck::Arbitrary for $type<MIN, MAX> {
+ #[inline]
+ fn arbitrary(g: &mut quickcheck::Gen) -> Self {
+ <Self as $crate::traits::RangeIsValid>::ASSERT;
+ // Safety: The `rem_euclid` call and addition ensure that the value is in range.
+ unsafe {
+ Self::new_unchecked($internal::arbitrary(g).rem_euclid(MAX - MIN + 1) + MIN)
+ }
+ }
+
+ #[inline]
+ fn shrink(&self) -> ::alloc::boxed::Box<dyn Iterator<Item = Self>> {
+ ::alloc::boxed::Box::new(
+ self.get()
+ .shrink()
+ .filter_map(Self::new)
+ )
+ }
+ }
+
+ #[cfg(feature = "quickcheck")]
+ impl<
+ const MIN: $internal,
+ const MAX: $internal,
+ > quickcheck::Arbitrary for $optional_type<MIN, MAX> {
+ #[inline]
+ fn arbitrary(g: &mut quickcheck::Gen) -> Self {
+ <$type<MIN, MAX> as $crate::traits::RangeIsValid>::ASSERT;
+ Option::<$type<MIN, MAX>>::arbitrary(g).into()
+ }
+
+ #[inline]
+ fn shrink(&self) -> ::alloc::boxed::Box<dyn Iterator<Item = Self>> {
+ ::alloc::boxed::Box::new(self.get().shrink().map(Self::from))
+ }
+ }
+ )*};
+}
+
+impl_ranged! {
+ RangedU8 {
+ mod_name: ranged_u8
+ internal: u8
+ signed: false
+ unsigned: u8
+ optional: OptionRangedU8
+ }
+ RangedU16 {
+ mod_name: ranged_u16
+ internal: u16
+ signed: false
+ unsigned: u16
+ optional: OptionRangedU16
+ }
+ RangedU32 {
+ mod_name: ranged_u32
+ internal: u32
+ signed: false
+ unsigned: u32
+ optional: OptionRangedU32
+ }
+ RangedU64 {
+ mod_name: ranged_u64
+ internal: u64
+ signed: false
+ unsigned: u64
+ optional: OptionRangedU64
+ }
+ RangedU128 {
+ mod_name: ranged_u128
+ internal: u128
+ signed: false
+ unsigned: u128
+ optional: OptionRangedU128
+ }
+ RangedUsize {
+ mod_name: ranged_usize
+ internal: usize
+ signed: false
+ unsigned: usize
+ optional: OptionRangedUsize
+ manual: [rand_09]
+ }
+ RangedI8 {
+ mod_name: ranged_i8
+ internal: i8
+ signed: true
+ unsigned: u8
+ optional: OptionRangedI8
+ }
+ RangedI16 {
+ mod_name: ranged_i16
+ internal: i16
+ signed: true
+ unsigned: u16
+ optional: OptionRangedI16
+ }
+ RangedI32 {
+ mod_name: ranged_i32
+ internal: i32
+ signed: true
+ unsigned: u32
+ optional: OptionRangedI32
+ }
+ RangedI64 {
+ mod_name: ranged_i64
+ internal: i64
+ signed: true
+ unsigned: u64
+ optional: OptionRangedI64
+ }
+ RangedI128 {
+ mod_name: ranged_i128
+ internal: i128
+ signed: true
+ unsigned: u128
+ optional: OptionRangedI128
+ }
+ RangedIsize {
+ mod_name: ranged_isize
+ internal: isize
+ signed: true
+ unsigned: usize
+ optional: OptionRangedIsize
+ manual: [rand_09]
+ }
+}
+
+#[cfg(feature = "rand09")]
+impl<const MIN: usize, const MAX: usize> rand09::distr::Distribution<RangedUsize<MIN, MAX>>
+ for rand09::distr::StandardUniform
+{
+ #[inline]
+ fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> RangedUsize<MIN, MAX> {
+ <RangedUsize<MIN, MAX> as traits::RangeIsValid>::ASSERT;
+
+ #[cfg(target_pointer_width = "16")]
+ let value = rng.random_range(MIN as u16..=MAX as u16) as usize;
+ #[cfg(target_pointer_width = "32")]
+ let value = rng.random_range(MIN as u32..=MAX as u32) as usize;
+ #[cfg(target_pointer_width = "64")]
+ let value = rng.random_range(MIN as u64..=MAX as u64) as usize;
+ #[cfg(not(any(
+ target_pointer_width = "16",
+ target_pointer_width = "32",
+ target_pointer_width = "64"
+ )))]
+ compile_error("platform has unusual (and unsupported) pointer width");
+
+ RangedUsize::new(value).expect("rand failed to generate a valid value")
+ }
+}
+
+#[cfg(feature = "rand09")]
+impl<const MIN: isize, const MAX: isize> rand09::distr::Distribution<RangedIsize<MIN, MAX>>
+ for rand09::distr::StandardUniform
+{
+ #[inline]
+ fn sample<R: rand09::Rng + ?Sized>(&self, rng: &mut R) -> RangedIsize<MIN, MAX> {
+ <RangedIsize<MIN, MAX> as traits::RangeIsValid>::ASSERT;
+
+ #[cfg(target_pointer_width = "16")]
+ let value = rng.random_range(MIN as i16..=MAX as i16) as isize;
+ #[cfg(target_pointer_width = "32")]
+ let value = rng.random_range(MIN as i32..=MAX as i32) as isize;
+ #[cfg(target_pointer_width = "64")]
+ let value = rng.random_range(MIN as i64..=MAX as i64) as isize;
+ #[cfg(not(any(
+ target_pointer_width = "16",
+ target_pointer_width = "32",
+ target_pointer_width = "64"
+ )))]
+ compile_error("platform has unusual (and unsupported) pointer width");
+
+ RangedIsize::new(value).expect("rand failed to generate a valid value")
+ }
+}
diff --git a/vendor/deranged/src/tests.rs b/vendor/deranged/src/tests.rs
new file mode 100644
index 00000000..3ea7530b
--- /dev/null
+++ b/vendor/deranged/src/tests.rs
@@ -0,0 +1,716 @@
+use core::hash::Hash;
+use std::format;
+use std::prelude::rust_2021::*;
+
+use crate::{
+ IntErrorKind, OptionRangedI128, OptionRangedI16, OptionRangedI32, OptionRangedI64,
+ OptionRangedI8, OptionRangedIsize, OptionRangedU128, OptionRangedU16, OptionRangedU32,
+ OptionRangedU64, OptionRangedU8, OptionRangedUsize, ParseIntError, RangedI128, RangedI16,
+ RangedI32, RangedI64, RangedI8, RangedIsize, RangedU128, RangedU16, RangedU32, RangedU64,
+ RangedU8, RangedUsize, TryFromIntError,
+};
+
+macro_rules! if_signed {
+ (signed $($x:tt)*) => { $($x)* };
+ (unsigned $($x:tt)*) => {};
+}
+
+macro_rules! if_unsigned {
+ (signed $($x:tt)*) => {};
+ (unsigned $($x:tt)*) => { $($x)* };
+}
+
+#[test]
+fn errors() {
+ assert_eq!(
+ TryFromIntError.to_string(),
+ "out of range integral type conversion attempted"
+ );
+ assert_eq!(TryFromIntError.clone(), TryFromIntError);
+ assert_eq!(format!("{TryFromIntError:?}"), "TryFromIntError");
+
+ assert_eq!(
+ ParseIntError {
+ kind: IntErrorKind::Empty,
+ }
+ .to_string(),
+ "cannot parse integer from empty string"
+ );
+ assert_eq!(
+ ParseIntError {
+ kind: IntErrorKind::InvalidDigit,
+ }
+ .to_string(),
+ "invalid digit found in string"
+ );
+ assert_eq!(
+ ParseIntError {
+ kind: IntErrorKind::PosOverflow,
+ }
+ .to_string(),
+ "number too large to fit in target type"
+ );
+ assert_eq!(
+ ParseIntError {
+ kind: IntErrorKind::NegOverflow,
+ }
+ .to_string(),
+ "number too small to fit in target type"
+ );
+ assert_eq!(
+ ParseIntError {
+ kind: IntErrorKind::Zero,
+ }
+ .to_string(),
+ "number would be zero for non-zero type"
+ );
+ assert_eq!(
+ format!(
+ "{:?}",
+ ParseIntError {
+ kind: IntErrorKind::Empty
+ }
+ ),
+ "ParseIntError { kind: Empty }"
+ );
+ assert_eq!(
+ ParseIntError {
+ kind: IntErrorKind::Empty
+ }
+ .clone(),
+ ParseIntError {
+ kind: IntErrorKind::Empty
+ }
+ );
+ assert_eq!(
+ ParseIntError {
+ kind: IntErrorKind::Empty
+ }
+ .kind(),
+ &IntErrorKind::Empty
+ );
+}
+
+macro_rules! tests {
+ ($($signed:ident $opt:ident $t:ident $inner:ident),* $(,)?) => {
+ #[test]
+ fn derives() {$(
+ assert_eq!($t::<5, 10>::MIN.clone(), $t::<5, 10>::MIN);
+ let mut hasher = std::collections::hash_map::DefaultHasher::new();
+ $t::<5, 10>::MIN.hash(&mut hasher);
+ assert_eq!(
+ $t::<5, 10>::MIN.cmp(&$t::<5, 10>::MAX),
+ core::cmp::Ordering::Less
+ );
+
+ assert_eq!($opt::<5, 10>::None.clone(), $opt::<5, 10>::None);
+ $opt::<5, 10>::None.hash(&mut hasher);
+ )*}
+
+ #[test]
+ fn expand() {$(
+ let expanded: $t::<0, 20> = $t::<5, 10>::MAX.expand();
+ assert_eq!(expanded, $t::<0, 20>::new_static::<10>());
+ )*}
+
+ #[test]
+ fn narrow() {$(
+ let narrowed: Option<$t::<10, 20>> = $t::<0, 20>::new_static::<10>().narrow();
+ assert_eq!(narrowed, Some($t::<10, 20>::MIN));
+ )*}
+
+ #[test]
+ fn new() {$(
+ assert!($t::<5, 10>::new(10).is_some());
+ assert!($t::<5, 10>::new(11).is_none());
+ )*}
+
+ #[test]
+ fn new_static() {$(
+ let six: $t::<5, 10> = $t::<5, 10>::new_static::<6>();
+ assert_eq!(Some(six), $t::<5, 10>::new(6));
+ )*}
+
+ #[test]
+ fn some_unchecked() {$(
+ // Safety: The value is in range.
+ unsafe {
+ assert_eq!($opt::<5, 10>::some_unchecked(10), $opt::Some($t::<5, 10>::MAX));
+ }
+ )*}
+
+ #[test]
+ fn is_some() {$(
+ assert!($opt::<5, 10>::Some($t::<5, 10>::MAX).is_some());
+ )*}
+
+ #[test]
+ fn is_none() {$(
+ assert!($opt::<5, 10>::None.is_none());
+ )*}
+
+ #[test]
+ fn is_some_by_ref() {$(
+ let value = $opt::<5, 10>::Some($t::<5, 10>::MAX);
+ assert!($opt::is_some(&value));
+ )*}
+
+ #[test]
+ fn is_none_by_ref() {$(
+ let value = $opt::<5, 10>::None;
+ assert!($opt::is_none(&value));
+ )*}
+
+ #[test]
+ fn default() {$(
+ assert_eq!($opt::<5, 10>::default(), $opt::<5, 10>::None);
+ )*}
+
+ #[test]
+ fn get() {$(
+ assert_eq!($t::<5, 10>::MAX.get(), 10);
+ assert_eq!($opt::<5, 10>::None.get(), None);
+ assert_eq!($opt::Some($t::<5, 10>::MAX).get(), Some($t::<5, 10>::MAX));
+ )*}
+
+ #[test]
+ fn get_primitive() {$(
+ assert_eq!($opt::Some($t::<5, 10>::MAX).get_primitive(), Some(10));
+ assert_eq!($opt::<5, 10>::None.get_primitive(), None);
+ )*}
+
+ #[test]
+ fn get_ref() {$(
+ assert_eq!($t::<5, 10>::MAX.get_ref(), &10);
+ )*}
+
+ #[test]
+ fn new_saturating() {$(
+ assert_eq!($t::<5, 10>::new_saturating(11), $t::<5, 10>::MAX);
+ assert_eq!($t::<5, 10>::new_saturating(0), $t::<5, 10>::MIN);
+ assert_eq!($t::<5, 10>::new_saturating(9), $t::<5, 10>::new_static::<9>());
+ )*}
+
+ #[test]
+ fn from_str_radix() {$(
+ assert_eq!($t::<5, 10>::from_str_radix("10", 10), Ok($t::<5, 10>::MAX));
+ assert_eq!($t::<5, 10>::from_str_radix("5", 10), Ok($t::<5, 10>::MIN));
+ assert_eq!(
+ $t::<5, 10>::from_str_radix("4", 10),
+ Err(ParseIntError { kind: IntErrorKind::NegOverflow }),
+ );
+ assert_eq!(
+ $t::<5, 10>::from_str_radix("11", 10),
+ Err(ParseIntError { kind: IntErrorKind::PosOverflow }),
+ );
+ assert_eq!(
+ $t::<5, 10>::from_str_radix("", 10),
+ Err(ParseIntError { kind: IntErrorKind::Empty }),
+ );
+ )*}
+
+ #[test]
+ fn checked_add() {$(
+ assert_eq!($t::<5, 10>::MAX.checked_add(1), None);
+ assert_eq!($t::<5, 10>::MAX.checked_add(0), Some($t::<5, 10>::MAX));
+ )*}
+
+ #[test]
+ fn unchecked_add() {$(
+ // Safety: The result is in range.
+ unsafe {
+ assert_eq!($t::<5, 10>::MIN.unchecked_add(5), $t::<5, 10>::MAX);
+ }
+ )*}
+
+ #[test]
+ fn checked_sub() {$(
+ assert_eq!($t::<5, 10>::MIN.checked_sub(1), None);
+ assert_eq!($t::<5, 10>::MIN.checked_sub(0), Some($t::<5, 10>::MIN));
+ )*}
+
+ #[test]
+ fn unchecked_sub() {$(
+ // Safety: The result is in range.
+ unsafe {
+ assert_eq!($t::<5, 10>::MAX.unchecked_sub(5), $t::<5, 10>::MIN);
+ }
+ )*}
+
+ #[test]
+ fn checked_mul() {$(
+ assert_eq!($t::<5, 10>::MAX.checked_mul(2), None);
+ assert_eq!($t::<5, 10>::MAX.checked_mul(1), Some($t::<5, 10>::MAX));
+ )*}
+
+ #[test]
+ fn unchecked_mul() {$(
+ // Safety: The result is in range.
+ unsafe {
+ assert_eq!($t::<5, 10>::MAX.unchecked_mul(1), $t::<5, 10>::MAX);
+ }
+ )*}
+
+ #[test]
+ fn checked_div() {$(
+ assert_eq!($t::<5, 10>::MAX.checked_div(3), None);
+ assert_eq!($t::<5, 10>::MAX.checked_div(2), $t::<5, 10>::new(5));
+ assert_eq!($t::<5, 10>::MAX.checked_div(1), Some($t::<5, 10>::MAX));
+ assert_eq!($t::<5, 10>::MAX.checked_div(0), None);
+ )*}
+
+ #[test]
+ fn unchecked_div() {$(
+ // Safety: The result is in range.
+ unsafe {
+ assert_eq!($t::<5, 10>::MAX.unchecked_div(1), $t::<5, 10>::MAX);
+ }
+ )*}
+
+ #[test]
+ fn checked_div_euclid() {$(
+ assert_eq!($t::<5, 10>::MAX.checked_div_euclid(3), None);
+ assert_eq!($t::<5, 10>::MAX.checked_div_euclid(2), $t::<5, 10>::new(5));
+ assert_eq!($t::<5, 10>::MAX.checked_div_euclid(1), Some($t::<5, 10>::MAX));
+ assert_eq!($t::<5, 10>::MAX.checked_div_euclid(0), None);
+ )*}
+
+ #[test]
+ fn unchecked_div_euclid() {$(
+ // Safety: The result is in range.
+ unsafe {
+ assert_eq!($t::<5, 10>::MAX.unchecked_div_euclid(1), $t::<5, 10>::MAX);
+ }
+ )*}
+
+ #[test]
+ fn rem() {$(if_unsigned! { $signed
+ assert_eq!($t::<5, 10>::MAX.rem($t::exact::<3>()), $t::<0, 3>::new_static::<1>());
+ assert_eq!($t::<5, 10>::MAX.rem($t::exact::<5>()), $t::<0, 5>::MIN);
+ })*}
+
+ #[test]
+ fn checked_rem() {$(
+ assert_eq!($t::<5, 10>::MAX.checked_rem(11), Some($t::<5, 10>::MAX));
+ assert_eq!($t::<5, 10>::MAX.checked_rem(5), None);
+ )*}
+
+ #[test]
+ fn unchecked_rem() {$(
+ // Safety: The result is in range.
+ unsafe {
+ assert_eq!($t::<5, 10>::MAX.unchecked_rem(11), $t::<5, 10>::MAX);
+ }
+ )*}
+
+ #[test]
+ fn checked_rem_euclid() {$(
+ assert_eq!($t::<5, 10>::MAX.checked_rem_euclid(11), Some($t::<5, 10>::MAX));
+ assert_eq!($t::<5, 10>::MAX.checked_rem_euclid(5), None);
+ )*}
+
+ #[test]
+ fn unchecked_rem_euclid() {$(
+ // Safety: The result is in range.
+ unsafe {
+ assert_eq!($t::<5, 10>::MAX.unchecked_rem_euclid(11), $t::<5, 10>::MAX);
+ }
+ )*}
+
+ #[test]
+ fn checked_neg() {$(
+ assert_eq!($t::<5, 10>::MIN.checked_neg(), None);
+ assert_eq!($t::<0, 10>::MIN.checked_neg(), Some($t::<0, 10>::MIN));
+ )*}
+
+ #[test]
+ fn unchecked_neg() {$(
+ // Safety: The result is in range.
+ unsafe {
+ assert_eq!($t::<0, 10>::MIN.unchecked_neg(), $t::<0, 10>::MIN);
+ }
+ )*}
+
+ #[test]
+ fn neg() {$( if_signed! { $signed
+ assert_eq!($t::<-10, 10>::MIN.neg(), $t::<-10, 10>::MAX);
+ })*}
+
+ #[test]
+ fn checked_shl() {$(
+ assert_eq!($t::<5, 10>::MAX.checked_shl(1), None);
+ assert_eq!($t::<5, 10>::MAX.checked_shl(0), Some($t::<5, 10>::MAX));
+ assert_eq!($t::<5, 10>::MIN.checked_shl(1), Some($t::<5, 10>::MAX));
+ )*}
+
+ #[test]
+ fn unchecked_shl() {$(
+ // Safety: The result is in range.
+ unsafe {
+ assert_eq!($t::<5, 10>::MAX.unchecked_shl(0), $t::<5, 10>::MAX);
+ assert_eq!($t::<5, 10>::MIN.unchecked_shl(1), $t::<5, 10>::MAX);
+ }
+ )*}
+
+ #[test]
+ fn checked_shr() {$(
+ assert_eq!($t::<5, 10>::MAX.checked_shr(2), None);
+ assert_eq!($t::<5, 10>::MAX.checked_shr(1), Some($t::<5, 10>::MIN));
+ assert_eq!($t::<5, 10>::MAX.checked_shr(0), Some($t::<5, 10>::MAX));
+ )*}
+
+ #[test]
+ fn unchecked_shr() {$(
+ // Safety: The result is in range.
+ unsafe {
+ assert_eq!($t::<5, 10>::MAX.unchecked_shr(1), $t::<5, 10>::MIN);
+ assert_eq!($t::<5, 10>::MAX.unchecked_shr(0), $t::<5, 10>::MAX);
+ }
+ )*}
+
+ #[test]
+ fn checked_abs() {$( if_signed! { $signed
+ assert_eq!($t::<5, 10>::MAX.checked_abs(), Some($t::<5, 10>::MAX));
+ assert_eq!($t::<-10, 10>::MIN.checked_abs(), Some($t::<-10, 10>::MAX));
+ assert_eq!($t::<-10, 0>::MIN.checked_abs(), None);
+ })*}
+
+ #[test]
+ fn unchecked_abs() { $(if_signed! { $signed
+ // Safety: The result is in range.
+ unsafe {
+ assert_eq!($t::<5, 10>::MAX.unchecked_abs(), $t::<5, 10>::MAX);
+ assert_eq!($t::<-10, 10>::MIN.unchecked_abs(), $t::<-10, 10>::MAX);
+ }
+ })*}
+
+ #[test]
+ fn abs() { $(if_signed! { $signed
+ assert_eq!($t::<-5, 10>::MIN.abs().get(), 5);
+ })*}
+
+ #[test]
+ fn checked_pow() {$(
+ assert_eq!($t::<5, 10>::MAX.checked_pow(0), None);
+ assert_eq!($t::<5, 10>::MAX.checked_pow(1), Some($t::<5, 10>::MAX));
+ assert_eq!($t::<5, 10>::MAX.checked_pow(2), None);
+ )*}
+
+ #[test]
+ fn unchecked_pow() {$(
+ // Safety: The result is in range.
+ unsafe {
+ assert_eq!($t::<5, 10>::MAX.unchecked_pow(1), $t::<5, 10>::MAX);
+ }
+ )*}
+
+ #[test]
+ fn saturating_add() {$(
+ assert_eq!($t::<5, 10>::MAX.saturating_add(0), $t::<5, 10>::MAX);
+ assert_eq!($t::<5, 10>::MAX.saturating_add(1), $t::<5, 10>::MAX);
+ )*}
+
+ #[test]
+ fn wrapping_add() {
+ $(
+ assert_eq!($t::<5, 10>::MAX.wrapping_add(0), $t::<5, 10>::MAX);
+ assert_eq!($t::<5, 10>::MAX.wrapping_add(1), $t::<5, 10>::MIN);
+ assert_eq!($t::<{ $inner::MIN }, { $inner::MAX }>::MAX.wrapping_add(1),
+ $t::<{ $inner::MIN }, { $inner::MAX }>::MIN);
+ for i in 1..127 {
+ assert_eq!(
+ $t::<{ $inner::MIN}, { $inner::MAX - 1 }>::MAX.wrapping_add(i),
+ $t::<{ $inner::MIN}, { $inner::MAX - 1 }>::new($inner::MIN + i - 1).unwrap_or_else(|| panic!("adding {i}+{} does not yield {}", $inner::MIN, $inner::MAX + i ))
+ );
+ }
+ )*
+ $(if_signed! { $signed
+ for i in 1..=127 {
+ assert_eq!($t::<-5, 126>::MIN.wrapping_add(-i), $t::<-5,126>::new(126-i+1).unwrap_or_else(|| panic!("adding {i}+{} does not yield {}", $inner::MIN, 126-i+1)));
+ assert_eq!($t::<-5, 126>::MIN.wrapping_add(i), $t::<-5,126>::new(-5+i).unwrap_or_else(|| panic!("adding {i}+{} does not yield {}", $inner::MIN, 126-i+1)));
+ }
+ for i in -127..=-1 {
+ assert_eq!($t::<-5, 126>::MIN.wrapping_add(i), $t::<-5,126>::new(126+i+1).unwrap_or_else(|| panic!("adding {i}+{} does not yield {}", $inner::MIN, 126-i+1)));
+ assert_eq!($t::<-5, 126>::MIN.wrapping_add(-i), $t::<-5,126>::new(-5-i).unwrap_or_else(|| panic!("adding {i}+{} does not yield {}", $inner::MIN, 126-i+1)));
+ }
+ assert_eq!($t::<-5, 126>::MIN.wrapping_add(-128), $t::<-5,126>::new(-1).unwrap_or_else(|| panic!("adding 128+{} does not yield -1", $inner::MIN)));
+ assert_eq!($t::<-5, 10>::MAX.wrapping_add(0), $t::<-5, 10>::MAX);
+ assert_eq!($t::<-5, -3>::MIN.wrapping_add(-1-3), $t::<-5, -3>::MAX);
+ assert_eq!($t::<-5, -3>::MIN.wrapping_add(-1-30), $t::<-5, -3>::MAX);
+ assert_eq!($t::<-5, -3>::MIN.wrapping_add(30), $t::<-5, -3>::MIN);
+ assert_eq!($t::<-5, -3>::MIN.wrapping_add(-30), $t::<-5, -3>::MIN);
+ assert_eq!($t::<-5, 10>::MAX.wrapping_add(25), $t::<-5, 10>::MIN.wrapping_add(24));
+ assert_eq!($t::<-5, 10>::MIN.wrapping_add(24), $t::<-5, 10>::MIN.wrapping_add(8));
+ assert_eq!($t::<-5, 10>::MAX.wrapping_add(1), $t::<-5, 10>::MIN);
+ assert_eq!($t::<-5, 10>::MIN.wrapping_add(-1), $t::<-5, 10>::MAX);
+ assert_eq!($t::<-5, 127>::MIN.wrapping_add(-1), $t::<-5, 127>::MAX);
+ assert_eq!($t::<-127, 126>::MIN.wrapping_add(-1), $t::<-127, 126>::MAX);
+ assert_eq!($t::<{ $inner::MIN }, { $inner::MAX }>::MIN.wrapping_add(-1),
+ $t::<{ $inner::MIN }, { $inner::MAX }>::MAX);
+ })*
+ }
+
+ #[test]
+ fn wrapping_sub() {
+ $(
+ assert_eq!($t::<5, 10>::MIN.wrapping_sub(0), $t::<5, 10>::MIN);
+ assert_eq!($t::<5, 10>::MIN.wrapping_sub(1), $t::<5, 10>::MAX);
+ assert_eq!($t::<5, 10>::new(5 + 1).unwrap().wrapping_sub(1), $t::<5, 10>::MIN);
+ assert_eq!($t::<5, 10>::MAX.wrapping_sub(1), $t::<5, 10>::new(10 - 1).unwrap());
+ assert_eq!($t::<{ $inner::MIN }, { $inner::MAX }>::MIN.wrapping_sub(1),
+ $t::<{ $inner::MIN }, { $inner::MAX }>::MAX);
+ for i in 1..127 {
+ assert_eq!(
+ $t::<{ $inner::MIN + 1 }, { $inner::MAX }>::MIN.wrapping_sub(i),
+ $t::<{ $inner::MIN + 1 }, { $inner::MAX }>::new($inner::MAX - i + 1).unwrap_or_else(|| panic!("failed test at iteration {i}"))
+ );
+ }
+ )*
+ $(if_signed! { $signed
+ for i in -127..=127 {
+ assert_eq!($t::<-5, 126>::MIN.wrapping_add(i), $t::<-5,126>::MIN.wrapping_sub(-i), "failed test at {i}");
+ assert_eq!($t::<-5, 126>::MIN.wrapping_add(-i), $t::<-5,126>::MIN.wrapping_sub(i), "failed test at {i}");
+ }
+ assert_eq!(
+ $t::<-5, 126>::MIN.wrapping_add(127).wrapping_add(1),
+ $t::<-5,126>::MIN.wrapping_sub(-128)
+ );
+ assert_eq!(
+ $t::<-5, 126>::MIN.wrapping_add(-128),
+ $t::<-5,126>::MIN.wrapping_sub(127).wrapping_sub(1)
+ );
+ })*
+ }
+
+ #[test]
+ fn saturating_sub() {$(
+ assert_eq!($t::<5, 10>::MIN.saturating_sub(0), $t::<5, 10>::MIN);
+ assert_eq!($t::<5, 10>::MIN.saturating_sub(1), $t::<5, 10>::MIN);
+ )*}
+
+ #[test]
+ fn saturating_neg() {$(if_signed! { $signed
+ assert_eq!($t::<5, 10>::MIN.saturating_neg(), $t::<5, 10>::MIN);
+ assert_eq!($t::<5, 10>::MAX.saturating_neg(), $t::<5, 10>::MIN);
+ assert_eq!($t::<-10, 0>::MIN.saturating_neg(), $t::<-10, 0>::MAX);
+ assert_eq!($t::<-10, 0>::MAX.saturating_neg(), $t::<-10, 0>::MAX);
+ })*}
+
+ #[test]
+ fn saturating_abs() {$(if_signed! { $signed
+ assert_eq!($t::<5, 10>::MIN.saturating_abs(), $t::<5, 10>::MIN);
+ assert_eq!($t::<5, 10>::MAX.saturating_abs(), $t::<5, 10>::MAX);
+ assert_eq!($t::<-10, 0>::MIN.saturating_abs(), $t::<-10, 0>::MAX);
+ assert_eq!($t::<-10, 0>::MAX.saturating_abs(), $t::<-10, 0>::MAX);
+ })*}
+
+ #[test]
+ fn saturating_mul() {$(
+ assert_eq!($t::<5, 10>::MIN.saturating_mul(0), $t::<5, 10>::MIN);
+ assert_eq!($t::<5, 10>::MIN.saturating_mul(1), $t::<5, 10>::MIN);
+ assert_eq!($t::<5, 10>::MIN.saturating_mul(2), $t::<5, 10>::MAX);
+ assert_eq!($t::<5, 10>::MIN.saturating_mul(3), $t::<5, 10>::MAX);
+ )*}
+
+ #[test]
+ fn saturating_pow() {$(
+ assert_eq!($t::<5, 10>::MIN.saturating_pow(0), $t::<5, 10>::MIN);
+ assert_eq!($t::<5, 10>::MIN.saturating_pow(1), $t::<5, 10>::MIN);
+ assert_eq!($t::<5, 10>::MIN.saturating_pow(2), $t::<5, 10>::MAX);
+ assert_eq!($t::<5, 10>::MIN.saturating_pow(3), $t::<5, 10>::MAX);
+ )*}
+
+ #[test]
+ fn as_ref() {$(
+ assert_eq!($t::<5, 10>::MIN.as_ref(), &5);
+ assert_eq!($t::<5, 10>::MAX.as_ref(), &10);
+ )*}
+
+ #[test]
+ fn borrow() {
+ use core::borrow::Borrow;
+ $(
+ assert_eq!(Borrow::<$inner>::borrow(&$t::<5, 10>::MIN), &5);
+ assert_eq!(Borrow::<$inner>::borrow(&$t::<5, 10>::MAX), &10);
+ )*
+ }
+
+ #[test]
+ fn formatting() {$(
+ let val = $t::<5, 10>::MAX;
+ assert_eq!(format!("{}", val), "10");
+ assert_eq!(format!("{:?}", val), "10");
+ assert_eq!(format!("{:b}", val), "1010");
+ assert_eq!(format!("{:o}", val), "12");
+ assert_eq!(format!("{:x}", val), "a");
+ assert_eq!(format!("{:X}", val), "A");
+ assert_eq!(format!("{:e}", val), "1e1");
+ assert_eq!(format!("{:E}", val), "1E1");
+
+ assert_eq!(format!("{:?}", $opt::Some($t::<5, 10>::MAX)), "Some(10)");
+ assert_eq!(format!("{:?}", $opt::<5, 10>::None), "None");
+ )*}
+
+ #[test]
+ fn ord() {$(
+ assert!($t::<5, 10>::MIN < $t::<5, 10>::MAX);
+ assert!($t::<5, 10>::MIN <= $t::<5, 10>::MAX);
+ assert!($t::<5, 10>::MAX > $t::<5, 10>::MIN);
+ assert!($t::<5, 10>::MAX >= $t::<5, 10>::MIN);
+
+ let none = $opt::<5, 10>::None;
+ let five = $opt::Some($t::<5, 10>::MIN);
+ let ten = $opt::Some($t::<5, 10>::MAX);
+
+ assert_eq!(none.cmp(&none), core::cmp::Ordering::Equal);
+ assert_eq!(five.cmp(&five), core::cmp::Ordering::Equal);
+ assert_eq!(ten.cmp(&ten), core::cmp::Ordering::Equal);
+ assert_eq!(none.cmp(&five), core::cmp::Ordering::Less);
+ assert_eq!(five.cmp(&ten), core::cmp::Ordering::Less);
+ assert_eq!(none.cmp(&ten), core::cmp::Ordering::Less);
+ assert_eq!(ten.cmp(&none), core::cmp::Ordering::Greater);
+
+ let none = $opt::<0, 10>::None;
+ let zero = $opt::Some($t::<0, 10>::MIN);
+ let ten = $opt::Some($t::<0, 10>::MAX);
+
+ assert_eq!(none.partial_cmp(&none), Some(core::cmp::Ordering::Equal));
+ assert_eq!(none.partial_cmp(&zero), Some(core::cmp::Ordering::Less));
+ assert_eq!(zero.partial_cmp(&ten), Some(core::cmp::Ordering::Less));
+ assert_eq!(none.partial_cmp(&ten), Some(core::cmp::Ordering::Less));
+ assert_eq!(ten.partial_cmp(&none), Some(core::cmp::Ordering::Greater));
+ )*}
+
+ #[test]
+ fn from() {$(
+ assert_eq!($inner::from($t::<5, 10>::MAX), 10);
+ assert_eq!($inner::from($t::<5, 10>::MIN), 5);
+
+ assert_eq!($opt::from($t::<5, 10>::MAX), $opt::Some($t::<5, 10>::MAX));
+ assert_eq!($opt::from(Some($t::<5, 10>::MAX)), $opt::Some($t::<5, 10>::MAX));
+ assert_eq!($opt::<5, 10>::from(None), $opt::<5, 10>::None);
+ assert_eq!(Option::from($opt::Some($t::<5, 10>::MAX)), Some($t::<5, 10>::MAX));
+ assert_eq!(Option::<$t<5, 10>>::from($opt::<5, 10>::None), None);
+ )*}
+
+ #[test]
+ fn try_from() {$(
+ assert_eq!($t::<5, 10>::try_from(10), Ok($t::<5, 10>::MAX));
+ assert_eq!($t::<5, 10>::try_from(5), Ok($t::<5, 10>::MIN));
+ assert_eq!($t::<5, 10>::try_from(4), Err(TryFromIntError));
+ assert_eq!($t::<5, 10>::try_from(11), Err(TryFromIntError));
+ )*}
+
+ #[test]
+ fn from_str() {$(
+ assert_eq!("10".parse::<$t<5, 10>>(), Ok($t::<5, 10>::MAX));
+ assert_eq!("5".parse::<$t<5, 10>>(), Ok($t::<5, 10>::MIN));
+ assert_eq!("4".parse::<$t<5, 10>>(), Err(ParseIntError { kind: IntErrorKind::NegOverflow }));
+ assert_eq!("11".parse::<$t<5, 10>>(), Err(ParseIntError { kind: IntErrorKind::PosOverflow }));
+ assert_eq!("".parse::<$t<5, 10>>(), Err(ParseIntError { kind: IntErrorKind::Empty }));
+ )*}
+
+ #[cfg(feature = "serde")]
+ #[test]
+ fn serde() -> serde_json::Result<()> {
+ $(
+ let val = $t::<5, 10>::MAX;
+ let serialized = serde_json::to_string(&val)?;
+ assert_eq!(serialized, "10");
+ let deserialized: $t<5, 10> = serde_json::from_str(&serialized)?;
+ assert_eq!(deserialized, val);
+
+ assert!(serde_json::from_str::<$t<5, 10>>("").is_err());
+ assert!(serde_json::from_str::<$t<5, 10>>("4").is_err());
+ assert!(serde_json::from_str::<$t<5, 10>>("11").is_err());
+
+ let val = $opt::<5, 10>::Some($t::<5, 10>::MAX);
+ let serialized = serde_json::to_string(&val)?;
+ assert_eq!(serialized, "10");
+ let deserialized: $opt<5, 10> = serde_json::from_str(&serialized)?;
+ assert_eq!(deserialized, val);
+
+ assert!(serde_json::from_str::<$opt<5, 10>>("").is_err());
+ assert!(serde_json::from_str::<$opt<5, 10>>("4").is_err());
+ assert!(serde_json::from_str::<$opt<5, 10>>("11").is_err());
+
+ let val = $opt::<5, 10>::None;
+ let serialized = serde_json::to_string(&val)?;
+ assert_eq!(serialized, "null");
+
+ assert!(serde_json::from_str::<$opt<5, 10>>("").is_err());
+ assert!(serde_json::from_str::<$opt<5, 10>>("4").is_err());
+ assert!(serde_json::from_str::<$opt<5, 10>>("11").is_err());
+ )*
+ Ok(())
+ }
+
+ #[cfg(feature = "rand08")]
+ #[test]
+ fn rand08() {$(
+ let rand_val: $t<5, 10> = rand08::random();
+ assert!(rand_val >= $t::<5, 10>::MIN);
+ assert!(rand_val <= $t::<5, 10>::MAX);
+
+ let rand: $opt<5, 10> = rand08::random();
+ if let Some(rand) = rand.get() {
+ assert!(rand >= $t::<5, 10>::MIN);
+ assert!(rand <= $t::<5, 10>::MAX);
+ }
+ )*}
+
+ #[cfg(feature = "rand09")]
+ #[test]
+ fn rand09() {$(
+ let rand_val: $t<5, 10> = rand09::random();
+ assert!(rand_val >= $t::<5, 10>::MIN);
+ assert!(rand_val <= $t::<5, 10>::MAX);
+
+ let rand: $opt<5, 10> = rand09::random();
+ if let Some(rand) = rand.get() {
+ assert!(rand >= $t::<5, 10>::MIN);
+ assert!(rand <= $t::<5, 10>::MAX);
+ }
+ )*}
+
+ #[cfg(feature = "num")]
+ #[test]
+ fn num() {$(
+ assert_eq!(<$t<5, 10> as num_traits::Bounded>::min_value(), $t::<5, 10>::MIN);
+ assert_eq!(<$t<5, 10> as num_traits::Bounded>::max_value(), $t::<5, 10>::MAX);
+ )*}
+
+ #[cfg(feature = "quickcheck")]
+ #[test]
+ fn quickcheck() {$(
+ #[allow(trivial_casts)]
+ quickcheck::quickcheck((|val| {
+ val >= $t::<5, 10>::MIN && val <= $t::<5, 10>::MAX
+ }) as fn($t<5, 10>) -> bool);
+
+ #[allow(trivial_casts)]
+ quickcheck::quickcheck((|val| {
+ if let Some(val) = val.get() {
+ val >= $t::<5, 10>::MIN && val <= $t::<5, 10>::MAX
+ } else {
+ true
+ }
+ }) as fn($opt<5, 10>) -> bool);
+ )*}
+ };
+}
+
+tests![
+ signed OptionRangedI8 RangedI8 i8,
+ signed OptionRangedI16 RangedI16 i16,
+ signed OptionRangedI32 RangedI32 i32,
+ signed OptionRangedI64 RangedI64 i64,
+ signed OptionRangedI128 RangedI128 i128,
+ signed OptionRangedIsize RangedIsize isize,
+ unsigned OptionRangedU8 RangedU8 u8,
+ unsigned OptionRangedU16 RangedU16 u16,
+ unsigned OptionRangedU32 RangedU32 u32,
+ unsigned OptionRangedU64 RangedU64 u64,
+ unsigned OptionRangedU128 RangedU128 u128,
+ unsigned OptionRangedUsize RangedUsize usize,
+];
diff --git a/vendor/deranged/src/traits.rs b/vendor/deranged/src/traits.rs
new file mode 100644
index 00000000..505b66de
--- /dev/null
+++ b/vendor/deranged/src/traits.rs
@@ -0,0 +1,123 @@
+//! Declaration and implementation of traits used for const assertions.
+
+use crate::{
+ RangedI128, RangedI16, RangedI32, RangedI64, RangedI8, RangedIsize, RangedU128, RangedU16,
+ RangedU32, RangedU64, RangedU8, RangedUsize,
+};
+
+/// Declare a series of traits that will be used for const assertions.
+macro_rules! declare_traits {
+ ($($trait_name:ident),* $(,)?) => {$(
+ pub(crate) trait $trait_name {
+ const ASSERT: ();
+ }
+ )*};
+}
+
+/// Implements traits that are common to all integer types.
+macro_rules! impl_traits_for_all {
+ ($($ranged_ty:ident $inner_ty:ident),* $(,)?) => {$(
+ impl<const MIN: $inner_ty, const MAX: $inner_ty> RangeIsValid for $ranged_ty<MIN, MAX> {
+ const ASSERT: () = assert!(MIN <= MAX);
+ }
+
+ impl<
+ const CURRENT_MIN: $inner_ty,
+ const CURRENT_MAX: $inner_ty,
+ const NEW_MIN: $inner_ty,
+ const NEW_MAX: $inner_ty,
+ > ExpandIsValid for ($ranged_ty<CURRENT_MIN, CURRENT_MAX>, $ranged_ty<NEW_MIN, NEW_MAX>) {
+ const ASSERT: () = {
+ assert!(NEW_MIN <= CURRENT_MIN);
+ assert!(NEW_MAX >= CURRENT_MAX);
+ };
+ }
+
+ impl<
+ const CURRENT_MIN: $inner_ty,
+ const CURRENT_MAX: $inner_ty,
+ const NEW_MIN: $inner_ty,
+ const NEW_MAX: $inner_ty,
+ > NarrowIsValid for ($ranged_ty<CURRENT_MIN, CURRENT_MAX>, $ranged_ty<NEW_MIN, NEW_MAX>) {
+ const ASSERT: () = {
+ assert!(NEW_MIN >= CURRENT_MIN);
+ assert!(NEW_MAX <= CURRENT_MAX);
+ };
+ }
+
+ impl<
+ const VALUE: $inner_ty,
+ const MIN: $inner_ty,
+ const MAX: $inner_ty,
+ > StaticIsValid for ($ranged_ty<MIN, VALUE>, $ranged_ty<VALUE, MAX>) {
+ const ASSERT: () = {
+ assert!(VALUE >= MIN);
+ assert!(VALUE <= MAX);
+ };
+ }
+ )*};
+}
+
+/// Implement traits that are common to all signed integer types.
+macro_rules! impl_traits_for_signed {
+ ($($ranged_ty:ident $inner_ty:ident),* $(,)?) => {$(
+ impl<const MIN: $inner_ty, const MAX: $inner_ty> AbsIsSafe for $ranged_ty<MIN, MAX> {
+ const ASSERT: () = {
+ assert!(MIN != <$inner_ty>::MIN);
+ assert!(-MIN <= MAX);
+ };
+ }
+
+ impl<const MIN: $inner_ty, const MAX: $inner_ty> NegIsSafe for $ranged_ty<MIN, MAX> {
+ const ASSERT: () = {
+ assert!(MIN != <$inner_ty>::MIN);
+ assert!(-MIN <= MAX);
+ assert!(-MAX >= MIN);
+ };
+ }
+
+ impl_traits_for_all!($ranged_ty $inner_ty);
+ )*};
+}
+
+/// Implement traits that are common to all unsigned integer types.
+macro_rules! impl_traits_for_unsigned {
+ ($($ranged_ty:ident $inner_ty:ident),* $(,)?) => {$(
+ impl<const MIN: $inner_ty, const MAX: $inner_ty> AbsIsSafe for $ranged_ty<MIN, MAX> {
+ const ASSERT: () = ();
+ }
+
+ impl<const MIN: $inner_ty, const MAX: $inner_ty> NegIsSafe for $ranged_ty<MIN, MAX> {
+ const ASSERT: () = assert!(MAX == 0);
+ }
+
+ impl_traits_for_all!($ranged_ty $inner_ty);
+ )*};
+}
+
+declare_traits![
+ RangeIsValid,
+ AbsIsSafe,
+ NegIsSafe,
+ ExpandIsValid,
+ NarrowIsValid,
+ StaticIsValid,
+];
+
+impl_traits_for_signed! {
+ RangedI8 i8,
+ RangedI16 i16,
+ RangedI32 i32,
+ RangedI64 i64,
+ RangedI128 i128,
+ RangedIsize isize,
+}
+
+impl_traits_for_unsigned! {
+ RangedU8 u8,
+ RangedU16 u16,
+ RangedU32 u32,
+ RangedU64 u64,
+ RangedU128 u128,
+ RangedUsize usize,
+}
diff --git a/vendor/deranged/src/unsafe_wrapper.rs b/vendor/deranged/src/unsafe_wrapper.rs
new file mode 100644
index 00000000..6b2304c1
--- /dev/null
+++ b/vendor/deranged/src/unsafe_wrapper.rs
@@ -0,0 +1,36 @@
+//! Declaration and implementation of `Unsafe`, which ensures all unsafe operations are correctly
+//! placed in unsafe blocks.
+
+/// A value that is safe to use, but is unsafe to construct or mutate.
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub(crate) struct Unsafe<T>(T);
+
+impl<T: core::fmt::Debug> core::fmt::Debug for Unsafe<T> {
+ #[inline]
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl<T> Unsafe<T> {
+ /// Create a new `Unsafe`, asserting that all invariants are upheld.
+ #[inline(always)]
+ pub(crate) const unsafe fn new(value: T) -> Self {
+ Self(value)
+ }
+
+ /// Get a reference to the inner value.
+ #[inline(always)]
+ pub(crate) const fn get(&self) -> &T {
+ &self.0
+ }
+}
+
+impl<T> core::ops::Deref for Unsafe<T> {
+ type Target = T;
+
+ #[inline(always)]
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}