diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-02 18:36:06 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-02 18:36:06 -0600 |
| commit | 8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch) | |
| tree | 22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/deranged | |
| parent | 4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff) | |
chore: add vendor directory
Diffstat (limited to 'vendor/deranged')
| -rw-r--r-- | vendor/deranged/.cargo-checksum.json | 1 | ||||
| -rw-r--r-- | vendor/deranged/Cargo.lock | 347 | ||||
| -rw-r--r-- | vendor/deranged/Cargo.toml | 203 | ||||
| -rw-r--r-- | vendor/deranged/LICENSE-Apache | 202 | ||||
| -rw-r--r-- | vendor/deranged/LICENSE-MIT | 19 | ||||
| -rw-r--r-- | vendor/deranged/README.md | 3 | ||||
| -rw-r--r-- | vendor/deranged/src/lib.rs | 1617 | ||||
| -rw-r--r-- | vendor/deranged/src/tests.rs | 716 | ||||
| -rw-r--r-- | vendor/deranged/src/traits.rs | 123 | ||||
| -rw-r--r-- | vendor/deranged/src/unsafe_wrapper.rs | 36 |
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 + } +} |
