typenum-1.17.0/.cargo_vcs_info.json0000644000000001360000000000100126230ustar { "git": { "sha1": "b237efbb1da9646435274f63d7290cb7651b031f" }, "path_in_vcs": "" }typenum-1.17.0/.github/workflows/check.yml000064400000000000000000000046361046102023000166210ustar 00000000000000on: push: branches: - main pull_request: branches: - main name: CI jobs: all-succeeded: name: All Succeeded if: always() runs-on: ubuntu-latest needs: - test-linux - test-non-linux - lint steps: - name: Check if all jubs succeeded uses: re-actors/alls-green@release/v1 with: jobs: ${{ toJSON(needs) }} test-linux: name: Test Linux runs-on: ubuntu-latest strategy: fail-fast: false matrix: rust: - stable - beta - nightly mb_const_generics: - "" - "--features const-generics" target: - x86_64 - i686 - sparc64 include: - mb_const_generics: "" rust: 1.37.0 target: x86_64 steps: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} - uses: actions-rs/cargo@v1 with: use-cross: ${{ matrix.target != 'x86_64' }} command: test args: --verbose --features "strict" ${{ matrix.mb_const_generics }} --target ${{ matrix.target }}-unknown-linux-gnu - uses: actions-rs/cargo@v1 with: use-cross: ${{ matrix.target != 'x86_64' }} command: doc args: --features "strict" ${{ matrix.mb_const_generics }} --target ${{ matrix.target }}-unknown-linux-gnu test-non-linux: name: Test non-Linux runs-on: ${{ matrix.os }} strategy: matrix: os: - macos-latest - windows-latest rust: - stable mb_const_generics: - "" - "--features const-generics" steps: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} - run: cargo test --verbose --features "strict" ${{ matrix.mb_const_generics }} - run: cargo doc --features "strict" ${{ matrix.mb_const_generics }} lint: name: Lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@nightly with: components: rustfmt, clippy - run: cargo fmt --all -- --check - run: cargo clippy -- -D warnings # Allow deprecated because we test the no_std feature. - run: cargo clippy --all-features -- -D warnings -A deprecated typenum-1.17.0/.github/workflows/publish.yml000064400000000000000000000011421046102023000171770ustar 00000000000000on: push: tags: - 'v*' name: Publish jobs: release: name: GitHub Release runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: marvinpinto/action-automatic-releases@latest with: repo_token: "${{ secrets.GITHUB_TOKEN }}" prerelease: false publish: name: Crates.io Publish runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@stable - uses: katyo/publish-crates@v1 with: registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }} typenum-1.17.0/.gitignore000064400000000000000000000000341046102023000134000ustar 00000000000000target Cargo.lock *.bk *\~ typenum-1.17.0/CHANGELOG.md000064400000000000000000000111631046102023000132260ustar 00000000000000# Changelog This project follows semantic versioning. The MSRV (Minimum Supported Rust Version) is 1.37.0, and typenum is tested against this Rust version. ### Unreleased - [removed] Remove `force_unix_path_separator` feature, make it the default - [added] docs.rs metadata and cfg options - [added] Playground metadata ### 1.16.0 (2022-12-05) - [added] `const INT` field to the `ToInt` trait. - [added] `const-generics` field with `U` mapping where `N` is a const generic. ### 1.15.0 (2021-12-25) - [fixed] Cross-compilation issue due to doing math in build script. (PR #177) - [added] New feature `scale_info` for using inside [Substrate](https://github.com/paritytech/substrate.git)-based runtimes (PR #175) ### 1.14.0 (2021-09-01) - [changed] Sealed all marker traits. Documentation already stated that these should not be implemented outside the crate, so this is not considered a breaking change. ### 1.13.0 (2021-03-12) - [changed] MSRV from 1.22.0 to 1.37.0. - [fixed] `op` macro with 2018 edition import. - [changed] Allowed calling `assert_type_eq` and `assert_type` at top level. - [added] Marker trait `Zero` for `Z0`, `U0`, and `B0`. - [added] Implementation of `Pow` trait for f32 and f64 with negative exponent. - [added] Trait `ToInt`. ### 1.12.0 (2020-04-13) - [added] Feature `force_unix_path_separator` to support building without Cargo. - [added] Greatest common divisor operator `Gcd` with alias `Gcf`. - [added] `gcd` to the `op!` macro. - [changed] Added `Copy` bound to `Rhs` of `Mul` impl for ``. - [changed] Added `Copy` bound to `Rhs` of `Div` impl for ``. - [changed] Added `Copy` bound to `Rhs` of `PartialDiv` impl for ``. - [changed] Added `Copy` bound to `Rhs` of `Rem` impl for ``. - [fixed] Make all functions #[inline]. ### 1.11.2 (2019-08-26) - [fixed] Cross compilation from Linux to Windows. ### 1.11.1 (2019-08-25) - [fixed] Builds on earlier Rust builds again and added Rust 1.22.0 to Travis to prevent future breakage. ### 1.11.0 (2019-08-25) - [added] Integer `log2` to the `op!` macro. - [added] Integer binary logarithm operator `Logarithm2` with alias `Log2`. - [changed] Removed `feature(i128_type)` when running with the `i128` feature. Kept the feature flag. for typenum to maintain compatibility with old Rust versions. - [added] Integer `sqrt` to the `op!` macro. - [added] Integer square root operator `SquareRoot` with alias `Sqrt`. - [fixed] Bug with attempting to create U1024 type alias twice. ### 1.10.0 (2018-03-11) - [added] The `PowerOfTwo` marker trait. - [added] Associated constants for `Bit`, `Unsigned`, and `Integer`. ### 1.9.0 (2017-05-14) - [added] The `Abs` type operator and corresponding `AbsVal` alias. - [added] The feature `i128` that enables creating 128-bit integers from typenums. - [added] The `assert_type!` and `assert_type_eq!` macros. - [added] Operators to the `op!` macro, including those performed by `cmp!`. - [fixed] Bug in `op!` macro involving functions and convoluted expressions. - [deprecated] The `cmp!` macro. ### 1.8.0 (2017-04-12) - [added] The `op!` macro for conveniently performing type-level operations. - [added] The `cmp!` macro for conveniently performing type-level comparisons. - [added] Some comparison type-operators that are used by the `cmp!` macro. ### 1.7.0 (2017-03-24) - [added] Type operators `Min` and `Max` with accompanying aliases `Minimum` and `Maximum` ### 1.6.0 (2017-02-24) - [fixed] Bug in `Array` division. - [fixed] Bug where `Rem` would sometimes exit early with the wrong answer. - [added] `PartialDiv` operator that performs division as a partial function -- it's defined only when there is no remainder. ### 1.5.2 (2017-02-04) - [fixed] Bug between `Div` implementation and type system. ### 1.5.1 (2016-11-08) - [fixed] Expanded implementation of `Pow` for primitives. ### 1.5.0 (2016-11-03) - [added] Functions to the `Pow` and `Len` traits. This is *technically* a breaking change, but it would only break someone's code if they have a custom impl for `Pow`. I would be very surprised if that is anyone other than me. ### 1.4.0 (2016-10-29) - [added] Type-level arrays of type-level integers. (PR #66) - [added] The types in this crate are now instantiable. (Issue #67, PR #68) ### 1.3.1 (2016-03-31) - [fixed] Bug with recent nightlies. ### 1.3.0 (2016-02-07) - [changed] Removed dependency on libstd. (Issue #53, PR #55) - [changed] Reorganized module structure. (PR #57) ### 1.2.0 (2016-01-03) - [added] This change log! - [added] Convenience type aliases for operators. (Issue #48, PR #50) - [added] Types in this crate now derive all possible traits. (Issue #42, PR #51) typenum-1.17.0/Cargo.toml0000644000000030270000000000100106230ustar # 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 = "2018" rust-version = "1.37.0" name = "typenum" version = "1.17.0" authors = [ "Paho Lurie-Gregg ", "Andre Bogus ", ] build = "build/main.rs" description = """ Typenum is a Rust library for type-level numbers evaluated at compile time. It currently supports bits, unsigned integers, and signed integers. It also provides a type-level array of type-level numbers, but its implementation is incomplete.""" documentation = "https://docs.rs/typenum" readme = "README.md" categories = ["no-std"] license = "MIT OR Apache-2.0" repository = "https://github.com/paholg/typenum" [package.metadata.docs.rs] features = [ "i128", "const-generics", ] rustdoc-args = [ "--cfg", "docsrs", ] [package.metadata.playground] features = [ "i128", "const-generics", ] [lib] name = "typenum" [dependencies.scale-info] version = "1.0" optional = true default-features = false [features] const-generics = [] force_unix_path_separator = [] i128 = [] no_std = [] scale_info = ["scale-info/derive"] strict = [] typenum-1.17.0/Cargo.toml.orig000064400000000000000000000021431046102023000143020ustar 00000000000000[package] name = "typenum" build = "build/main.rs" version = "1.17.0" # remember to update html_root_url authors = [ "Paho Lurie-Gregg ", "Andre Bogus ", ] documentation = "https://docs.rs/typenum" repository = "https://github.com/paholg/typenum" readme = "README.md" license = "MIT OR Apache-2.0" description = """Typenum is a Rust library for type-level numbers evaluated at compile time. It currently supports bits, unsigned integers, and signed integers. It also provides a type-level array of type-level numbers, but its implementation is incomplete.""" categories = ["no-std"] edition = "2018" rust-version = "1.37.0" [dependencies] scale-info = { version = "1.0", default-features = false, optional = true } [lib] name = "typenum" [features] no_std = [] # Deprecated i128 = [] strict = [] force_unix_path_separator = [] # Deprecated const-generics = [] scale_info = ["scale-info/derive"] [package.metadata.docs.rs] features = ["i128", "const-generics"] rustdoc-args = ["--cfg", "docsrs"] [package.metadata.playground] features = ["i128", "const-generics"] typenum-1.17.0/LICENSE000064400000000000000000000000211046102023000124110ustar 00000000000000MIT OR Apache-2.0typenum-1.17.0/LICENSE-APACHE000064400000000000000000000251231046102023000133420ustar 00000000000000 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 2014 Paho Lurie-Gregg 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.typenum-1.17.0/LICENSE-MIT000064400000000000000000000020731046102023000130510ustar 00000000000000The MIT License (MIT) Copyright (c) 2014 Paho Lurie-Gregg 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. typenum-1.17.0/README.md000064400000000000000000000043521046102023000126760ustar 00000000000000[![crates.io](https://img.shields.io/crates/v/typenum.svg)](https://crates.io/crates/typenum) [![Build Status](https://github.com/paholg/typenum/actions/workflows/check.yml/badge.svg)](https://github.com/paholg/typenum/actions/workflows/check.yml) Typenum ===== Typenum is a Rust library for type-level numbers evaluated at compile time. It currently supports bits, unsigned integers, and signed integers. Typenum depends only on libcore, and so is suitable for use on any platform! For the full documentation, go [here](https://docs.rs/typenum). ### Importing While `typenum` is divided into several modules, they are all re-exported through the crate root, so you can import anything contained herein with `use typenum::whatever;`, ignoring the crate structure. You may also find it useful to treat the `consts` module as a prelude, performing a glob import. ### Example Here is a trivial example of `typenum`'s use: ```rust use typenum::{Sum, Exp, Integer, N2, P3, P4}; type X = Sum; assert_eq!(::to_i32(), 7); type Y = Exp; assert_eq!(::to_i32(), -8); ``` For a non-trivial example of its use, see one of the crates that depends on it. The full list is [here](https://crates.io/crates/typenum/reverse_dependencies). Of note are [dimensioned](https://crates.io/crates/dimensioned/) which does compile-time type checking for arbitrary unit systems and [generic-array](https://crates.io/crates/generic-array/) which provides arrays whose length you can generically refer to. ### Error messages Typenum's error messages aren't great, and can be difficult to parse. The good news is that the fine folks at Auxon have written a tool to help with it. Please take a look at [tnfilt](https://github.com/auxoncorp/tnfilt). ### License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. typenum-1.17.0/build/generic_const_mappings.rs000064400000000000000000000050721046102023000176040ustar 00000000000000use super::*; pub fn emit_impls() -> ::std::io::Result<()> { let out_dir = ::std::env::var("OUT_DIR").unwrap(); let dest = ::std::path::Path::new(&out_dir).join("generic_const_mappings.rs"); let mut f = ::std::fs::File::create(&dest).unwrap(); #[allow(clippy::write_literal)] write!(f, "{}", "\ #[cfg(doc)] use generic_const_mappings::*; /// Module with some `const`-generics-friendly definitions, to help bridge the gap /// between those and `typenum` types. /// /// - It requires the `const-generics` crate feature to be enabled. /// /// The main type to use here is [`U`], although [`Const`] and [`ToUInt`] may be needed /// in a generic context. #[allow(warnings)] // script-generated code #[cfg(feature = \"const-generics\")] // hints at doc_auto_cfg pub mod generic_const_mappings { use crate::*; /// The main mapping from a generic `const: usize` to a [`UInt`]: [`U`] is expected to work like [`UN`]. /// /// - It requires the `const-generics` crate feature to be enabled. /// /// [`U`]: `U` /// [`UN`]: `U42` /// /// # Example /// /// ```rust /// use typenum::*; /// /// assert_type_eq!(U<42>, U42); /// ``` /// /// This can even be used in a generic `const N: usize` context, provided the /// genericity is guarded by a `where` clause: /// /// ```rust /// use typenum::*; /// /// struct MyStruct; /// /// trait MyTrait { type AssocType; } /// /// impl MyTrait /// for MyStruct /// where /// Const : ToUInt, /// { /// type AssocType = U; /// } /// /// assert_type_eq!( as MyTrait>::AssocType, U42); /// ``` pub type U = as ToUInt>::Output; /// Used to allow the usage of [`U`] in a generic context. pub struct Const; /// Used to allow the usage of [`U`] in a generic context. pub trait ToUInt { /// The [`UN`][`crate::U42`] type corresponding to `Self = Const`. type Output; } \ ")?; for uint in uints() { write!( f, " {cfg} impl ToUInt for Const<{uint}> {{ type Output = U{uint}; }} \ ", uint = uint, cfg = feature_gate_to_64_bit(uint), )?; } write!(f, "}}")?; f.flush()?; Ok(()) } const fn feature_gate_to_64_bit(uint: u64) -> &'static str { if uint > u32::MAX as u64 { r#"#[cfg(target_pointer_width = "64")]"# } else { "" } } typenum-1.17.0/build/main.rs000064400000000000000000000120751046102023000140110ustar 00000000000000use std::env; use std::fmt; use std::fs::File; use std::io::Write; use std::path::Path; #[cfg(feature = "const-generics")] mod generic_const_mappings; mod op; mod tests; pub enum UIntCode { Term, Zero(Box), One(Box), } pub enum IntCode { Zero, Pos(Box), Neg(Box), } impl fmt::Display for UIntCode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { UIntCode::Term => write!(f, "UTerm"), UIntCode::Zero(ref inner) => write!(f, "UInt<{}, B0>", inner), UIntCode::One(ref inner) => write!(f, "UInt<{}, B1>", inner), } } } impl fmt::Display for IntCode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { IntCode::Zero => write!(f, "Z0"), IntCode::Pos(ref inner) => write!(f, "PInt<{}>", inner), IntCode::Neg(ref inner) => write!(f, "NInt<{}>", inner), } } } pub fn gen_uint(u: u64) -> UIntCode { let mut result = UIntCode::Term; let mut x = 1u64 << 63; while x > u { x >>= 1 } while x > 0 { result = if x & u > 0 { UIntCode::One(Box::new(result)) } else { UIntCode::Zero(Box::new(result)) }; x >>= 1; } result } pub fn gen_int(i: i64) -> IntCode { use std::cmp::Ordering::{Equal, Greater, Less}; match i.cmp(&0) { Greater => IntCode::Pos(Box::new(gen_uint(i as u64))), Less => IntCode::Neg(Box::new(gen_uint(i.abs() as u64))), Equal => IntCode::Zero, } } #[cfg_attr( feature = "no_std", deprecated( since = "1.3.0", note = "the `no_std` flag is no longer necessary and will be removed in the future" ) )] pub fn no_std() {} #[cfg_attr( feature = "force_unix_path_separator", deprecated( since = "1.17.0", note = "the `force_unix_path_separator` flag is no longer necessary and will be removed in the future" ) )] pub fn force_unix_path_separator() {} const HIGHEST: u64 = 1024; fn uints() -> impl Iterator { // Use hardcoded values to avoid issues with cross-compilation. // See https://github.com/paholg/typenum/issues/162 let first2: u32 = 11; // (highest as f64).log(2.0).round() as u32 + 1; let first10: u32 = 4; // (highest as f64).log(10.0) as u32 + 1; (0..(HIGHEST + 1)) .chain((first2..64).map(|i| 2u64.pow(i))) .chain((first10..20).map(|i| 10u64.pow(i))) } // fixme: get a warning when testing without this #[allow(dead_code)] fn main() { println!("cargo:rerun-if-changed=build/main.rs"); // Allow caching the generation if `src/*` files change. let out_dir = env::var("OUT_DIR").unwrap(); let dest = Path::new(&out_dir).join("consts.rs"); let mut f = File::create(&dest).unwrap(); no_std(); force_unix_path_separator(); // Header stuff here! write!( f, " /** Type aliases for many constants. This file is generated by typenum's build script. For unsigned integers, the format is `U` followed by the number. We define aliases for - Numbers 0 through {highest} - Powers of 2 below `u64::MAX` - Powers of 10 below `u64::MAX` These alias definitions look like this: ```rust use typenum::{{B0, B1, UInt, UTerm}}; # #[allow(dead_code)] type U6 = UInt, B1>, B0>; ``` For positive signed integers, the format is `P` followed by the number and for negative signed integers it is `N` followed by the number. For the signed integer zero, we use `Z0`. We define aliases for - Numbers -{highest} through {highest} - Powers of 2 between `i64::MIN` and `i64::MAX` - Powers of 10 between `i64::MIN` and `i64::MAX` These alias definitions look like this: ```rust use typenum::{{B0, B1, UInt, UTerm, PInt, NInt}}; # #[allow(dead_code)] type P6 = PInt, B1>, B0>>; # #[allow(dead_code)] type N6 = NInt, B1>, B0>>; ``` # Example ```rust # #[allow(unused_imports)] use typenum::{{U0, U1, U2, U3, U4, U5, U6}}; # #[allow(unused_imports)] use typenum::{{N3, N2, N1, Z0, P1, P2, P3}}; # #[allow(unused_imports)] use typenum::{{U774, N17, N10000, P1024, P4096}}; ``` We also define the aliases `False` and `True` for `B0` and `B1`, respectively. */ #[allow(missing_docs)] pub mod consts {{ use crate::uint::{{UInt, UTerm}}; use crate::int::{{PInt, NInt}}; pub use crate::bit::{{B0, B1}}; pub use crate::int::Z0; pub type True = B1; pub type False = B0; ", highest = HIGHEST, ) .unwrap(); for u in uints() { writeln!(f, " pub type U{} = {};", u, gen_uint(u)).unwrap(); if u <= ::std::i64::MAX as u64 && u != 0 { let i = u as i64; writeln!( f, " pub type P{i} = PInt; pub type N{i} = NInt;", i = i ) .unwrap(); } } write!(f, "}}").unwrap(); tests::build_tests().unwrap(); op::write_op_macro().unwrap(); #[cfg(feature = "const-generics")] generic_const_mappings::emit_impls().unwrap(); } typenum-1.17.0/build/op.rs000064400000000000000000000357531046102023000135130ustar 00000000000000#[derive(Debug, Copy, Clone, Eq, PartialEq)] enum OpType { Operator, Function, } use self::OpType::*; struct Op { token: &'static str, operator: &'static str, example: (&'static str, &'static str), precedence: u8, n_args: u8, op_type: OpType, } pub fn write_op_macro() -> ::std::io::Result<()> { let out_dir = ::std::env::var("OUT_DIR").unwrap(); let dest = ::std::path::Path::new(&out_dir).join("op.rs"); let mut f = ::std::fs::File::create(&dest).unwrap(); // Operator precedence is taken from // https://doc.rust-lang.org/reference.html#operator-precedence // // We choose 16 as the highest precedence (functions are set to 255 but it doesn't matter // for them). We also only use operators that are left associative so we don't have to worry // about that. let ops = &[ Op { token: "*", operator: "Prod", example: ("P2 * P3", "P6"), precedence: 16, n_args: 2, op_type: Operator, }, Op { token: "/", operator: "Quot", example: ("P6 / P2", "P3"), precedence: 16, n_args: 2, op_type: Operator, }, Op { token: "%", operator: "Mod", example: ("P5 % P3", "P2"), precedence: 16, n_args: 2, op_type: Operator, }, Op { token: "+", operator: "Sum", example: ("P2 + P3", "P5"), precedence: 15, n_args: 2, op_type: Operator, }, Op { token: "-", operator: "Diff", example: ("P2 - P3", "N1"), precedence: 15, n_args: 2, op_type: Operator, }, Op { token: "<<", operator: "Shleft", example: ("U1 << U5", "U32"), precedence: 14, n_args: 2, op_type: Operator, }, Op { token: ">>", operator: "Shright", example: ("U32 >> U5", "U1"), precedence: 14, n_args: 2, op_type: Operator, }, Op { token: "&", operator: "And", example: ("U5 & U3", "U1"), precedence: 13, n_args: 2, op_type: Operator, }, Op { token: "^", operator: "Xor", example: ("U5 ^ U3", "U6"), precedence: 12, n_args: 2, op_type: Operator, }, Op { token: "|", operator: "Or", example: ("U5 | U3", "U7"), precedence: 11, n_args: 2, op_type: Operator, }, Op { token: "==", operator: "Eq", example: ("P5 == P3 + P2", "True"), precedence: 10, n_args: 2, op_type: Operator, }, Op { token: "!=", operator: "NotEq", example: ("P5 != P3 + P2", "False"), precedence: 10, n_args: 2, op_type: Operator, }, Op { token: "<=", operator: "LeEq", example: ("P6 <= P3 + P2", "False"), precedence: 10, n_args: 2, op_type: Operator, }, Op { token: ">=", operator: "GrEq", example: ("P6 >= P3 + P2", "True"), precedence: 10, n_args: 2, op_type: Operator, }, Op { token: "<", operator: "Le", example: ("P4 < P3 + P2", "True"), precedence: 10, n_args: 2, op_type: Operator, }, Op { token: ">", operator: "Gr", example: ("P5 < P3 + P2", "False"), precedence: 10, n_args: 2, op_type: Operator, }, Op { token: "cmp", operator: "Compare", example: ("cmp(P2, P3)", "Less"), precedence: !0, n_args: 2, op_type: Function, }, Op { token: "sqr", operator: "Square", example: ("sqr(P2)", "P4"), precedence: !0, n_args: 1, op_type: Function, }, Op { token: "sqrt", operator: "Sqrt", example: ("sqrt(U9)", "U3"), precedence: !0, n_args: 1, op_type: Function, }, Op { token: "abs", operator: "AbsVal", example: ("abs(N2)", "P2"), precedence: !0, n_args: 1, op_type: Function, }, Op { token: "cube", operator: "Cube", example: ("cube(P2)", "P8"), precedence: !0, n_args: 1, op_type: Function, }, Op { token: "pow", operator: "Exp", example: ("pow(P2, P3)", "P8"), precedence: !0, n_args: 2, op_type: Function, }, Op { token: "min", operator: "Minimum", example: ("min(P2, P3)", "P2"), precedence: !0, n_args: 2, op_type: Function, }, Op { token: "max", operator: "Maximum", example: ("max(P2, P3)", "P3"), precedence: !0, n_args: 2, op_type: Function, }, Op { token: "log2", operator: "Log2", example: ("log2(U9)", "U3"), precedence: !0, n_args: 1, op_type: Function, }, Op { token: "gcd", operator: "Gcf", example: ("gcd(U9, U21)", "U3"), precedence: !0, n_args: 2, op_type: Function, }, ]; use std::io::Write; write!( f, " /** Convenient type operations. Any types representing values must be able to be expressed as `ident`s. That means they need to be in scope. For example, `P5` is okay, but `typenum::P5` is not. You may combine operators arbitrarily, although doing so excessively may require raising the recursion limit. # Example ```rust #![recursion_limit=\"128\"] #[macro_use] extern crate typenum; use typenum::consts::*; fn main() {{ assert_type!( op!(min((P1 - P2) * (N3 + N7), P5 * (P3 + P4)) == P10) ); }} ``` Operators are evaluated based on the operator precedence outlined [here](https://doc.rust-lang.org/reference.html#operator-precedence). The full list of supported operators and functions is as follows: {} They all expand to type aliases defined in the `operator_aliases` module. Here is an expanded list, including examples: ", ops.iter() .map(|op| format!("`{}`", op.token)) .collect::>() .join(", ") )?; //write!(f, "Token | Alias | Example\n ===|===|===\n")?; for op in ops.iter() { write!( f, "---\nOperator `{token}`. Expands to `{operator}`. ```rust # #[macro_use] extern crate typenum; # use typenum::*; # fn main() {{ assert_type_eq!(op!({ex0}), {ex1}); # }} ```\n ", token = op.token, operator = op.operator, ex0 = op.example.0, ex1 = op.example.1 )?; } write!( f, "*/ #[macro_export(local_inner_macros)] macro_rules! op {{ ($($tail:tt)*) => ( __op_internal__!($($tail)*) ); }} #[doc(hidden)] #[macro_export(local_inner_macros)] macro_rules! __op_internal__ {{ " )?; // We first us the shunting-yard algorithm to produce our tokens in Polish notation. // See: https://en.wikipedia.org/wiki/Shunting-yard_algorithm // Note: Due to macro asymmetry, "the top of the stack" refers to the first element, not the // last // ----------------------------------------------------------------------------------------- // Stage 1: There are tokens to be read: // ------- // Case 1: Token is a function => Push it onto the stack: for fun in ops.iter().filter(|f| f.op_type == Function) { write!( f, " (@stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: {f_token} $($tail:tt)*) => ( __op_internal__!(@stack[{f_op}, $($stack,)*] @queue[$($queue,)*] @tail: $($tail)*) );", f_token = fun.token, f_op = fun.operator )?; } // ------- // Case 2: Token is a comma => Until the top of the stack is a LParen, // Pop operators from stack to queue // Base case: Top of stack is LParen, ditch comma and continue write!( f, " (@stack[LParen, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: , $($tail:tt)*) => ( __op_internal__!(@stack[LParen, $($stack,)*] @queue[$($queue,)*] @tail: $($tail)*) );" )?; // Recursive case: Not LParen, pop from stack to queue write!( f, " (@stack[$stack_top:ident, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: , $($tail:tt)*) => ( __op_internal__!(@stack[$($stack,)*] @queue[$stack_top, $($queue,)*] @tail: , $($tail)*) );" )?; // ------- // Case 3: Token is an operator, o1: for o1 in ops.iter().filter(|op| op.op_type == Operator) { // If top of stack is operator o2 with o1.precedence <= o2.precedence, // Then pop o2 off stack onto queue: for o2 in ops .iter() .filter(|op| op.op_type == Operator) .filter(|o2| o1.precedence <= o2.precedence) { write!( f, " (@stack[{o2_op}, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: {o1_token} $($tail:tt)*) => ( __op_internal__!(@stack[$($stack,)*] @queue[{o2_op}, $($queue,)*] @tail: {o1_token} $($tail)*) );", o2_op = o2.operator, o1_token = o1.token )?; } // Base case: push o1 onto stack write!( f, " (@stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: {o1_token} $($tail:tt)*) => ( __op_internal__!(@stack[{o1_op}, $($stack,)*] @queue[$($queue,)*] @tail: $($tail)*) );", o1_op = o1.operator, o1_token = o1.token )?; } // ------- // Case 4: Token is "(": push it onto stack as "LParen". Also convert the ")" to "RParen" to // appease the macro gods: write!( f, " (@stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: ( $($stuff:tt)* ) $($tail:tt)* ) => ( __op_internal__!(@stack[LParen, $($stack,)*] @queue[$($queue,)*] @tail: $($stuff)* RParen $($tail)*) );" )?; // ------- // Case 5: Token is "RParen": // 1. Pop from stack to queue until we see an "LParen", // 2. Kill the "LParen", // 3. If the top of the stack is a function, pop it onto the queue // 2. Base case: write!( f, " (@stack[LParen, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: RParen $($tail:tt)*) => ( __op_internal__!(@rp3 @stack[$($stack,)*] @queue[$($queue,)*] @tail: $($tail)*) );" )?; // 1. Recursive case: write!( f, " (@stack[$stack_top:ident, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: RParen $($tail:tt)*) => ( __op_internal__!(@stack[$($stack,)*] @queue[$stack_top, $($queue,)*] @tail: RParen $($tail)*) );" )?; // 3. Check for function: for fun in ops.iter().filter(|f| f.op_type == Function) { write!( f, " (@rp3 @stack[{fun_op}, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: $($tail:tt)*) => ( __op_internal__!(@stack[$($stack,)*] @queue[{fun_op}, $($queue,)*] @tail: $($tail)*) );", fun_op = fun.operator )?; } // 3. If no function found: write!( f, " (@rp3 @stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: $($tail:tt)*) => ( __op_internal__!(@stack[$($stack,)*] @queue[$($queue,)*] @tail: $($tail)*) );" )?; // ------- // Case 6: Token is a number: Push it onto the queue write!( f, " (@stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: $num:ident $($tail:tt)*) => ( __op_internal__!(@stack[$($stack,)*] @queue[$num, $($queue,)*] @tail: $($tail)*) );" )?; // ------- // Case 7: Out of tokens: // Base case: Stack empty: Start evaluating write!( f, " (@stack[] @queue[$($queue:ident,)*] @tail: ) => ( __op_internal__!(@reverse[] @input: $($queue,)*) );" )?; // Recursive case: Pop stack to queue write!( f, " (@stack[$stack_top:ident, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail:) => ( __op_internal__!(@stack[$($stack,)*] @queue[$stack_top, $($queue,)*] @tail: ) );" )?; // ----------------------------------------------------------------------------------------- // Stage 2: Reverse so we have RPN write!( f, " (@reverse[$($revved:ident,)*] @input: $head:ident, $($tail:ident,)* ) => ( __op_internal__!(@reverse[$head, $($revved,)*] @input: $($tail,)*) );" )?; write!( f, " (@reverse[$($revved:ident,)*] @input: ) => ( __op_internal__!(@eval @stack[] @input[$($revved,)*]) );" )?; // ----------------------------------------------------------------------------------------- // Stage 3: Evaluate in Reverse Polish Notation // Operators / Operators with 2 args: for op in ops.iter().filter(|op| op.n_args == 2) { // Note: We have to switch $a and $b here, otherwise non-commutative functions are backwards write!( f, " (@eval @stack[$a:ty, $b:ty, $($stack:ty,)*] @input[{op}, $($tail:ident,)*]) => ( __op_internal__!(@eval @stack[$crate::{op}<$b, $a>, $($stack,)*] @input[$($tail,)*]) );", op = op.operator )?; } // Operators with 1 arg: for op in ops.iter().filter(|op| op.n_args == 1) { write!( f, " (@eval @stack[$a:ty, $($stack:ty,)*] @input[{op}, $($tail:ident,)*]) => ( __op_internal__!(@eval @stack[$crate::{op}<$a>, $($stack,)*] @input[$($tail,)*]) );", op = op.operator )?; } // Wasn't a function or operator, so must be a value => push onto stack write!( f, " (@eval @stack[$($stack:ty,)*] @input[$head:ident, $($tail:ident,)*]) => ( __op_internal__!(@eval @stack[$head, $($stack,)*] @input[$($tail,)*]) );" )?; // No input left: write!( f, " (@eval @stack[$stack:ty,] @input[]) => ( $stack );" )?; // ----------------------------------------------------------------------------------------- // Stage 0: Get it started write!( f, " ($($tail:tt)* ) => ( __op_internal__!(@stack[] @queue[] @tail: $($tail)*) );" )?; write!( f, " }}" )?; Ok(()) } typenum-1.17.0/build/tests.rs000064400000000000000000000213751046102023000142320ustar 00000000000000use std::{env, fmt, fs, io, path}; use super::{gen_int, gen_uint}; /// Computes the greatest common divisor of two integers. fn gcdi(mut a: i64, mut b: i64) -> i64 { a = a.abs(); b = b.abs(); while a != 0 { let tmp = b % a; b = a; a = tmp; } b } fn gcdu(mut a: u64, mut b: u64) -> u64 { while a != 0 { let tmp = b % a; b = a; a = tmp; } b } fn sign(i: i64) -> char { use std::cmp::Ordering::*; match i.cmp(&0) { Greater => 'P', Less => 'N', Equal => '_', } } struct UIntTest { a: u64, op: &'static str, b: Option, r: u64, } impl fmt::Display for UIntTest { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.b { Some(b) => write!( f, " #[test] #[allow(non_snake_case)] fn test_{a}_{op}_{b}() {{ type A = {gen_a}; type B = {gen_b}; type U{r} = {result}; #[allow(non_camel_case_types)] type U{a}{op}U{b} = <>::Output as Same>::Output; assert_eq!(::to_u64(), ::to_u64()); }}", gen_a = gen_uint(self.a), gen_b = gen_uint(b), r = self.r, result = gen_uint(self.r), a = self.a, b = b, op = self.op ), None => write!( f, " #[test] #[allow(non_snake_case)] fn test_{a}_{op}() {{ type A = {gen_a}; type U{r} = {result}; #[allow(non_camel_case_types)] type {op}U{a} = <::Output as Same>::Output; assert_eq!(<{op}U{a} as Unsigned>::to_u64(), ::to_u64()); }}", gen_a = gen_uint(self.a), r = self.r, result = gen_uint(self.r), a = self.a, op = self.op ), } } } fn uint_binary_test(left: u64, operator: &'static str, right: u64, result: u64) -> UIntTest { UIntTest { a: left, op: operator, b: Option::Some(right), r: result, } } // fn uint_unary_test(op: &'static str, a: u64, result: u64) -> UIntTest { // UIntTest { a: a, op: op, b: Option::None, r: result } // } struct IntBinaryTest { a: i64, op: &'static str, b: i64, r: i64, } impl fmt::Display for IntBinaryTest { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, " #[test] #[allow(non_snake_case)] fn test_{sa}{a}_{op}_{sb}{b}() {{ type A = {gen_a}; type B = {gen_b}; type {sr}{r} = {result}; #[allow(non_camel_case_types)] type {sa}{a}{op}{sb}{b} = <>::Output as Same<{sr}{r}>>::Output; assert_eq!(<{sa}{a}{op}{sb}{b} as Integer>::to_i64(), <{sr}{r} as Integer>::to_i64()); }}", gen_a = gen_int(self.a), gen_b = gen_int(self.b), r = self.r.abs(), sr = sign(self.r), result = gen_int(self.r), a = self.a.abs(), b = self.b.abs(), sa = sign(self.a), sb = sign(self.b), op = self.op ) } } fn int_binary_test(left: i64, operator: &'static str, right: i64, result: i64) -> IntBinaryTest { IntBinaryTest { a: left, op: operator, b: right, r: result, } } struct IntUnaryTest { op: &'static str, a: i64, r: i64, } impl fmt::Display for IntUnaryTest { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, " #[test] #[allow(non_snake_case)] fn test_{sa}{a}_{op}() {{ type A = {gen_a}; type {sr}{r} = {result}; #[allow(non_camel_case_types)] type {op}{sa}{a} = <::Output as Same<{sr}{r}>>::Output; assert_eq!(<{op}{sa}{a} as Integer>::to_i64(), <{sr}{r} as Integer>::to_i64()); }}", gen_a = gen_int(self.a), r = self.r.abs(), sr = sign(self.r), result = gen_int(self.r), a = self.a.abs(), sa = sign(self.a), op = self.op ) } } fn int_unary_test(operator: &'static str, num: i64, result: i64) -> IntUnaryTest { IntUnaryTest { op: operator, a: num, r: result, } } fn uint_cmp_test(a: u64, b: u64) -> String { format!( " #[test] #[allow(non_snake_case)] fn test_{a}_Cmp_{b}() {{ type A = {gen_a}; type B = {gen_b}; #[allow(non_camel_case_types)] type U{a}CmpU{b} = >::Output; assert_eq!(::to_ordering(), Ordering::{result:?}); }}", a = a, b = b, gen_a = gen_uint(a), gen_b = gen_uint(b), result = a.cmp(&b) ) } fn int_cmp_test(a: i64, b: i64) -> String { format!( " #[test] #[allow(non_snake_case)] fn test_{sa}{a}_Cmp_{sb}{b}() {{ type A = {gen_a}; type B = {gen_b}; #[allow(non_camel_case_types)] type {sa}{a}Cmp{sb}{b} = >::Output; assert_eq!(<{sa}{a}Cmp{sb}{b} as Ord>::to_ordering(), Ordering::{result:?}); }}", a = a.abs(), b = b.abs(), sa = sign(a), sb = sign(b), gen_a = gen_int(a), gen_b = gen_int(b), result = a.cmp(&b) ) } // Allow for rustc 1.22 compatibility. #[allow(bare_trait_objects)] pub fn build_tests() -> Result<(), Box<::std::error::Error>> { // will test all permutations of number pairs up to this (and down to its opposite for ints) let high: i64 = 5; let uints = (0u64..high as u64 + 1).flat_map(|a| (a..a + 1).cycle().zip(0..high as u64 + 1)); let ints = (-high..high + 1).flat_map(|a| (a..a + 1).cycle().zip(-high..high + 1)); let out_dir = env::var("OUT_DIR")?; let dest = path::Path::new(&out_dir).join("tests.rs"); let f = fs::File::create(&dest)?; let mut writer = io::BufWriter::new(&f); use std::io::Write; writer.write_all( b" extern crate typenum; use std::ops::*; use std::cmp::Ordering; use typenum::*; ", )?; use std::cmp; // uint operators: for (a, b) in uints { write!(writer, "{}", uint_binary_test(a, "BitAnd", b, a & b))?; write!(writer, "{}", uint_binary_test(a, "BitOr", b, a | b))?; write!(writer, "{}", uint_binary_test(a, "BitXor", b, a ^ b))?; write!(writer, "{}", uint_binary_test(a, "Shl", b, a << b))?; write!(writer, "{}", uint_binary_test(a, "Shr", b, a >> b))?; write!(writer, "{}", uint_binary_test(a, "Add", b, a + b))?; write!(writer, "{}", uint_binary_test(a, "Min", b, cmp::min(a, b)))?; write!(writer, "{}", uint_binary_test(a, "Max", b, cmp::max(a, b)))?; write!(writer, "{}", uint_binary_test(a, "Gcd", b, gcdu(a, b)))?; if a >= b { write!(writer, "{}", uint_binary_test(a, "Sub", b, a - b))?; } write!(writer, "{}", uint_binary_test(a, "Mul", b, a * b))?; if b != 0 { write!(writer, "{}", uint_binary_test(a, "Div", b, a / b))?; write!(writer, "{}", uint_binary_test(a, "Rem", b, a % b))?; if a % b == 0 { write!(writer, "{}", uint_binary_test(a, "PartialDiv", b, a / b))?; } } write!(writer, "{}", uint_binary_test(a, "Pow", b, a.pow(b as u32)))?; write!(writer, "{}", uint_cmp_test(a, b))?; } // int operators: for (a, b) in ints { write!(writer, "{}", int_binary_test(a, "Add", b, a + b))?; write!(writer, "{}", int_binary_test(a, "Sub", b, a - b))?; write!(writer, "{}", int_binary_test(a, "Mul", b, a * b))?; write!(writer, "{}", int_binary_test(a, "Min", b, cmp::min(a, b)))?; write!(writer, "{}", int_binary_test(a, "Max", b, cmp::max(a, b)))?; write!(writer, "{}", int_binary_test(a, "Gcd", b, gcdi(a, b)))?; if b != 0 { write!(writer, "{}", int_binary_test(a, "Div", b, a / b))?; write!(writer, "{}", int_binary_test(a, "Rem", b, a % b))?; if a % b == 0 { write!(writer, "{}", int_binary_test(a, "PartialDiv", b, a / b))?; } } if b >= 0 || a.abs() == 1 { let result = if b < 0 { if a == 1 { a } else if a == -1 { a.pow((-b) as u32) } else { unreachable!() } } else { a.pow(b as u32) }; write!(writer, "{}", int_binary_test(a, "Pow", b, result))?; } write!(writer, "{}", int_cmp_test(a, b))?; } // int unary operators: for n in -high..high + 1 { write!(writer, "{}", int_unary_test("Neg", n, -n))?; write!(writer, "{}", int_unary_test("Abs", n, n.abs()))?; } writer.flush()?; Ok(()) } typenum-1.17.0/clippy.toml000064400000000000000000000000421046102023000136040ustar 00000000000000cognitive-complexity-threshold=35 typenum-1.17.0/rustfmt.toml000064400000000000000000000000431046102023000140110ustar 00000000000000format_code_in_doc_comments = true typenum-1.17.0/src/array.rs000064400000000000000000000171601046102023000136730ustar 00000000000000//! A type-level array of type-level numbers. //! //! It is not very featureful right now, and should be considered a work in progress. use core::ops::{Add, Div, Mul, Sub}; use super::*; /// The terminating type for type arrays. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug)] #[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] pub struct ATerm; impl TypeArray for ATerm {} /// `TArr` is a type that acts as an array of types. It is defined similarly to `UInt`, only its /// values can be more than bits, and it is designed to act as an array. So you can only add two if /// they have the same number of elements, for example. /// /// This array is only really designed to contain `Integer` types. If you use it with others, you /// may find it lacking functionality. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug)] #[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] pub struct TArr { first: V, rest: A, } impl TypeArray for TArr {} /// Create a new type-level array. Only usable on Rust 1.13.0 or newer. /// /// There's not a whole lot you can do with it right now. /// /// # Example /// ```rust /// #[macro_use] /// extern crate typenum; /// use typenum::consts::*; /// /// type Array = tarr![P3, N4, Z0, P38]; /// # fn main() { let _: Array; } #[macro_export] macro_rules! tarr { () => ( $crate::ATerm ); ($n:ty) => ( $crate::TArr<$n, $crate::ATerm> ); ($n:ty,) => ( $crate::TArr<$n, $crate::ATerm> ); ($n:ty, $($tail:ty),+) => ( $crate::TArr<$n, tarr![$($tail),+]> ); ($n:ty, $($tail:ty),+,) => ( $crate::TArr<$n, tarr![$($tail),+]> ); } // --------------------------------------------------------------------------------------- // Length /// Length of `ATerm` by itself is 0 impl Len for ATerm { type Output = U0; #[inline] fn len(&self) -> Self::Output { UTerm } } /// Size of a `TypeArray` impl Len for TArr where A: Len, Length: Add, Sum, B1>: Unsigned, { type Output = Add1>; #[inline] fn len(&self) -> Self::Output { self.rest.len() + B1 } } // --------------------------------------------------------------------------------------- // Add arrays // Note that two arrays are only addable if they are the same length. impl Add for ATerm { type Output = ATerm; #[inline] fn add(self, _: ATerm) -> Self::Output { ATerm } } impl Add> for TArr where Al: Add, Vl: Add, { type Output = TArr, Sum>; #[inline] fn add(self, rhs: TArr) -> Self::Output { TArr { first: self.first + rhs.first, rest: self.rest + rhs.rest, } } } // --------------------------------------------------------------------------------------- // Subtract arrays // Note that two arrays are only subtractable if they are the same length. impl Sub for ATerm { type Output = ATerm; #[inline] fn sub(self, _: ATerm) -> Self::Output { ATerm } } impl Sub> for TArr where Vl: Sub, Al: Sub, { type Output = TArr, Diff>; #[inline] fn sub(self, rhs: TArr) -> Self::Output { TArr { first: self.first - rhs.first, rest: self.rest - rhs.rest, } } } // --------------------------------------------------------------------------------------- // Multiply an array by a scalar impl Mul for ATerm { type Output = ATerm; #[inline] fn mul(self, _: Rhs) -> Self::Output { ATerm } } impl Mul for TArr where V: Mul, A: Mul, Rhs: Copy, { type Output = TArr, Prod>; #[inline] fn mul(self, rhs: Rhs) -> Self::Output { TArr { first: self.first * rhs, rest: self.rest * rhs, } } } impl Mul for Z0 { type Output = ATerm; #[inline] fn mul(self, _: ATerm) -> Self::Output { ATerm } } impl Mul for PInt where U: Unsigned + NonZero, { type Output = ATerm; #[inline] fn mul(self, _: ATerm) -> Self::Output { ATerm } } impl Mul for NInt where U: Unsigned + NonZero, { type Output = ATerm; #[inline] fn mul(self, _: ATerm) -> Self::Output { ATerm } } impl Mul> for Z0 where Z0: Mul, { type Output = TArr>; #[inline] fn mul(self, rhs: TArr) -> Self::Output { TArr { first: Z0, rest: self * rhs.rest, } } } impl Mul> for PInt where U: Unsigned + NonZero, PInt: Mul + Mul, { type Output = TArr, V>, Prod, A>>; #[inline] fn mul(self, rhs: TArr) -> Self::Output { TArr { first: self * rhs.first, rest: self * rhs.rest, } } } impl Mul> for NInt where U: Unsigned + NonZero, NInt: Mul + Mul, { type Output = TArr, V>, Prod, A>>; #[inline] fn mul(self, rhs: TArr) -> Self::Output { TArr { first: self * rhs.first, rest: self * rhs.rest, } } } // --------------------------------------------------------------------------------------- // Divide an array by a scalar impl Div for ATerm { type Output = ATerm; #[inline] fn div(self, _: Rhs) -> Self::Output { ATerm } } impl Div for TArr where V: Div, A: Div, Rhs: Copy, { type Output = TArr, Quot>; #[inline] fn div(self, rhs: Rhs) -> Self::Output { TArr { first: self.first / rhs, rest: self.rest / rhs, } } } // --------------------------------------------------------------------------------------- // Partial Divide an array by a scalar impl PartialDiv for ATerm { type Output = ATerm; #[inline] fn partial_div(self, _: Rhs) -> Self::Output { ATerm } } impl PartialDiv for TArr where V: PartialDiv, A: PartialDiv, Rhs: Copy, { type Output = TArr, PartialQuot>; #[inline] fn partial_div(self, rhs: Rhs) -> Self::Output { TArr { first: self.first.partial_div(rhs), rest: self.rest.partial_div(rhs), } } } // --------------------------------------------------------------------------------------- // Modulo an array by a scalar use core::ops::Rem; impl Rem for ATerm { type Output = ATerm; #[inline] fn rem(self, _: Rhs) -> Self::Output { ATerm } } impl Rem for TArr where V: Rem, A: Rem, Rhs: Copy, { type Output = TArr, Mod>; #[inline] fn rem(self, rhs: Rhs) -> Self::Output { TArr { first: self.first % rhs, rest: self.rest % rhs, } } } // --------------------------------------------------------------------------------------- // Negate an array use core::ops::Neg; impl Neg for ATerm { type Output = ATerm; #[inline] fn neg(self) -> Self::Output { ATerm } } impl Neg for TArr where V: Neg, A: Neg, { type Output = TArr, Negate>; #[inline] fn neg(self) -> Self::Output { TArr { first: -self.first, rest: -self.rest, } } } typenum-1.17.0/src/bit.rs000064400000000000000000000147301046102023000133330ustar 00000000000000//! Type-level bits. //! //! These are rather simple and are used as the building blocks of the //! other number types in this crate. //! //! //! **Type operators** implemented: //! //! - From `core::ops`: `BitAnd`, `BitOr`, `BitXor`, and `Not`. //! - From `typenum`: `Same` and `Cmp`. use crate::{private::InternalMarker, Cmp, Equal, Greater, Less, NonZero, PowerOfTwo, Zero}; use core::ops::{BitAnd, BitOr, BitXor, Not}; pub use crate::marker_traits::Bit; /// The type-level bit 0. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] #[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] pub struct B0; impl B0 { /// Instantiates a singleton representing this bit. #[inline] pub fn new() -> B0 { B0 } } /// The type-level bit 1. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] #[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] pub struct B1; impl B1 { /// Instantiates a singleton representing this bit. #[inline] pub fn new() -> B1 { B1 } } impl Bit for B0 { const U8: u8 = 0; const BOOL: bool = false; #[inline] fn new() -> Self { Self } #[inline] fn to_u8() -> u8 { 0 } #[inline] fn to_bool() -> bool { false } } impl Bit for B1 { const U8: u8 = 1; const BOOL: bool = true; #[inline] fn new() -> Self { Self } #[inline] fn to_u8() -> u8 { 1 } #[inline] fn to_bool() -> bool { true } } impl Zero for B0 {} impl NonZero for B1 {} impl PowerOfTwo for B1 {} /// Not of 0 (!0 = 1) impl Not for B0 { type Output = B1; #[inline] fn not(self) -> Self::Output { B1 } } /// Not of 1 (!1 = 0) impl Not for B1 { type Output = B0; #[inline] fn not(self) -> Self::Output { B0 } } /// And with 0 ( 0 & B = 0) impl BitAnd for B0 { type Output = B0; #[inline] fn bitand(self, _: Rhs) -> Self::Output { B0 } } /// And with 1 ( 1 & 0 = 0) impl BitAnd for B1 { type Output = B0; #[inline] fn bitand(self, _: B0) -> Self::Output { B0 } } /// And with 1 ( 1 & 1 = 1) impl BitAnd for B1 { type Output = B1; #[inline] fn bitand(self, _: B1) -> Self::Output { B1 } } /// Or with 0 ( 0 | 0 = 0) impl BitOr for B0 { type Output = B0; #[inline] fn bitor(self, _: B0) -> Self::Output { B0 } } /// Or with 0 ( 0 | 1 = 1) impl BitOr for B0 { type Output = B1; #[inline] fn bitor(self, _: B1) -> Self::Output { B1 } } /// Or with 1 ( 1 | B = 1) impl BitOr for B1 { type Output = B1; #[inline] fn bitor(self, _: Rhs) -> Self::Output { B1 } } /// Xor between 0 and 0 ( 0 ^ 0 = 0) impl BitXor for B0 { type Output = B0; #[inline] fn bitxor(self, _: B0) -> Self::Output { B0 } } /// Xor between 1 and 0 ( 1 ^ 0 = 1) impl BitXor for B1 { type Output = B1; #[inline] fn bitxor(self, _: B0) -> Self::Output { B1 } } /// Xor between 0 and 1 ( 0 ^ 1 = 1) impl BitXor for B0 { type Output = B1; #[inline] fn bitxor(self, _: B1) -> Self::Output { B1 } } /// Xor between 1 and 1 ( 1 ^ 1 = 0) impl BitXor for B1 { type Output = B0; #[inline] fn bitxor(self, _: B1) -> Self::Output { B0 } } #[cfg(tests)] mod tests { // macro for testing operation results. Uses `Same` to ensure the types are equal and // not just the values they evaluate to. macro_rules! test_bit_op { ($op:ident $Lhs:ident = $Answer:ident) => {{ type Test = <<$Lhs as $op>::Output as ::Same<$Answer>>::Output; assert_eq!(<$Answer as Bit>::to_u8(), ::to_u8()); }}; ($Lhs:ident $op:ident $Rhs:ident = $Answer:ident) => {{ type Test = <<$Lhs as $op<$Rhs>>::Output as ::Same<$Answer>>::Output; assert_eq!(<$Answer as Bit>::to_u8(), ::to_u8()); }}; } #[test] fn bit_operations() { test_bit_op!(Not B0 = B1); test_bit_op!(Not B1 = B0); test_bit_op!(B0 BitAnd B0 = B0); test_bit_op!(B0 BitAnd B1 = B0); test_bit_op!(B1 BitAnd B0 = B0); test_bit_op!(B1 BitAnd B1 = B1); test_bit_op!(B0 BitOr B0 = B0); test_bit_op!(B0 BitOr B1 = B1); test_bit_op!(B1 BitOr B0 = B1); test_bit_op!(B1 BitOr B1 = B1); test_bit_op!(B0 BitXor B0 = B0); test_bit_op!(B0 BitXor B1 = B1); test_bit_op!(B1 BitXor B0 = B1); test_bit_op!(B1 BitXor B1 = B0); } } impl Cmp for B0 { type Output = Equal; #[inline] fn compare(&self, _: &B0) -> Self::Output { Equal } } impl Cmp for B0 { type Output = Less; #[inline] fn compare(&self, _: &B1) -> Self::Output { Less } } impl Cmp for B1 { type Output = Greater; #[inline] fn compare(&self, _: &B0) -> Self::Output { Greater } } impl Cmp for B1 { type Output = Equal; #[inline] fn compare(&self, _: &B1) -> Self::Output { Equal } } use crate::Min; impl Min for B0 { type Output = B0; #[inline] fn min(self, _: B0) -> B0 { self } } impl Min for B0 { type Output = B0; #[inline] fn min(self, _: B1) -> B0 { self } } impl Min for B1 { type Output = B0; #[inline] fn min(self, rhs: B0) -> B0 { rhs } } impl Min for B1 { type Output = B1; #[inline] fn min(self, _: B1) -> B1 { self } } use crate::Max; impl Max for B0 { type Output = B0; #[inline] fn max(self, _: B0) -> B0 { self } } impl Max for B0 { type Output = B1; #[inline] fn max(self, rhs: B1) -> B1 { rhs } } impl Max for B1 { type Output = B1; #[inline] fn max(self, _: B0) -> B1 { self } } impl Max for B1 { type Output = B1; #[inline] fn max(self, _: B1) -> B1 { self } } #[cfg(test)] mod tests { #[test] fn bit_creation() { { use crate::{B0, B1}; let _: B0 = B0::new(); let _: B1 = B1::new(); } { use crate::{Bit, B0, B1}; let _: B0 = ::new(); let _: B1 = ::new(); } } } typenum-1.17.0/src/int.rs000064400000000000000000001000161046102023000133400ustar 00000000000000//! Type-level signed integers. //! //! //! Type **operators** implemented: //! //! From `core::ops`: `Add`, `Sub`, `Mul`, `Div`, and `Rem`. //! From `typenum`: `Same`, `Cmp`, and `Pow`. //! //! Rather than directly using the structs defined in this module, it is recommended that //! you import and use the relevant aliases from the [consts](../consts/index.html) module. //! //! Note that operators that work on the underlying structure of the number are //! intentionally not implemented. This is because this implementation of signed integers //! does *not* use twos-complement, and implementing them would require making arbitrary //! choices, causing the results of such operators to be difficult to reason about. //! //! # Example //! ```rust //! use std::ops::{Add, Div, Mul, Rem, Sub}; //! use typenum::{Integer, N3, P2}; //! //! assert_eq!(>::Output::to_i32(), -1); //! assert_eq!(>::Output::to_i32(), -5); //! assert_eq!(>::Output::to_i32(), -6); //! assert_eq!(>::Output::to_i32(), -1); //! assert_eq!(>::Output::to_i32(), -1); //! ``` pub use crate::marker_traits::Integer; use crate::{ bit::{Bit, B0, B1}, consts::{N1, P1, U0, U1}, private::{Internal, InternalMarker, PrivateDivInt, PrivateIntegerAdd, PrivateRem}, uint::{UInt, Unsigned}, Cmp, Equal, Greater, Less, NonZero, Pow, PowerOfTwo, ToInt, Zero, }; use core::ops::{Add, Div, Mul, Neg, Rem, Sub}; /// Type-level signed integers with positive sign. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] #[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] pub struct PInt { pub(crate) n: U, } /// Type-level signed integers with negative sign. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] #[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] pub struct NInt { pub(crate) n: U, } impl PInt { /// Instantiates a singleton representing this strictly positive integer. #[inline] pub fn new() -> PInt { PInt::default() } } impl NInt { /// Instantiates a singleton representing this strictly negative integer. #[inline] pub fn new() -> NInt { NInt::default() } } /// The type-level signed integer 0. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] #[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] pub struct Z0; impl Z0 { /// Instantiates a singleton representing the integer 0. #[inline] pub fn new() -> Z0 { Z0 } } impl NonZero for PInt {} impl NonZero for NInt {} impl Zero for Z0 {} impl PowerOfTwo for PInt {} impl Integer for Z0 { const I8: i8 = 0; const I16: i16 = 0; const I32: i32 = 0; const I64: i64 = 0; #[cfg(feature = "i128")] const I128: i128 = 0; const ISIZE: isize = 0; #[inline] fn to_i8() -> i8 { 0 } #[inline] fn to_i16() -> i16 { 0 } #[inline] fn to_i32() -> i32 { 0 } #[inline] fn to_i64() -> i64 { 0 } #[cfg(feature = "i128")] #[inline] fn to_i128() -> i128 { 0 } #[inline] fn to_isize() -> isize { 0 } } impl Integer for PInt { const I8: i8 = U::I8; const I16: i16 = U::I16; const I32: i32 = U::I32; const I64: i64 = U::I64; #[cfg(feature = "i128")] const I128: i128 = U::I128; const ISIZE: isize = U::ISIZE; #[inline] fn to_i8() -> i8 { ::to_i8() } #[inline] fn to_i16() -> i16 { ::to_i16() } #[inline] fn to_i32() -> i32 { ::to_i32() } #[inline] fn to_i64() -> i64 { ::to_i64() } #[cfg(feature = "i128")] #[inline] fn to_i128() -> i128 { ::to_i128() } #[inline] fn to_isize() -> isize { ::to_isize() } } // Simply negating the result of e.g. `U::I8` will result in overflow for `std::i8::MIN`. Instead, // we use the fact that `U: NonZero` by subtracting one from the `U::U8` before negating. impl Integer for NInt { const I8: i8 = -((U::U8 - 1) as i8) - 1; const I16: i16 = -((U::U16 - 1) as i16) - 1; const I32: i32 = -((U::U32 - 1) as i32) - 1; const I64: i64 = -((U::U64 - 1) as i64) - 1; #[cfg(feature = "i128")] const I128: i128 = -((U::U128 - 1) as i128) - 1; const ISIZE: isize = -((U::USIZE - 1) as isize) - 1; #[inline] fn to_i8() -> i8 { Self::I8 } #[inline] fn to_i16() -> i16 { Self::I16 } #[inline] fn to_i32() -> i32 { Self::I32 } #[inline] fn to_i64() -> i64 { Self::I64 } #[cfg(feature = "i128")] #[inline] fn to_i128() -> i128 { Self::I128 } #[inline] fn to_isize() -> isize { Self::ISIZE } } // --------------------------------------------------------------------------------------- // Neg /// `-Z0 = Z0` impl Neg for Z0 { type Output = Z0; #[inline] fn neg(self) -> Self::Output { Z0 } } /// `-PInt = NInt` impl Neg for PInt { type Output = NInt; #[inline] fn neg(self) -> Self::Output { NInt::new() } } /// `-NInt = PInt` impl Neg for NInt { type Output = PInt; #[inline] fn neg(self) -> Self::Output { PInt::new() } } // --------------------------------------------------------------------------------------- // Add /// `Z0 + I = I` impl Add for Z0 { type Output = I; #[inline] fn add(self, rhs: I) -> Self::Output { rhs } } /// `PInt + Z0 = PInt` impl Add for PInt { type Output = PInt; #[inline] fn add(self, _: Z0) -> Self::Output { PInt::new() } } /// `NInt + Z0 = NInt` impl Add for NInt { type Output = NInt; #[inline] fn add(self, _: Z0) -> Self::Output { NInt::new() } } /// `P(Ul) + P(Ur) = P(Ul + Ur)` impl Add> for PInt