lexical-util-0.8.5/.cargo_vcs_info.json0000644000000001520000000000100134400ustar { "git": { "sha1": "86dd62255a2cc3d0839d5272c8f30aec2c3b3791" }, "path_in_vcs": "lexical-util" }lexical-util-0.8.5/CODE_OF_CONDUCT.md000064400000000000000000000230620072674642500150640ustar 00000000000000# Code of Conduct ## When Something Happens If you see a Code of Conduct violation, follow these steps: 1. Let the person know that what they did is not appropriate and ask them to stop and/or edit their message(s) or commits. 2. That person should immediately stop the behavior and correct the issue. 3. If this doesn’t happen, or if you're uncomfortable speaking up, [contact the maintainers](#contacting-maintainers). 4. As soon as available, a maintainer will look into the issue, and take [further action (see below)](#further-enforcement), starting with a warning, then temporary block, then long-term repo or organization ban. When reporting, please include any relevant details, links, screenshots, context, or other information that may be used to better understand and resolve the situation. **The maintainer team will prioritize the well-being and comfort of the recipients of the violation over the comfort of the violator.** See [some examples below](#enforcement-examples). ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers of this project pledge to making participation in our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, technical preferences, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language. * Being respectful of differing viewpoints and experiences. * Gracefully accepting constructive feedback. * Focusing on what is best for the community. * Showing empathy and kindness towards other community members. * Encouraging and raising up your peers in the project so you can all bask in hacks and glory. Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances, including when simulated online. The only exception to sexual topics is channels/spaces specifically for topics of sexual identity. * Casual mention of slavery or indentured servitude and/or false comparisons of one's occupation or situation to slavery. Please consider using or asking about alternate terminology when referring to such metaphors in technology. * Making light of/making mocking comments about trigger warnings and content warnings. * Trolling, insulting/derogatory comments, and personal or political attacks. * Public or private harassment, deliberate intimidation, or threats. * Publishing others' private information, such as a physical or electronic address, without explicit permission. This includes any sort of "outing" of any aspect of someone's identity without their consent. * Publishing private screenshots or quotes of interactions in the context of this project without all quoted users' *explicit* consent. * Publishing of private communication that doesn't have to do with reporting harrassment. * Any of the above even when [presented as "ironic" or "joking"](https://en.wikipedia.org/wiki/Hipster_racism). * Any attempt to present "reverse-ism" versions of the above as violations. Examples of reverse-isms are "reverse racism", "reverse sexism", "heterophobia", and "cisphobia". * Unsolicited explanations under the assumption that someone doesn't already know it. Ask before you teach! Don't assume what people's knowledge gaps are. * [Feigning or exaggerating surprise](https://www.recurse.com/manual#no-feigned-surprise) when someone admits to not knowing something. * "[Well-actuallies](https://www.recurse.com/manual#no-well-actuallys)" * Other conduct which could reasonably be considered inappropriate in a professional or community setting. ## Scope This Code of Conduct applies both within spaces involving this project and in other spaces involving community members. This includes the repository, its Pull Requests and Issue tracker, private email communications in the context of the project, and any events where members of the project are participating, as well as adjacent communities and venues affecting the project's members. Depending on the violation, the maintainers may decide that violations of this code of conduct that have happened outside of the scope of the community may deem an individual unwelcome, and take appropriate action to maintain the comfort and safety of its members. ### Other Community Standards As a project on GitHub, this project is additionally covered by the [GitHub Community Guidelines](https://help.github.com/articles/github-community-guidelines/). Enforcement of those guidelines after violations overlapping with the above are the responsibility of the entities, and enforcement may happen in any or all of the services/communities. ## Maintainer Enforcement Process Once the maintainers get involved, they will follow a documented series of steps and do their best to preserve the well-being of project members. This section covers actual concrete steps. ### Contacting Maintainers You may get in touch with the maintainer team through any of the following methods: Through email: ahuszagh@gmail.com (Alex Huszagh) ### Further Enforcement If you've already followed the [initial enforcement steps](#enforcement), these are the steps maintainers will take for further enforcement, as needed: 1. Repeat the request to stop. 2. If the person doubles down, they will have offending messages removed or edited by a maintainers given an official warning. The PR or Issue may be locked. 3. If the behavior continues or is repeated later, the person will be blocked from participating for 24 hours. 4. If the behavior continues or is repeated after the temporary block, a long-term (6-12mo) ban will be used. On top of this, maintainers may remove any offending messages, images, contributions, etc, as they deem necessary. Maintainers reserve full rights to skip any of these steps, at their discretion, if the violation is considered to be a serious and/or immediate threat to the health and well-being of members of the community. These include any threats, serious physical or verbal attacks, and other such behavior that would be completely unacceptable in any social setting that puts our members at risk. Members expelled from events or venues with any sort of paid attendance will not be refunded. ### Who Watches the Watchers? Maintainers and other leaders who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. These may include anything from removal from the maintainer team to a permanent ban from the community. Additionally, as a project hosted on both GitHub and npm, [their own Codes of Conducts may be applied against maintainers of this project](#other-community-standards), externally of this project's procedures. ### Enforcement Examples #### The Best Case The vast majority of situations work out like this. This interaction is common, and generally positive. > Alex: "Yeah I used X and it was really crazy!" > Patt (not a maintainer): "Hey, could you not use that word? What about 'ridiculous' instead?" > Alex: "oh sorry, sure." -> edits old comment to say "it was really confusing!" #### The Maintainer Case Sometimes, though, you need to get maintainers involved. Maintainers will do their best to resolve conflicts, but people who were harmed by something **will take priority**. > Patt: "Honestly, sometimes I just really hate using $library and anyone who uses it probably sucks at their job." > Alex: "Whoa there, could you dial it back a bit? There's a CoC thing about attacking folks' tech use like that." > Patt: "I'm not attacking anyone, what's your problem?" > Alex: "@maintainers hey uh. Can someone look at this issue? Patt is getting a bit aggro. I tried to nudge them about it, but nope." > KeeperOfCommitBits: (on issue) "Hey Patt, maintainer here. Could you tone it down? This sort of attack is really not okay in this space." > Patt: "Leave me alone I haven't said anything bad wtf is wrong with you." > KeeperOfCommitBits: (deletes user's comment), "@patt I mean it. Please refer to the CoC over at (URL to this CoC) if you have questions, but you can consider this an actual warning. I'd appreciate it if you reworded your messages in this thread, since they made folks there uncomfortable. Let's try and be kind, yeah?" > Patt: "@keeperofbits Okay sorry. I'm just frustrated and I'm kinda burnt out and I guess I got carried away. I'll DM Alex a note apologizing and edit my messages. Sorry for the trouble." > KeeperOfCommitBits: "@patt Thanks for that. I hear you on the stress. Burnout sucks :/. Have a good one!" #### The Nope Case > PepeTheFrog🐸: "Hi, I am a literal actual nazi and I think white supremacists are quite fashionable." > Patt: "NOOOOPE. OH NOPE NOPE." > Alex: "JFC NO. NOPE. @keeperofbits NOPE NOPE LOOK HERE" > KeeperOfCommitBits: "👀 Nope. NOPE NOPE NOPE. 🔥" > PepeTheFrog🐸 has been banned from all organization or user repositories belonging to KeeperOfCommitBits. ## Attribution This Code of Conduct was generated using [WeAllJS Code of Conduct Generator](https://npm.im/weallbehave), which is based on the [WeAllJS Code of Conduct](https://wealljs.org/code-of-conduct), which is itself based on [Contributor Covenant](http://contributor-covenant.org), version 1.4, available at [http://contributor-covenant.org/version/1/4](http://contributor-covenant.org/version/1/4), and the LGBTQ in Technology Slack [Code of Conduct](http://lgbtq.technology/coc.html). lexical-util-0.8.5/Cargo.toml0000644000000030550000000000100114430ustar # 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" name = "lexical-util" version = "0.8.5" authors = ["Alex Huszagh "] exclude = [ "assets/*", "docs/*", "etc/*", "cargo-timing*.html", ] autobenches = false description = "Shared utilities for lexical creates." readme = "README.md" keywords = ["no_std"] categories = [ "value-formatting", "encoding", "no-std", ] license = "MIT/Apache-2.0" repository = "https://github.com/Alexhuszagh/rust-lexical" [package.metadata.docs.rs] features = [ "radix", "format", "write-integers", "write-floats", "parse-integers", "parse-floats", ] [dependencies.static_assertions] version = "1" [dev-dependencies.proptest] version = "0.10.1" [features] compact = [] default = ["std"] f128 = ["floats"] f16 = ["floats"] floats = [] format = [] integers = [] lint = [] parse = [] parse-floats = [ "parse", "floats", ] parse-integers = [ "parse", "integers", ] power-of-two = [] radix = ["power-of-two"] std = [] write = [] write-floats = [ "write", "floats", ] write-integers = [ "write", "integers", ] lexical-util-0.8.5/Cargo.toml.orig000064400000000000000000000044770072674642500151650ustar 00000000000000[package] authors = ["Alex Huszagh "] autobenches = false categories = ["value-formatting", "encoding", "no-std"] description = "Shared utilities for lexical creates." edition = "2018" keywords = ["no_std"] license = "MIT/Apache-2.0" name = "lexical-util" readme = "README.md" repository = "https://github.com/Alexhuszagh/rust-lexical" version = "0.8.5" exclude = [ "assets/*", "docs/*", "etc/*", "cargo-timing*.html" ] [dependencies] static_assertions = "1" [dev-dependencies] # FIXME: Replace back to "1.0.4" once the PR is merged. # There's an issue in quickcheck due to an infinitely repeating shrinker. # Issue: https://github.com/BurntSushi/quickcheck/issues/295 # Fix: https://github.com/BurntSushi/quickcheck/pull/296 quickcheck = { git = "https://github.com/neithernut/quickcheck/", branch = "i32min-shrink-bound" } proptest = "0.10.1" # FEATURES # -------- # In order to improve compile times, we have separate support # for each numeric conversion. Since these features are additive, # if more features are added, separate crates can add support # for more features without requiring re-compilation of lexical. [features] default = ["std"] # Use the standard library. std = [] # Add support for numerical conversions with power-of-two strings. power-of-two = [] # Add support for numerical conversions with non-decimal strings. radix = ["power-of-two"] # Add support for parsing custom numerical formats. format = [] # Add support for writing integers. write-integers = ["write", "integers"] # Add support for writing floats. write-floats = ["write", "floats"] # Add support for parsing integers. parse-integers = ["parse", "integers"] # Add support for parsing floats. parse-floats = ["parse", "floats"] # Reduce code size at the cost of performance. compact = [] # Internal only features. # Enable the lint checks. lint = [] # Add support for writing numbers. write = [] # Add support for parsing numbers. parse = [] # Add support for conversions to or from integers. integers = [] # Add support for conversions to or from floats. floats = [] # Currently unsupported. # Enable support for 16-bit floats. f16 = ["floats"] # Enable support for 128-bit floats. f128 = ["floats"] [package.metadata.docs.rs] features = ["radix", "format", "write-integers", "write-floats", "parse-integers", "parse-floats"] lexical-util-0.8.5/LICENSE-APACHE000064400000000000000000000251420072674642500142120ustar 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 [yyyy] [name of copyright owner] 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. lexical-util-0.8.5/LICENSE-MIT000064400000000000000000000017770072674642500137320ustar 00000000000000Permission 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. lexical-util-0.8.5/README.md000064400000000000000000000470760072674642500135570ustar 00000000000000lexical ======= High-performance numeric conversion routines for use in a `no_std` environment. This does not depend on any standard library features, nor a system allocator. **Similar Projects** If you want a minimal, stable, and compile-time friendly version of lexical's float-parsing algorithm, see [minimal-lexical](https://github.com/Alexhuszagh/minimal-lexical). If you want a minimal, performant float parser, recent versions of the Rust standard library should be [sufficient](https://github.com/rust-lang/rust/pull/86761). **Table of Contents** - [Getting Started](#getting-started) - [Partial/Complete Parsers](#partialcomplete-parsers) - [no_std](#no_std) - [Features](#features) - [Customization](#customization) - [Number Format API](#number-format-api) - [Options API](#options-api) - [Documentation](#documentation) - [Validation](#validation) - [Metrics](#metrics) - [Safety](#safety) - [Platform Support](#platform-support) - [Versioning and Version Support](#versioning-and-version-support) - [Changelog](#changelog) - [License](#license) - [Contributing](#contributing) # Getting Started Add lexical to your `Cargo.toml`: ```toml [dependencies] lexical = "^6.0" ``` And get started using lexical: ```rust // Number to string use lexical_core::BUFFER_SIZE; let mut buffer = [b'0'; BUFFER_SIZE]; lexical_core::write(3.0, &mut buffer); // "3.0", always has a fraction suffix, lexical_core::write(3, &mut buffer); // "3" // String to number. let i: i32 = lexical_core::parse("3")?; // Ok(3), auto-type deduction. let f: f32 = lexical_core::parse("3.5")?; // Ok(3.5) let d: f64 = lexical_core::parse("3.5")?; // Ok(3.5), error checking parse. let d: f64 = lexical_core::parse("3a")?; // Err(Error(_)), failed to parse. ``` In order to use lexical in generic code, the trait bounds `FromLexical` (for `parse`) and `ToLexical` (for `to_string`) are provided. ```rust /// Multiply a value in a string by multiplier, and serialize to string. fn mul_2(value: &str, multiplier: T) -> Result where T: lexical_core::ToLexical + lexical_core::FromLexical, { let value: T = lexical_core::parse(value.as_bytes())?; let mut buffer = [b'0'; lexical_core::BUFFER_SIZE]; let bytes = lexical_core::write(value * multiplier, &mut buffer); Ok(std::str::from_utf8(bytes).unwrap()) } ``` # Partial/Complete Parsers Lexical has both partial and complete parsers: the complete parsers ensure the entire buffer is used while parsing, without ignoring trailing characters, while the partial parsers parse as many characters as possible, returning both the parsed value and the number of parsed digits. Upon encountering an error, lexical will return an error indicating both the error type and the index at which the error occurred inside the buffer. **Complete Parsers** ```rust // This will return Err(Error::InvalidDigit(3)), indicating // the first invalid character occurred at the index 3 in the input // string (the space character). let x: i32 = lexical_core::parse(b"123 456")?; ``` **Partial Parsers** ```rust // This will return Ok((123, 3)), indicating that 3 digits were successfully // parsed, and that the returned value is `123`. let (x, count): (i32, usize) = lexical_core::parse_partial(b"123 456")?; ``` # no_std `lexical-core` does not depend on a standard library, nor a system allocator. To use `lexical-core` in a `no_std` environment, add the following to `Cargo.toml`: ```toml [dependencies.lexical-core] version = "0.8.5" default-features = false # Can select only desired parsing/writing features. features = ["write-integers", "write-floats", "parse-integers", "parse-floats"] ``` And get started using lexical: ```rust // A constant for the maximum number of bytes a formatter will write. use lexical_core::BUFFER_SIZE; let mut buffer = [b'0'; BUFFER_SIZE]; // Number to string. The underlying buffer must be a slice of bytes. let count = lexical_core::write(3.0, &mut buffer); assert_eq!(buffer[..count], b"3.0"); let count = lexical_core::write(3i32, &mut buffer); assert_eq!(buffer[..count], b"3"); // String to number. The input must be a slice of bytes. let i: i32 = lexical_core::parse(b"3")?; // Ok(3), auto-type deduction. let f: f32 = lexical_core::parse(b"3.5")?; // Ok(3.5) let d: f64 = lexical_core::parse(b"3.5")?; // Ok(3.5), error checking parse. let d: f64 = lexical_core::parse(b"3a")?; // Err(Error(_)), failed to parse. ``` # Features Lexical feature-gates each numeric conversion routine, resulting in faster compile times if certain numeric conversions. These features can be enabled/disabled for both `lexical-core` (which does not require a system allocator) and `lexical`. By default, all conversions are enabled. - **parse-floats**:   Enable string-to-float conversions. - **parse-integers**:   Enable string-to-integer conversions. - **write-floats**:   Enable float-to-string conversions. - **write-integers**:   Enable integer-to-string conversions. Lexical is highly customizable, and contains numerous other optional features: - **std**:   Enable use of the Rust standard library (enabled by default). - **power-of-two**:   Enable conversions to and from non-decimal strings.
With power_of_two enabled, the radixes {2, 4, 8, 10, 16, and 32} are valid, otherwise, only 10 is valid. This enables common conversions to/from hexadecimal integers/floats, without requiring large pre-computed tables for other radixes.
- **radix**:   Allow conversions to and from non-decimal strings.
With radix enabled, any radix from 2 to 36 (inclusive) is valid, otherwise, only 10 is valid.
- **format**:   Customize acceptable number formats for number parsing and writing.
With format enabled, the number format is dictated through bitflags and masks packed into a u128. These dictate the valid syntax of parsed and written numbers, including enabling digit separators, requiring integer or fraction digits, and toggling case-sensitive exponent characters.
- **compact**:   Optimize for binary size at the expense of performance.
This minimizes the use of pre-computed tables, producing significantly smaller binaries.
- **safe**:   Require all array indexing to be bounds-checked.
This is effectively a no-op for number parsers, since they use safe indexing except where indexing without bounds checking can be trivially shown to be correct. The number writers frequently use unsafe indexing, since we can easily over-estimate the number of digits in the output due to the fixed-length input.
- **f16**:   Add support for numeric conversions to-and-from 16-bit floats.
Adds f16, a half-precision IEEE-754 floating-point type, and bf16, the Brain Float 16 type, and numeric conversions to-and-from these floats. Note that since these are storage formats, and therefore do not have native arithmetic operations, all conversions are done using an intermediate f32.
To ensure the safety when bounds checking is disabled, we extensively fuzz the all numeric conversion routines. See the [Safety](#safety) section below for more information. Lexical also places a heavy focus on code bloat: with algorithms both optimized for performance and size. By default, this focuses on performance, however, using the `compact` feature, you can also opt-in to reduced code size at the cost of performance. The compact algorithms minimize the use of pre-computed tables and other optimizations at the cost of performance. # Customization > ⚠ **WARNING:** If changing the number of significant digits written, disabling the use of exponent notation, or changing exponent notation thresholds, `BUFFER_SIZE` may be insufficient to hold the resulting output. `WriteOptions::buffer_size` will provide a correct upper bound on the number of bytes written. If a buffer of insufficient length is provided, lexical-core will panic. Every language has competing specifications for valid numerical input, meaning a number parser for Rust will incorrectly accept or reject input for different programming or data languages. For example: ```rust // Valid in Rust strings. // Not valid in JSON. let f: f64 = lexical_core::parse(b"3.e7")?; // 3e7 // Let's only accept JSON floats. const JSON: u128 = lexical_core::format::JSON; let options = ParseFloatOptions::new(); let f: f64 = lexical_core::parse_with_options::(b"3.0e7", &options)?; // 3e7 let f: f64 = lexical_core::parse_with_options::(b"3.e7", &options)?; // Errors! ``` Due the high variability in the syntax of numbers in different programming and data languages, we provide 2 different APIs to simplify converting numbers with different syntax requirements. - Number Format API (feature-gated via `format` or `power-of-two`).
This is a packed struct contained flags to specify compile-time syntax rules for number parsing or writing. This includes features such as the radix of the numeric string, digit separators, case-sensitive exponent characters, optional base prefixes/suffixes, and more.
- Options API.
This contains run-time rules for parsing and writing numbers. This includes exponent break points, rounding modes, the exponent and decimal point characters, and the string representation of NaN and Infinity.
A limited subset of functionality is documented in examples below, however, the complete specification can be found in the API reference documentation. ## Number Format API The number format class provides numerous flags to specify number syntax when parsing or writing. When the `power-of-two` feature is enabled, additional flags are added: - The radix for the significant digits (default `10`). - The radix for the exponent base (default `10`). - The radix for the exponent digits (default `10`). When the `format` feature is enabled, numerous other syntax and digit separator flags are enabled, including: - A digit separator character, to group digits for increased legibility. - Whether leading, trailing, internal, and consecutive digit separators are allowed. - Toggling required float components, such as digits before the decimal point. - Toggling whether special floats are allowed or are case-sensitive. Many pre-defined constants therefore exist to simplify common use-cases, including: - JSON, XML, TOML, YAML, SQLite, and many more. - Rust, Python, C#, FORTRAN, COBOL literals and strings, and many more. An example of building a custom number format is as follows: ```rust const FORMAT: u128 = lexical_core::NumberFormatBuilder::new() // Disable exponent notation. .no_exponent_notation(true) // Disable all special numbers, such as Nan and Inf. .no_special(true) .build(); // Due to use in a `const fn`, we can't panic or expect users to unwrap invalid // formats, so it's up to the caller to verify the format. If an invalid format // is provided to a parser or writer, the function will error or panic, respectively. debug_assert!(lexical_core::format_is_valid::()); ``` ## Options API The options API allows customizing number parsing and writing at run-time, such as specifying the maximum number of significant digits, exponent characters, and more. An example of building a custom options struct is as follows: ```rust use std::num; let options = lexical_core::WriteFloatOptions::builder() // Only write up to 5 significant digits, IE, `1.23456` becomes `1.2345`. .max_significant_digits(num::NonZeroUsize::new(5)) // Never write less than 5 significant digits, `1.1` becomes `1.1000`. .min_significant_digits(num::NonZeroUsize::new(5)) // Trim the trailing `.0` from integral float strings. .trim_floats(true) // Use a European-style decimal point. .decimal_point(b',') // Panic if we try to write NaN as a string. .nan_string(None) // Write infinity as "Infinity". .inf_string(Some(b"Infinity")) .build() .unwrap(); ``` # Documentation Lexical's API reference can be found on [docs.rs](https://docs.rs/lexical), as can [lexical-core's](lexical-core). Detailed descriptions of the algorithms used can be found here: - [Parsing Integers](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-integer/docs/Algorithm.md) - [Parsing Floats](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-float/docs/Algorithm.md) - [Writing Integers](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-integer/docs/Algorithm.md) - [Writing Floats](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-float/docs/Algorithm.md) In addition, descriptions of how lexical handles [digit separators](https://github.com/Alexhuszagh/rust-lexical/blob/main/docs/DigitSeparators.md) and implements [big-integer arithmetic](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-float/docs/BigInteger.md) are also documented. # Validation **Float-Parsing** Float parsing is difficult to do correctly, and major bugs have been found in implementations from [libstdc++'s strtod](https://www.exploringbinary.com/glibc-strtod-incorrectly-converts-2-to-the-negative-1075/) to [Python](https://bugs.python.org/issue7632). In order to validate the accuracy of the lexical, we employ the following external tests: 1. Hrvoje Abraham's [strtod](https://github.com/ahrvoje/numerics/tree/master/strtod) test cases. 2. Rust's [test-float-parse](https://github.com/rust-lang/rust/tree/64185f205dcbd8db255ad6674e43c63423f2369a/src/etc/test-float-parse) unittests. 3. Testbase's [stress tests](https://www.icir.org/vern/papers/testbase-report.pdf) for converting from decimal to binary. 4. Nigel Tao's [tests](https://github.com/nigeltao/parse-number-fxx-test-data) extracted from test suites for Freetype, Google's double-conversion library, IBM's IEEE-754R compliance test, as well as numerous other curated examples. 5. [Various](https://www.exploringbinary.com/glibc-strtod-incorrectly-converts-2-to-the-negative-1075/) [difficult](https://www.exploringbinary.com/how-glibc-strtod-works/) [cases](https://www.exploringbinary.com/how-strtod-works-and-sometimes-doesnt/) reported on blogs. Although lexical may contain bugs leading to rounding error, it is tested against a comprehensive suite of random-data and near-halfway representations, and should be fast and correct for the vast majority of use-cases. # Metrics Various benchmarks, binary sizes, and compile times are shown here: **Build Timings** The compile-times when building with all numeric conversions enabled. For a more fine-tuned breakdown, see [build timings](https://github.com/Alexhuszagh/rust-lexical/blob/main/docs/BuildTimings.md). ![Build Timings](https://raw.githubusercontent.com/Alexhuszagh/rust-lexical/main/assets/timings_all_posix.svg) **Binary Size** The binary sizes of stripped binaries compiled at optimization level "2". For a more fine-tuned breakdown, see [binary sizes](https://github.com/Alexhuszagh/rust-lexical/blob/main/docs/BinarySize.md). ![Parse Stripped - Optimization Level "2"](https://raw.githubusercontent.com/Alexhuszagh/rust-lexical/main/assets/size_parse_stripped_opt2_posix.svg) ![Write Stripped - Optimization Level "2"](https://raw.githubusercontent.com/Alexhuszagh/rust-lexical/main/assets/size_write_stripped_opt2_posix.svg) **Benchmarks -- Parse Integer** A benchmark on randomly-generated integers uniformly distributed over the entire range. For a more fine-tuned breakdown, see [benchmarks](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-integer/docs/Benchmarks.md). ![Uniform Random Data](https://raw.githubusercontent.com/Alexhuszagh/rust-lexical/main/lexical-parse-integer/assets/random_uniform.svg) **Benchmarks -- Parse Float** A benchmark on parsing floats from various real-world data sets. For a more fine-tuned breakdown, see [benchmarks](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-float/docs/Benchmarks.md). ![Real Data](https://raw.githubusercontent.com/Alexhuszagh/rust-lexical/main/lexical-parse-float/assets/real.svg) **Benchmarks -- Write Integer** A benchmark on writing random integers uniformly distributed over the entire range. For a more fine-tuned breakdown, see [benchmarks](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-integer/docs/Benchmarks.md). ![Uniform Random Data](https://raw.githubusercontent.com/Alexhuszagh/rust-lexical/main/lexical-write-integer/assets/random_uniform.svg) **Benchmarks -- Write Float** A benchmark on writing floats generated via a random-number generator and parsed from a JSON document. For a more fine-tuned breakdown, see [benchmarks](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-float/docs/Benchmarks.md). ![Random Data](https://raw.githubusercontent.com/Alexhuszagh/rust-lexical/main/lexical-write-float/assets/json.svg) # Safety Due to the use of memory unsafe code in the integer and float writers, we extensively fuzz our float writers and parsers. The fuzz harnesses may be found under [fuzz](https://github.com/Alexhuszagh/rust-lexical/tree/main/fuzz), and are run continuously. So far, we've parsed and written over 72 billion floats. Due to the simple logic of the integer writers, and the lack of memory safety in the integer parsers, we minimally fuzz both, and test it with edge-cases, which has shown no memory safety issues to date. # Platform Support lexical-core is tested on a wide variety of platforms, including big and small-endian systems, to ensure portable code. Supported architectures include: - x86_64 Linux, Windows, macOS, Android, iOS, FreeBSD, and NetBSD. - x86 Linux, macOS, Android, iOS, and FreeBSD. - aarch64 (ARM8v8-A) Linux, Android, and iOS. - armv7 (ARMv7-A) Linux, Android, and iOS. - arm (ARMv6) Linux, and Android. - mips (MIPS) Linux. - mipsel (MIPS LE) Linux. - mips64 (MIPS64 BE) Linux. - mips64el (MIPS64 LE) Linux. - powerpc (PowerPC) Linux. - powerpc64 (PPC64) Linux. - powerpc64le (PPC64LE) Linux. - s390x (IBM Z) Linux. lexical-core should also work on a wide variety of other architectures and ISAs. If you have any issue compiling lexical-core on any architecture, please file a bug report. # Versioning and Version Support **Version Support** The currently supported versions are: - v0.8.x - v0.7.x (Maintenance) - v0.6.x (Maintenance) **Rustc Compatibility** - v0.8.x supports 1.51+, including stable, beta, and nightly. - v0.7.x supports 1.37+, including stable, beta, and nightly. - v0.6.x supports Rustc 1.24+, including stable, beta, and nightly. Please report any errors compiling a supported lexical-core version on a compatible Rustc version. **Versioning** lexical uses [semantic versioning](https://semver.org/). Removing support for Rustc versions newer than the latest stable Debian or Ubuntu version is considered an incompatible API change, requiring a major version change. # Changelog All changes are documented in [CHANGELOG](https://github.com/Alexhuszagh/rust-lexical/blob/main/CHANGELOG). # License Lexical is dual licensed under the Apache 2.0 license as well as the MIT license. See the [LICENSE.md](LICENSE.md) file for full license details. # Contributing Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in lexical by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. Contributing to the repository means abiding by the [code of conduct](https://github.com/Alexhuszagh/rust-lexical/blob/main/CODE_OF_CONDUCT.md). For the process on how to contribute to lexical, see the [development](https://github.com/Alexhuszagh/rust-lexical/blob/main/docs/Development.md) quick-start guide. lexical-util-0.8.5/src/algorithm.rs000064400000000000000000000031370072674642500154110ustar 00000000000000//! Simple, shared algorithms for slices and iterators. #[cfg(feature = "write")] use core::ptr; /// Copy bytes from source to destination. /// /// # Safety /// /// Safe as long as `dst` is larger than `src`. #[inline] #[cfg(feature = "write")] pub unsafe fn copy_to_dst>(dst: &mut [u8], src: Bytes) -> usize { debug_assert!(dst.len() >= src.as_ref().len()); // SAFETY: safe, if `dst.len() <= src.len()`. let src = src.as_ref(); unsafe { ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len()) }; src.len() } /// Count the number of trailing characters equal to a given value. #[inline] #[cfg(feature = "write")] pub fn rtrim_char_count(slc: &[u8], c: u8) -> usize { slc.iter().rev().take_while(|&&si| si == c).count() } /// Count the number of leading characters equal to a given value. #[inline] #[cfg(feature = "write")] pub fn ltrim_char_count(slc: &[u8], c: u8) -> usize { slc.iter().take_while(|&&si| si == c).count() } /// Trim character from the end (right-side) of a slice. #[inline] #[cfg(feature = "write")] pub fn rtrim_char_slice(slc: &[u8], c: u8) -> (&[u8], usize) { let count = rtrim_char_count(slc, c); let index = slc.len() - count; // Count must be <= slc.len(), and therefore, slc.len() - count must // also be <= slc.len(), since this is derived from an iterator // in the standard library. debug_assert!(count <= slc.len()); debug_assert!(index <= slc.len()); // SAFETY: safe since `count <= slc.len()` and therefore `index <= slc.len()`. let slc = unsafe { slc.get_unchecked(..index) }; (slc, count) } lexical-util-0.8.5/src/api.rs000064400000000000000000000330750072674642500142000ustar 00000000000000//! Implement string conversion routines in a single trait. // NOTE: // We use macros to define the traits, rather than implement here // since we can't define traits for types when both are defined outside // the current crate, including in workspaces. // FROM LEXICAL /// Define FromLexical trait. #[macro_export] #[cfg(feature = "parse")] macro_rules! from_lexical { () => { /// Trait for numerical types that can be parsed from bytes. pub trait FromLexical: lexical_util::num::Number { /// Checked parser for a string-to-number conversion. /// /// This method parses the entire string, returning an error if /// any invalid digits are found during parsing. Returns a `Result` /// containing either the parsed value, or an error containing /// any errors that occurred during parsing. /// /// * `bytes` - Slice containing a numeric string. fn from_lexical(bytes: &[u8]) -> lexical_util::result::Result; /// Checked parser for a string-to-number conversion. /// /// This method parses until an invalid digit is found (or the end /// of the string), returning the number of processed digits /// and the parsed value until that point. Returns a `Result` /// containing either the parsed value and the number of processed /// digits, or an error containing any errors that occurred during /// parsing. /// /// * `bytes` - Slice containing a numeric string. fn from_lexical_partial(bytes: &[u8]) -> lexical_util::result::Result<(Self, usize)>; } }; } /// Define FromLexicalWithOptions trait. #[macro_export] #[cfg(feature = "parse")] macro_rules! from_lexical_with_options { () => { /// Trait for numerical types that can be parsed from bytes with custom options. /// /// The `Options` type specifies the configurable options to provide. pub trait FromLexicalWithOptions: lexical_util::num::Number { /// Custom formatting options for parsing a number. type Options: lexical_util::options::ParseOptions; /// Checked parser for a string-to-number conversion. /// /// This method parses the entire string, returning an error if /// any invalid digits are found during parsing. The parsing /// is dictated by the options, which specifies special /// float strings, required float components, digit separators, /// exponent characters, and more. Returns a `Result` containing /// either the parsed value, or an error containing any errors /// that occurred during parsing. /// /// * `FORMAT` - Flags and characters designating the number grammar. /// * `bytes` - Slice containing a numeric string. /// * `options` - Options to dictate number parsing. /// /// The `FORMAT` packed struct is built using [`NumberFormatBuilder`]. /// Any invalid number format will prevent parsing, returning /// the appropriate format error. If you are unsure which format /// to use, use [`STANDARD`]. /// /// [`NumberFormatBuilder`]: lexical_util::format::NumberFormatBuilder /// [`STANDARD`]: lexical_util::format::STANDARD fn from_lexical_with_options( bytes: &[u8], options: &Self::Options, ) -> lexical_util::result::Result; /// Checked parser for a string-to-number conversion. /// /// This method parses until an invalid digit is found (or the end /// of the string), returning the number of processed digits /// and the parsed value until that point. Returns a `Result` /// containing either the parsed value and the number of /// processed digits, or an error containing any errors that /// occurred during parsing. /// /// * `FORMAT` - Flags and characters designating the number grammar. /// * `bytes` - Slice containing a numeric string. /// * `options` - Options to dictate number parsing. /// /// The `FORMAT` packed struct is built using [`NumberFormatBuilder`]. /// Any invalid number format will prevent parsing, returning /// the appropriate format error. If you are unsure which format /// to use, use [`STANDARD`]. /// /// [`NumberFormatBuilder`]: lexical_util::format::NumberFormatBuilder /// [`STANDARD`]: lexical_util::format::STANDARD fn from_lexical_partial_with_options( bytes: &[u8], options: &Self::Options, ) -> lexical_util::result::Result<(Self, usize)>; } }; } // TO LEXICAL /// Define ToLexical trait. #[macro_export] #[cfg(feature = "write")] macro_rules! to_lexical { () => { /// Trait for numerical types that can be serialized to bytes. /// /// To determine the number of bytes required to serialize a value to /// string, check the associated constants from a required trait: /// - [`FORMATTED_SIZE`] /// - [`FORMATTED_SIZE_DECIMAL`] /// /// [`FORMATTED_SIZE`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE /// [`FORMATTED_SIZE_DECIMAL`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE_DECIMAL pub trait ToLexical: lexical_util::constants::FormattedSize + lexical_util::num::Number { /// Serializer for a number-to-string conversion. /// /// Returns a subslice of the input buffer containing the written bytes, /// starting from the same address in memory as the input slice. /// /// * `value` - Number to serialize. /// * `bytes` - Buffer to write number to. /// /// # Safety /// /// Safe as long as the caller has provided a buffer of at least /// [`FORMATTED_SIZE_DECIMAL`] elements. If a smaller buffer is /// provided, a buffer overflow is very likely. /// /// [`FORMATTED_SIZE_DECIMAL`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE_DECIMAL unsafe fn to_lexical_unchecked<'a>(self, bytes: &'a mut [u8]) -> &'a mut [u8]; /// Serializer for a number-to-string conversion. /// /// Returns a subslice of the input buffer containing the written bytes, /// starting from the same address in memory as the input slice. /// /// * `value` - Number to serialize. /// * `bytes` - Buffer to write number to. /// /// # Panics /// /// Panics if the buffer is not of sufficient size. The caller /// must provide a slice of sufficient size. In order to ensure /// the function will not panic, ensure the buffer has at least /// [`FORMATTED_SIZE_DECIMAL`] elements. /// /// [`FORMATTED_SIZE_DECIMAL`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE_DECIMAL fn to_lexical<'a>(self, bytes: &'a mut [u8]) -> &'a mut [u8]; } }; } /// Define ToLexicalWithOptions trait. #[macro_export] #[cfg(feature = "write")] macro_rules! to_lexical_with_options { () => { /// Trait for numerical types that can be serialized to bytes with custom options. /// /// To determine the number of bytes required to serialize a value to /// string, check the associated constants from a required trait: /// - [`FORMATTED_SIZE`] /// - [`FORMATTED_SIZE_DECIMAL`] /// /// The `Options` type specifies the configurable options to provide. /// /// [`FORMATTED_SIZE`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE /// [`FORMATTED_SIZE_DECIMAL`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE_DECIMAL pub trait ToLexicalWithOptions: lexical_util::constants::FormattedSize + lexical_util::num::Number { /// Custom formatting options for writing a number. type Options: lexical_util::options::WriteOptions; /// Serializer for a number-to-string conversion. /// /// Returns a subslice of the input buffer containing the written bytes, /// starting from the same address in memory as the input slice. /// /// * `FORMAT` - Flags and characters designating the number grammar. /// * `value` - Number to serialize. /// * `bytes` - Buffer to write number to. /// * `options` - Options for number formatting. /// /// # Safety /// /// Safe as long as the caller has provided a buffer of at least /// [`FORMATTED_SIZE`] elements. If a smaller buffer is provided, a /// buffer overflow is very likely. If you are changing the /// number significant digits written, the exponent break points, /// or disabling scientific notation, you will need a larger buffer /// than the one provided. An upper limit on the buffer size can /// then be determined using [`WriteOptions::buffer_size`]. If you /// are not using `min_significant_digits`, 1200 bytes is always /// enough to hold the the output for a custom radix, and `400` /// is always enough for decimal strings. /// /// # Panics /// /// **Floats Only** /// /// These panics are only when using uncommon features for float /// writing, represent configuration errors, so runtime error /// handling is not provided. /// /// Panics if the provided number format is invalid, or if the /// mantissa radix is not equal to the exponent base /// and the mantissa radix/exponent base combinations are /// not in the following list: /// /// - `4, 2` /// - `8, 2` /// - `16, 2` /// - `32, 2` /// - `16, 4` /// /// Panics as well if the NaN or Inf string provided to the writer /// is disabled, but the value provided is NaN or Inf, respectively. /// /// [`WriteOptions::buffer_size`]: lexical_util::options::WriteOptions::buffer_size /// [`FORMATTED_SIZE`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE unsafe fn to_lexical_with_options_unchecked<'a, const FORMAT: u128>( self, bytes: &'a mut [u8], options: &Self::Options, ) -> &'a mut [u8]; /// Serializer for a number-to-string conversion. /// /// Returns a subslice of the input buffer containing the written bytes, /// starting from the same address in memory as the input slice. /// /// * `FORMAT` - Flags and characters designating the number grammar. /// * `value` - Number to serialize. /// * `bytes` - Buffer to write number to. /// * `options` - Options for number formatting. /// /// # Panics /// /// Panics if the buffer is not of sufficient size. The caller /// must provide a slice of sufficient size. In order to ensure /// the function will not panic, ensure the buffer has at least /// [`FORMATTED_SIZE`] elements. If you are changing the /// number significant digits written, the exponent break points, /// or disabling scientific notation, you will need a larger buffer /// than the one provided. An upper limit on the buffer size can /// then be determined using [`WriteOptions::buffer_size`]. If you /// are not using `min_significant_digits`, 1200 bytes is always /// enough to hold the the output for a custom radix, and `400` /// is always enough for decimal strings. /// /// **Floats Only** /// /// These panics are only when using uncommon features for float /// writing, represent configuration errors, so runtime error /// handling is not provided. /// /// Also panics if the provided number format is invalid, or /// if the mantissa radix is not equal to the exponent base /// and the mantissa radix/exponent base combinations are /// not in the following list: /// /// - `4, 2` /// - `8, 2` /// - `16, 2` /// - `32, 2` /// - `16, 4` /// /// Panics as well if the NaN or Inf string provided to the writer /// is disabled, but the value provided is NaN or Inf, respectively. /// /// [`WriteOptions::buffer_size`]: lexical_util::options::WriteOptions::buffer_size /// [`FORMATTED_SIZE`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE fn to_lexical_with_options<'a, const FORMAT: u128>( self, bytes: &'a mut [u8], options: &Self::Options, ) -> &'a mut [u8]; } }; } lexical-util-0.8.5/src/ascii.rs000064400000000000000000000027000072674642500145060ustar 00000000000000//! Utilities for working with ASCII characters. /// Determine if a character is a valid ASCII character for float grammar. pub const fn is_valid_ascii(c: u8) -> bool { // Below 0x20 is mostly control characters, with no representation. // 0x7F is a control character, DEL, so don't include it. // We also want the few visual characters below 0x20: // 0x09 - Horizontal Tab // 0x0A - Newline // 0x0B - Vertical Tab (Deprecated) // 0x0C - Form Feed (Deprecated) // 0x0D - Carriage Return (c >= 0x09 && c <= 0x0d) || (c >= 0x20 && c < 0x7F) } /// Determine if a slice is all valid ASCII characters for float grammar. /// Modified to be used in a const fn, since for loops and iter don't work. pub const fn is_valid_ascii_slice(slc: &[u8]) -> bool { let mut index = 0; while index < slc.len() { if !is_valid_ascii(slc[index]) { return false; } index += 1; } true } /// Determine if a character is a valid ASCII letter. pub const fn is_valid_letter(c: u8) -> bool { (c >= 0x41 && c <= 0x5a) || (c >= 0x61 && c <= 0x7a) } /// Determine if a slice is all valid ASCII letters. /// Modified to be used in a const fn, since for loops and iter don't work. pub const fn is_valid_letter_slice(slc: &[u8]) -> bool { let mut index = 0; while index < slc.len() { if !is_valid_letter(slc[index]) { return false; } index += 1; } true } lexical-util-0.8.5/src/assert.rs000064400000000000000000000052700072674642500147240ustar 00000000000000//! Debugging assertions to check a radix is valid. #[cfg(feature = "write")] use crate::constants::FormattedSize; use crate::format::NumberFormat; // RADIX /// Check radix is in range `[2, 36]` in debug builds. #[inline] #[cfg(feature = "radix")] pub fn debug_assert_radix(radix: u32) { debug_assert!((2..=36).contains(&radix), "Numerical base must be from 2-36."); } /// Check radix is is 10 or a power of 2. #[inline] #[cfg(all(feature = "power-of-two", not(feature = "radix")))] pub fn debug_assert_radix(radix: u32) { debug_assert!(matches!(radix, 2 | 4 | 8 | 10 | 16 | 32), "Numerical base must be from 2-36."); } /// Check radix is equal to 10. #[inline] #[cfg(not(feature = "power-of-two"))] pub fn debug_assert_radix(radix: u32) { debug_assert!(radix == 10, "Numerical base must be 10."); } /// Assert radix is in range `[2, 36]`. #[inline] #[cfg(feature = "radix")] pub fn assert_radix() { assert!( (2..=36).contains(&NumberFormat::<{ FORMAT }>::RADIX), "Numerical base must be from 2-36." ); } /// Check radix is is 10 or a power of 2. #[inline] #[cfg(all(feature = "power-of-two", not(feature = "radix")))] pub fn assert_radix() { assert!( matches!(NumberFormat::<{ FORMAT }>::RADIX, 2 | 4 | 8 | 10 | 16 | 32), "Numerical base must be from 2, 4, 8, 10, 16, or 32." ); } /// Check radix is equal to 10. #[inline] #[cfg(not(feature = "power-of-two"))] pub fn assert_radix() { assert!(NumberFormat::<{ FORMAT }>::RADIX == 10, "Numerical base must be 10."); } // BUFFER /// Debug assertion the buffer has sufficient room for the output. #[inline] #[cfg(feature = "write")] pub fn debug_assert_buffer(radix: u32, len: usize) { debug_assert!( match radix { 10 => len >= T::FORMATTED_SIZE_DECIMAL, _ => len >= T::FORMATTED_SIZE, }, "Buffer is too small: may overwrite buffer in release builds." ); } /// Assertion the buffer has sufficient room for the output. #[inline] #[cfg(all(feature = "power-of-two", feature = "write"))] pub fn assert_buffer(radix: u32, len: usize) { assert!( match radix { 10 => len >= T::FORMATTED_SIZE_DECIMAL, _ => len >= T::FORMATTED_SIZE, }, "Buffer is too small: may overwrite buffer, panicking!" ); } /// Assertion the buffer has sufficient room for the output. #[inline] #[cfg(all(not(feature = "power-of-two"), feature = "write"))] pub fn assert_buffer(_: u32, len: usize) { assert!( len >= T::FORMATTED_SIZE_DECIMAL, "Buffer is too small: may overwrite buffer, panicking!" ); } lexical-util-0.8.5/src/bf16.rs000064400000000000000000000102040072674642500141520ustar 00000000000000//! Brain Floating Point implementation, a 16-bit type used in machine learning. //! //! bf16 is meant as an interchange format, and therefore there may be //! rounding error in using it for fast-path algorithms. Since there //! are no native operations using `bf16`, this is of minimal concern. #![cfg(feature = "f16")] #![doc(hidden)] use core::cmp::Ordering; use core::{fmt, ops}; /// Brain floating point type. #[allow(non_camel_case_types)] #[derive(Default, Copy, Clone)] pub struct bf16 { /// Raw bitwise representation of the float as a 16-bit type. bits: u16, } unsafe impl Send for bf16 { } unsafe impl Sync for bf16 { } impl bf16 { #[inline(always)] pub const fn to_bits(self) -> u16 { self.bits } #[inline(always)] pub const fn from_bits(bits: u16) -> Self { Self { bits, } } #[inline(always)] pub fn as_f32(self) -> f32 { // This is super easy, since we have the same exponent bits: // just need to shift left 16. f32::from_bits((self.bits as u32) << 16) } #[inline(always)] pub fn from_f32(value: f32) -> Self { // Same number of exponent bits, less mantissa bits: simple conversion. // We want to round to the nearest float, so we'll check if it's odd // and above or equal to halfway. This also properly handled inf, denormal, // and NaN cases, since they're effectively the same. let bits = value.to_bits(); let truncated = bits as u16; let bf16_bits = (bits >> 16) as u16; let halfway = 1u16 << 15; let is_odd = bf16_bits % 2 == 1; let is_halfway = truncated == halfway; let is_above = truncated > halfway; let round_up = is_above || (is_halfway && is_odd); Self::from_bits(bf16_bits + round_up as u16) } } impl PartialEq for bf16 { #[inline(always)] fn eq(&self, other: &Self) -> bool { self.as_f32().eq(&other.as_f32()) } } impl PartialOrd for bf16 { #[inline(always)] fn partial_cmp(&self, other: &Self) -> Option { self.as_f32().partial_cmp(&other.as_f32()) } } impl fmt::Debug for bf16 { #[inline(always)] fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { self.as_f32().fmt(formatter) } } impl fmt::Display for bf16 { #[inline(always)] fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { self.as_f32().fmt(formatter) } } impl ops::Add for bf16 { type Output = Self; #[inline(always)] fn add(self, rhs: Self) -> Self::Output { Self::from_f32(self.as_f32() + rhs.as_f32()) } } impl ops::Div for bf16 { type Output = Self; #[inline(always)] fn div(self, rhs: Self) -> Self::Output { Self::from_f32(self.as_f32() / rhs.as_f32()) } } impl ops::Mul for bf16 { type Output = Self; #[inline(always)] fn mul(self, rhs: Self) -> Self::Output { Self::from_f32(self.as_f32() * rhs.as_f32()) } } impl ops::Sub for bf16 { type Output = Self; #[inline(always)] fn sub(self, rhs: Self) -> Self::Output { Self::from_f32(self.as_f32() - rhs.as_f32()) } } impl ops::Rem for bf16 { type Output = Self; #[inline(always)] fn rem(self, rhs: Self) -> Self::Output { Self::from_f32(self.as_f32() % rhs.as_f32()) } } impl ops::Neg for bf16 { type Output = Self; #[inline(always)] fn neg(self) -> Self::Output { Self::from_bits(self.bits ^ (1 << 15)) } } impl ops::AddAssign for bf16 { #[inline(always)] fn add_assign(&mut self, rhs: Self) { *self = *self + rhs; } } impl ops::DivAssign for bf16 { #[inline(always)] fn div_assign(&mut self, rhs: Self) { *self = *self / rhs; } } impl ops::MulAssign for bf16 { #[inline(always)] fn mul_assign(&mut self, rhs: Self) { *self = *self * rhs; } } impl ops::SubAssign for bf16 { #[inline(always)] fn sub_assign(&mut self, rhs: Self) { *self = *self - rhs; } } impl ops::RemAssign for bf16 { #[inline(always)] fn rem_assign(&mut self, rhs: Self) { *self = *self % rhs; } } lexical-util-0.8.5/src/constants.rs000064400000000000000000000072330072674642500154400ustar 00000000000000//! Pre-defined constants for numeric types. #![cfg(feature = "write")] #[cfg(feature = "f16")] use crate::bf16::bf16; #[cfg(feature = "f16")] use crate::f16::f16; /// The size, in bytes, of formatted values. pub trait FormattedSize { /// Maximum number of bytes required to serialize a number to string. /// /// Note that this value may be insufficient if digit precision control, /// exponent break points, or disabling exponent notation is used. If /// you are changing the number significant digits written, the exponent /// break points, or disabling scientific notation, you will need a larger /// buffer than the one provided. An upper limit on the buffer size can /// then be determined using [`WriteOptions::buffer_size`]. /// /// [`WriteOptions::buffer_size`]: crate::options::WriteOptions::buffer_size /// [`lexical_write_float`]: https://github.com/Alexhuszagh/rust-lexical/tree/main/lexical-write-float const FORMATTED_SIZE: usize; /// Maximum number of bytes required to serialize a number to a decimal string. /// /// Note that this value may be insufficient if digit precision control, /// exponent break points, or disabling exponent notation is used. If /// you are changing the number significant digits written, the exponent /// break points, or disabling scientific notation, you will need a larger /// buffer than the one provided. An upper limit on the buffer size can /// then be determined using [`WriteOptions::buffer_size`]. /// /// [`WriteOptions::buffer_size`]: crate::options::WriteOptions::buffer_size /// [`lexical_write_float`]: https://github.com/Alexhuszagh/rust-lexical/tree/main/lexical-write-float const FORMATTED_SIZE_DECIMAL: usize; } macro_rules! formatted_size_impl { ($($t:tt $decimal:literal $radix:literal ; )*) => ($( impl FormattedSize for $t { #[cfg(feature = "power-of-two")] const FORMATTED_SIZE: usize = $radix; #[cfg(not(feature = "power-of-two"))] const FORMATTED_SIZE: usize = $decimal; const FORMATTED_SIZE_DECIMAL: usize = $decimal; } )*); } formatted_size_impl! { i8 4 16 ; i16 6 32 ; i32 11 64 ; i64 20 128 ; i128 40 256 ; u8 3 16 ; u16 5 32 ; u32 10 64 ; u64 20 128 ; u128 39 256 ; // The f64 buffer is actually a size of 60, but use 64 since it's a power of 2. // Use 256 fir non-decimal values, actually, since we seem to have memory // issues with f64. Clearly not sufficient memory allocated for non-decimal // values. //bf16 64 256 ; //f16 64 256 ; f32 64 256 ; f64 64 256 ; //f128 128 512 ; //f256 256 1024 ; } #[cfg(feature = "f16")] formatted_size_impl! { f16 64 256 ; bf16 64 256 ; } #[cfg(target_pointer_width = "16")] formatted_size_impl! { isize 6 32 ; } #[cfg(target_pointer_width = "16")] formatted_size_impl! { usize 5 32 ; } #[cfg(target_pointer_width = "32")] formatted_size_impl! { isize 11 64 ; } #[cfg(target_pointer_width = "32")] formatted_size_impl! { usize 10 64 ; } #[cfg(target_pointer_width = "64")] formatted_size_impl! { isize 20 128 ; } #[cfg(target_pointer_width = "64")] formatted_size_impl! { usize 20 128 ; } /// Maximum number of bytes required to serialize any number to string. /// /// Note that this value may be insufficient if digit precision control, /// exponent break points, or disabling exponent notation is used. /// Please read the documentation in [`lexical_write_float`] for more information. /// /// [`lexical_write_float`]: https://github.com/Alexhuszagh/rust-lexical/tree/main/lexical-write-float pub const BUFFER_SIZE: usize = f64::FORMATTED_SIZE; lexical-util-0.8.5/src/digit.rs000064400000000000000000000067240072674642500145300ustar 00000000000000//! Utilities to process digits. //! //! This both contains routines to convert to and from digits, //! as well as iterate over digits while skipping digit separators. // CONST FNS // --------- // These are optimized functions for when the radix is known at compile-time, // which is **most** of our cases. There are cases where for codegen, using a // runtime algorithm is preferable. /// Unchecked, highly optimized algorithm to convert a char to a digit. /// This only works if the input character is known to be a valid digit. #[inline] pub const fn char_to_valid_digit_const(c: u8, radix: u32) -> u32 { if radix <= 10 { // Optimize for small radixes. (c.wrapping_sub(b'0')) as u32 } else { // Fallback, still decently fast. let digit = match c { b'0'..=b'9' => c - b'0', b'A'..=b'Z' => c - b'A' + 10, b'a'..=b'z' => c - b'a' + 10, _ => 0xFF, }; digit as u32 } } /// Convert a character to a digit with a radix known at compile time. /// /// This optimizes for cases where radix is <= 10, and uses a decent, /// match-based fallback algorithm. #[inline] pub const fn char_to_digit_const(c: u8, radix: u32) -> Option { let digit = char_to_valid_digit_const(c, radix); if digit < radix { Some(digit) } else { None } } /// Determine if a character is a digit with a radix known at compile time. #[inline] pub const fn char_is_digit_const(c: u8, radix: u32) -> bool { char_to_digit_const(c, radix).is_some() } /// Convert a digit to a character with a radix known at compile time. /// /// This optimizes for cases where radix is <= 10, and uses a decent, /// match-based fallback algorithm. #[inline] #[cfg(any(feature = "write", feature = "floats"))] pub const fn digit_to_char_const(digit: u32, radix: u32) -> u8 { if radix <= 10 || digit < 10 { // Can short-circuit if we know the radix is small at compile time. digit as u8 + b'0' } else { digit as u8 + b'A' - 10 } } // NON-CONST // --------- // These are less optimized functions for when the radix is not known at // compile-time, which is a few (but important) cases. These generally have // improved compiler optimization passes when generics are used more sparingly. /// Convert a character to a digit. #[inline] #[cfg(feature = "parse")] pub const fn char_to_digit(c: u8, radix: u32) -> Option { // Fallback, still decently fast. let digit = match c { b'0'..=b'9' => c - b'0', b'A'..=b'Z' => c - b'A' + 10, b'a'..=b'z' => c - b'a' + 10, _ => 0xFF, } as u32; if digit < radix { Some(digit) } else { None } } /// Determine if a character is a digit. #[inline] #[cfg(feature = "parse")] pub const fn char_is_digit(c: u8, radix: u32) -> bool { char_to_digit(c, radix).is_some() } /// Convert a digit to a character. This uses a pre-computed table to avoid branching. /// /// # Safety /// /// Safe as long as `digit < 36`. #[inline] #[cfg(feature = "write")] pub unsafe fn digit_to_char(digit: u32) -> u8 { const TABLE: [u8; 36] = [ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X', b'Y', b'Z', ]; debug_assert!(digit < 36, "digit_to_char() invalid character."); unsafe { *TABLE.get_unchecked(digit as usize) } } lexical-util-0.8.5/src/div128.rs000064400000000000000000000322330072674642500144370ustar 00000000000000//! Optimized division algorithms for u128. //! //! # Fast Algorithms //! //! The more optimized algorithms for calculating the divisor constants are //! based off of the paper "Division by Invariant Integers Using Multiplication", //! by T. Granlund and P. Montgomery, in "Proc. of the SIGPLAN94 Conference //! on Programming Language Design and Implementation", available online //! [here](https://gmplib.org/~tege/divcnst-pldi94.pdf). //! //! This approach is derived from the Rust algorithm for formatting 128-bit //! values, and therefore is similarly dual-licensed under MIT/Apache-2.0. //! //! # Fallback Algorithms //! //! The slower algorithms in this module are derived off of `dtolnay/itoa` //! and Rust's compiler-builtins crate. This copies a specific //! path of LLVM's `__udivmodti4` intrinsic, which does division/ //! modulus for u128 in a single step. Rust implements both division //! and modulus in terms of this intrinsic, but calls the intrinsic //! twice for subsequent division and modulus operations on the same //! dividend/divisor, leading to significant performance overhead. //! //! This module calculates the optimal divisors for each radix, //! and exports a general-purpose division algorithm for u128 where //! the divisor can fit in a u64. The moderate algorithm is derived from //! dtolnay/itoa, which can be found //! [here](https://github.com/dtolnay/itoa/blob/master/src/udiv128.rs), which //! in turn is derived from Rust's compiler-builtins crate, which can be found //! [here](https://github.com/rust-lang-nursery/compiler-builtins/blob/master/src/int/udiv.rs). //! //! Licensing for these routines is therefore subject to an MIT/Illinois //! dual license (a BSD-like license), while the rest of the module is //! subject to an MIT/Apache-2.0 dual-license. //! //! # Generation //! //! See [`etc/div128.py`] for the script to generate the divisors and the //! constants, and the division algorithm. //! //! [`etc/div128.py`]: https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-util/etc/div128.py #![cfg(not(feature = "compact"))] #![cfg(feature = "write")] use crate::assert::debug_assert_radix; use crate::mul::mulhi; /// Calculate a div/remainder algorithm optimized for power-of-two radixes. /// This is trivial: the number of digits we process is `64 / log2(radix)`. /// Therefore, the `shr` is `log2(radix) * digits`, and the mask is just the /// lower `shr` bits of the digits. #[inline] #[allow(clippy::many_single_char_names)] pub const fn pow2_u128_divrem(n: u128, mask: u64, shr: u32) -> (u128, u64) { let quot = n >> shr; let rem = mask & n as u64; (quot, rem) } /// Fast division/remainder algorithm for u128, without a fast native approximation. #[inline] #[allow(clippy::many_single_char_names)] pub fn fast_u128_divrem( n: u128, d: u64, fast: u128, fast_shr: u32, factor: u128, factor_shr: u32, ) -> (u128, u64) { let quot = if n < fast { ((n >> fast_shr) as u64 / (d >> fast_shr)) as u128 } else { mulhi::(n, factor) >> factor_shr }; let rem = (n - quot * d as u128) as u64; (quot, rem) } /// Fast division/remainder algorithm for u128, without a fast native approximation. #[inline] #[allow(clippy::many_single_char_names)] pub fn moderate_u128_divrem(n: u128, d: u64, factor: u128, factor_shr: u32) -> (u128, u64) { let quot = mulhi::(n, factor) >> factor_shr; let rem = (n - quot * d as u128) as u64; (quot, rem) } /// Optimized fallback division/remainder algorithm for u128. /// /// This is because the codegen for u128 divrem is very inefficient in Rust, /// calling both `__udivmodti4` twice internally, rather than a single time. /// /// This is still a fair bit slower than the optimized algorithms described /// in the above paper, but this is a suitable fallback when we cannot use /// the faster algorithm. #[inline] #[allow(clippy::many_single_char_names)] pub fn slow_u128_divrem(n: u128, d: u64, d_ctlz: u32) -> (u128, u64) { // Ensure we have the correct number of leading zeros passed. debug_assert_eq!(d_ctlz, d.leading_zeros()); // Optimize if we can divide using u64 first. let high = (n >> 64) as u64; if high == 0 { let low = n as u64; return ((low / d) as u128, low % d); } // sr = 1 + u64::BITS + d.leading_zeros() - high.leading_zeros(); let sr = 65 + d_ctlz - high.leading_zeros(); // 1 <= sr <= u64::BITS - 1 let mut q: u128 = n << (128 - sr); let mut r: u128 = n >> sr; let mut carry: u64 = 0; // Don't use a range because they may generate references to memcpy in unoptimized code // Loop invariants: r < d; carry is 0 or 1 let mut i = 0; while i < sr { i += 1; // r:q = ((r:q) << 1) | carry r = (r << 1) | (q >> 127); q = (q << 1) | carry as u128; // carry = 0 // if r >= d { // r -= d; // carry = 1; // } let s = (d as u128).wrapping_sub(r).wrapping_sub(1) as i128 >> 127; carry = (s & 1) as u64; r -= (d as u128) & s as u128; } ((q << 1) | carry as u128, r as u64) } /// Calculate the div/remainder of a value based on the radix. /// /// This uses the largest divisor possible for the given size, /// and uses various fast-path approximations for different types. /// /// 1. Powers-of-two can be cleanly split into 2 64-bit products. /// 2. Division that can be simulated as if by multiplication by a constant. /// 3. Cases of 2. with a power-of-two divisor. /// 4. Fallback cases. /// /// This returns the quotient and the remainder. /// For the number of digits processed, see /// [min_step](crate::step::min_step). #[inline(always)] pub fn u128_divrem(n: u128, radix: u32) -> (u128, u64) { debug_assert_radix(radix); if cfg!(feature = "radix") { match radix { 2 => u128_divrem_2(n), 3 => u128_divrem_3(n), 4 => u128_divrem_4(n), 5 => u128_divrem_5(n), 6 => u128_divrem_6(n), 7 => u128_divrem_7(n), 8 => u128_divrem_8(n), 9 => u128_divrem_9(n), 10 => u128_divrem_10(n), 11 => u128_divrem_11(n), 12 => u128_divrem_12(n), 13 => u128_divrem_13(n), 14 => u128_divrem_14(n), 15 => u128_divrem_15(n), 16 => u128_divrem_16(n), 17 => u128_divrem_17(n), 18 => u128_divrem_18(n), 19 => u128_divrem_19(n), 20 => u128_divrem_20(n), 21 => u128_divrem_21(n), 22 => u128_divrem_22(n), 23 => u128_divrem_23(n), 24 => u128_divrem_24(n), 25 => u128_divrem_25(n), 26 => u128_divrem_26(n), 27 => u128_divrem_27(n), 28 => u128_divrem_28(n), 29 => u128_divrem_29(n), 30 => u128_divrem_30(n), 31 => u128_divrem_31(n), 32 => u128_divrem_32(n), 33 => u128_divrem_33(n), 34 => u128_divrem_34(n), 35 => u128_divrem_35(n), 36 => u128_divrem_36(n), _ => unreachable!(), } } else if cfg!(feature = "power-of-two") { match radix { 2 => u128_divrem_2(n), 4 => u128_divrem_4(n), 8 => u128_divrem_8(n), 10 => u128_divrem_10(n), 16 => u128_divrem_16(n), 32 => u128_divrem_32(n), _ => unreachable!(), } } else { u128_divrem_10(n) } } // AUTO-GENERATED // These functions were auto-generated by `etc/div128.py`. // Do not edit them unless there is a good reason to. // Preferably, edit the source code to generate the constants. // // The seemingly magical values are all derived there, and are explained // in the function signatures of the functions they call. #[inline] const fn u128_divrem_2(n: u128) -> (u128, u64) { pow2_u128_divrem(n, 18446744073709551615, 64) } #[inline] fn u128_divrem_3(n: u128) -> (u128, u64) { slow_u128_divrem(n, 12157665459056928801, 0) } #[inline] const fn u128_divrem_4(n: u128) -> (u128, u64) { pow2_u128_divrem(n, 18446744073709551615, 64) } #[inline] fn u128_divrem_5(n: u128) -> (u128, u64) { moderate_u128_divrem(n, 7450580596923828125, 105312291668557186697918027683670432319, 61) } #[inline] fn u128_divrem_6(n: u128) -> (u128, u64) { fast_u128_divrem( n, 4738381338321616896, 309485009821345068724781056, 24, 165591931273573223021296166324748699891, 61, ) } #[inline] fn u128_divrem_7(n: u128) -> (u128, u64) { moderate_u128_divrem(n, 3909821048582988049, 200683792729517998822275406364627986707, 61) } #[inline] const fn u128_divrem_8(n: u128) -> (u128, u64) { pow2_u128_divrem(n, 9223372036854775807, 63) } #[inline] fn u128_divrem_9(n: u128) -> (u128, u64) { slow_u128_divrem(n, 12157665459056928801, 0) } #[inline] fn u128_divrem_10(n: u128) -> (u128, u64) { fast_u128_divrem( n, 10000000000000000000, 9671406556917033397649408, 19, 156927543384667019095894735580191660403, 62, ) } #[inline] fn u128_divrem_11(n: u128) -> (u128, u64) { slow_u128_divrem(n, 5559917313492231481, 1) } #[inline] fn u128_divrem_12(n: u128) -> (u128, u64) { slow_u128_divrem(n, 2218611106740436992, 3) } #[inline] fn u128_divrem_13(n: u128) -> (u128, u64) { moderate_u128_divrem(n, 8650415919381337933, 181410402513790565292660635782582404765, 62) } #[inline] fn u128_divrem_14(n: u128) -> (u128, u64) { fast_u128_divrem( n, 2177953337809371136, 1208925819614629174706176, 16, 1407280417134467544760816054546363235, 53, ) } #[inline] fn u128_divrem_15(n: u128) -> (u128, u64) { moderate_u128_divrem(n, 6568408355712890625, 1866504587258795246613513364166764993, 55) } #[inline] const fn u128_divrem_16(n: u128) -> (u128, u64) { pow2_u128_divrem(n, 18446744073709551615, 64) } #[inline] fn u128_divrem_17(n: u128) -> (u128, u64) { moderate_u128_divrem(n, 2862423051509815793, 68529153692836345537218837732158950089, 59) } #[inline] fn u128_divrem_18(n: u128) -> (u128, u64) { fast_u128_divrem( n, 6746640616477458432, 604462909807314587353088, 15, 232601011830094623283686247347795155951, 62, ) } #[inline] fn u128_divrem_19(n: u128) -> (u128, u64) { moderate_u128_divrem(n, 15181127029874798299, 25842538415601616733690423925257626679, 60) } #[inline] fn u128_divrem_20(n: u128) -> (u128, u64) { fast_u128_divrem( n, 1638400000000000000, 4951760157141521099596496896, 28, 239452428260295134118491722992235809941, 60, ) } #[inline] fn u128_divrem_21(n: u128) -> (u128, u64) { moderate_u128_divrem(n, 3243919932521508681, 120939747781233590383781714337497669585, 60) } #[inline] fn u128_divrem_22(n: u128) -> (u128, u64) { slow_u128_divrem(n, 6221821273427820544, 1) } #[inline] fn u128_divrem_23(n: u128) -> (u128, u64) { moderate_u128_divrem(n, 11592836324538749809, 270731922700393644432243678371210997949, 63) } #[inline] fn u128_divrem_24(n: u128) -> (u128, u64) { fast_u128_divrem( n, 876488338465357824, 10141204801825835211973625643008, 39, 55950381945266105153185943557606235389, 57, ) } #[inline] fn u128_divrem_25(n: u128) -> (u128, u64) { moderate_u128_divrem(n, 1490116119384765625, 131640364585696483372397534604588040399, 59) } #[inline] fn u128_divrem_26(n: u128) -> (u128, u64) { fast_u128_divrem( n, 2481152873203736576, 151115727451828646838272, 13, 316239166637962178669658228673482425689, 61, ) } #[inline] fn u128_divrem_27(n: u128) -> (u128, u64) { slow_u128_divrem(n, 4052555153018976267, 2) } #[inline] fn u128_divrem_28(n: u128) -> (u128, u64) { fast_u128_divrem( n, 6502111422497947648, 1237940039285380274899124224, 26, 241348591538561183926479953354701294803, 62, ) } #[inline] fn u128_divrem_29(n: u128) -> (u128, u64) { moderate_u128_divrem(n, 10260628712958602189, 152941450056053853841698190746050519297, 62) } #[inline] fn u128_divrem_30(n: u128) -> (u128, u64) { slow_u128_divrem(n, 15943230000000000000, 0) } #[inline] fn u128_divrem_31(n: u128) -> (u128, u64) { moderate_u128_divrem(n, 787662783788549761, 124519929891402176328714857711808162537, 58) } #[inline] const fn u128_divrem_32(n: u128) -> (u128, u64) { pow2_u128_divrem(n, 1152921504606846975, 60) } #[inline] fn u128_divrem_33(n: u128) -> (u128, u64) { slow_u128_divrem(n, 1667889514952984961, 3) } #[inline] fn u128_divrem_34(n: u128) -> (u128, u64) { fast_u128_divrem( n, 2386420683693101056, 75557863725914323419136, 12, 328792707121977505492535302517672775183, 61, ) } #[inline] fn u128_divrem_35(n: u128) -> (u128, u64) { moderate_u128_divrem(n, 3379220508056640625, 116097442450503652080238494022501325491, 60) } #[inline] fn u128_divrem_36(n: u128) -> (u128, u64) { fast_u128_divrem( n, 4738381338321616896, 309485009821345068724781056, 24, 165591931273573223021296166324748699891, 61, ) } lexical-util-0.8.5/src/error.rs000064400000000000000000000435540072674642500145630ustar 00000000000000//! Error type for numeric parsing functions. //! //! The error type is C-compatible, simplifying use external language //! bindings. use core::{fmt, mem}; use static_assertions::const_assert; #[cfg(feature = "std")] use std::error; /// Error code during parsing, indicating failure type. #[non_exhaustive] #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub enum Error { // PARSE ERRORS /// Integral overflow occurred during numeric parsing. Overflow(usize), /// Integral underflow occurred during numeric parsing. Underflow(usize), /// Invalid digit found before string termination. InvalidDigit(usize), /// Empty byte array found. Empty(usize), /// Empty mantissa found. EmptyMantissa(usize), /// Empty exponent found. EmptyExponent(usize), /// Empty integer found. EmptyInteger(usize), /// Empty fraction found. EmptyFraction(usize), /// Invalid positive mantissa sign was found. InvalidPositiveMantissaSign(usize), /// Mantissa sign was required(usize), but not found. MissingMantissaSign(usize), /// Exponent was present but not allowed. InvalidExponent(usize), /// Invalid positive exponent sign was found. InvalidPositiveExponentSign(usize), /// Exponent sign was required(usize), but not found. MissingExponentSign(usize), /// Exponent was present without fraction component. ExponentWithoutFraction(usize), /// Integer or integer component of float had invalid leading zeros. InvalidLeadingZeros(usize), /// No exponent with required exponent notation. MissingExponent(usize), /// Integral sign was required(usize), but not found. MissingSign(usize), /// Invalid positive sign for an integer was found. InvalidPositiveSign(usize), /// Invalid negative sign for an unsigned type was found. InvalidNegativeSign(usize), // NUMBER FORMAT ERRORS /// Invalid radix for the mantissa (significant) digits. InvalidMantissaRadix, /// Invalid base for the exponent. InvalidExponentBase, /// Invalid radix for the exponent digits. InvalidExponentRadix, /// Invalid digit separator character. InvalidDigitSeparator, /// Invalid decimal point character. InvalidDecimalPoint, /// Invalid symbol to represent exponent notation. InvalidExponentSymbol, /// Invalid character for a base prefix. InvalidBasePrefix, /// Invalid character for a base suffix. InvalidBaseSuffix, /// Invalid punctuation characters: multiple symbols overlap. InvalidPunctuation, /// Optional exponent flags were set while disabling exponent notation. InvalidExponentFlags, /// Set no positive mantissa sign while requiring mantissa signs. InvalidMantissaSign, /// Set no positive exponent sign while requiring exponent signs. InvalidExponentSign, /// Set optional special float flags while disable special floats. InvalidSpecial, /// Invalid consecutive integer digit separator. InvalidConsecutiveIntegerDigitSeparator, /// Invalid consecutive fraction digit separator. InvalidConsecutiveFractionDigitSeparator, /// Invalid consecutive exponent digit separator. InvalidConsecutiveExponentDigitSeparator, /// Invalid flags were set without the format feature. InvalidFlags, // OPTION ERRORS /// Invalid NaN string: must start with an `n` character. InvalidNanString, /// NaN string is too long. NanStringTooLong, /// Invalid short infinity string: must start with an `i` character. InvalidInfString, /// Short infinity string is too long. InfStringTooLong, /// Invalid long infinity string: must start with an `i` character. InvalidInfinityString, /// Long infinity string is too long. InfinityStringTooLong, /// Long infinity string is too short: it must be as long as short infinity. InfinityStringTooShort, /// Invalid float parsing algorithm. InvalidFloatParseAlgorithm, /// Invalid radix for the significant digits. InvalidRadix, /// Invalid precision flags for writing floats. InvalidFloatPrecision, /// Invalid negative exponent break: break is above 0. InvalidNegativeExponentBreak, /// Invalid positive exponent break: break is below 0. InvalidPositiveExponentBreak, // NOT AN ERROR /// An error did not actually occur, and the result was successful. Success, } // Ensure we don't have extra padding on the structure. const_assert!(mem::size_of::() <= 2 * mem::size_of::()); macro_rules! is_error_type { ($name:ident, $type:ident$($t:tt)*) => ( /// const fn check to see if an error is of a specific type. pub const fn $name(&self) -> bool { // Note: enum equality is not a const fn, so use a let expression. if let Self::$type$($t)* = self { true } else { false } } ); } impl Error { /// Get the index for the parsing error. pub fn index(&self) -> Option<&usize> { match self { // PARSE ERRORS Self::Overflow(index) => Some(index), Self::Underflow(index) => Some(index), Self::InvalidDigit(index) => Some(index), Self::Empty(index) => Some(index), Self::EmptyMantissa(index) => Some(index), Self::EmptyExponent(index) => Some(index), Self::EmptyInteger(index) => Some(index), Self::EmptyFraction(index) => Some(index), Self::InvalidPositiveMantissaSign(index) => Some(index), Self::MissingMantissaSign(index) => Some(index), Self::InvalidExponent(index) => Some(index), Self::InvalidPositiveExponentSign(index) => Some(index), Self::MissingExponentSign(index) => Some(index), Self::ExponentWithoutFraction(index) => Some(index), Self::InvalidLeadingZeros(index) => Some(index), Self::MissingExponent(index) => Some(index), Self::MissingSign(index) => Some(index), Self::InvalidPositiveSign(index) => Some(index), Self::InvalidNegativeSign(index) => Some(index), // NUMBER FORMAT ERRORS Self::InvalidMantissaRadix => None, Self::InvalidExponentBase => None, Self::InvalidExponentRadix => None, Self::InvalidDigitSeparator => None, Self::InvalidDecimalPoint => None, Self::InvalidExponentSymbol => None, Self::InvalidBasePrefix => None, Self::InvalidBaseSuffix => None, Self::InvalidPunctuation => None, Self::InvalidExponentFlags => None, Self::InvalidMantissaSign => None, Self::InvalidExponentSign => None, Self::InvalidSpecial => None, Self::InvalidConsecutiveIntegerDigitSeparator => None, Self::InvalidConsecutiveFractionDigitSeparator => None, Self::InvalidConsecutiveExponentDigitSeparator => None, Self::InvalidFlags => None, // OPTION ERRORS Self::InvalidNanString => None, Self::NanStringTooLong => None, Self::InvalidInfString => None, Self::InfStringTooLong => None, Self::InvalidInfinityString => None, Self::InfinityStringTooLong => None, Self::InfinityStringTooShort => None, Self::InvalidFloatParseAlgorithm => None, Self::InvalidRadix => None, Self::InvalidFloatPrecision => None, Self::InvalidNegativeExponentBreak => None, Self::InvalidPositiveExponentBreak => None, // NOT AN ERROR Self::Success => None, } } is_error_type!(is_overflow, Overflow(_)); is_error_type!(is_underflow, Underflow(_)); is_error_type!(is_invalid_digit, InvalidDigit(_)); is_error_type!(is_empty, Empty(_)); is_error_type!(is_empty_mantissa, EmptyMantissa(_)); is_error_type!(is_empty_exponent, EmptyExponent(_)); is_error_type!(is_empty_integer, EmptyInteger(_)); is_error_type!(is_empty_fraction, EmptyFraction(_)); is_error_type!(is_invalid_positive_mantissa_sign, InvalidPositiveMantissaSign(_)); is_error_type!(is_missing_mantissa_sign, MissingMantissaSign(_)); is_error_type!(is_invalid_exponent, InvalidExponent(_)); is_error_type!(is_invalid_positive_exponent_sign, InvalidPositiveExponentSign(_)); is_error_type!(is_missing_exponent_sign, MissingExponentSign(_)); is_error_type!(is_exponent_without_fraction, ExponentWithoutFraction(_)); is_error_type!(is_invalid_leading_zeros, InvalidLeadingZeros(_)); is_error_type!(is_missing_exponent, MissingExponent(_)); is_error_type!(is_missing_sign, MissingSign(_)); is_error_type!(is_invalid_positive_sign, InvalidPositiveSign(_)); is_error_type!(is_invalid_negative_sign, InvalidNegativeSign(_)); is_error_type!(is_invalid_mantissa_radix, InvalidMantissaRadix); is_error_type!(is_invalid_exponent_base, InvalidExponentBase); is_error_type!(is_invalid_exponent_radix, InvalidExponentRadix); is_error_type!(is_invalid_digit_separator, InvalidDigitSeparator); is_error_type!(is_invalid_decimal_point, InvalidDecimalPoint); is_error_type!(is_invalid_exponent_symbol, InvalidExponentSymbol); is_error_type!(is_invalid_base_prefix, InvalidBasePrefix); is_error_type!(is_invalid_base_suffix, InvalidBaseSuffix); is_error_type!(is_invalid_punctuation, InvalidPunctuation); is_error_type!(is_invalid_exponent_flags, InvalidExponentFlags); is_error_type!(is_invalid_mantissa_sign, InvalidMantissaSign); is_error_type!(is_invalid_exponent_sign, InvalidExponentSign); is_error_type!(is_invalid_special, InvalidSpecial); is_error_type!( is_invalid_consecutive_integer_digit_separator, InvalidConsecutiveIntegerDigitSeparator ); is_error_type!( is_invalid_consecutive_fraction_digit_separator, InvalidConsecutiveFractionDigitSeparator ); is_error_type!( is_invalid_consecutive_exponent_digit_separator, InvalidConsecutiveExponentDigitSeparator ); is_error_type!(is_invalid_flags, InvalidFlags); is_error_type!(is_invalid_nan_string, InvalidNanString); is_error_type!(is_nan_string_too_long, NanStringTooLong); is_error_type!(is_invalid_inf_string, InvalidInfString); is_error_type!(is_inf_string_too_long, InfStringTooLong); is_error_type!(is_invalid_infinity_string, InvalidInfinityString); is_error_type!(is_infinity_string_too_long, InfinityStringTooLong); is_error_type!(is_infinity_string_too_short, InfinityStringTooShort); is_error_type!(is_invalid_float_parse_algorithm, InvalidFloatParseAlgorithm); is_error_type!(is_invalid_radix, InvalidRadix); is_error_type!(is_invalid_float_precision, InvalidFloatPrecision); is_error_type!(is_invalid_negative_exponent_break, InvalidNegativeExponentBreak); is_error_type!(is_invalid_positive_exponent_break, InvalidPositiveExponentBreak); is_error_type!(is_success, Success); } /// Add an error message for parsing errors. macro_rules! write_parse_error { ($formatter:ident, $message:literal, $index:ident) => { write!($formatter, "lexical parse error: {} at index {}", $message, $index) }; } /// Add an error message for number format errors. macro_rules! format_message { ($formatter:ident, $message:literal) => { write!($formatter, "lexical number format error: {}", $message) }; } /// Add an error message for options errors. macro_rules! options_message { ($formatter:ident, $message:literal) => { write!($formatter, "lexical options error: {}", $message) }; } impl fmt::Display for Error { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { match self { // PARSE ERRORS Self::Overflow(index) => write_parse_error!(formatter, "'numeric overflow occurred'", index), Self::Underflow(index) => write_parse_error!(formatter, "'numeric underflow occurred'", index), Self::InvalidDigit(index) => write_parse_error!(formatter, "'invalid digit found'", index), Self::Empty(index) => write_parse_error!(formatter, "'the string to parse was empty'", index), Self::EmptyMantissa(index) => write_parse_error!(formatter, "'no significant digits found'", index), Self::EmptyExponent(index) => write_parse_error!(formatter, "'exponent notation found without an exponent'", index), Self::EmptyInteger(index) => write_parse_error!(formatter, "'invalid float with no integer digits'", index), Self::EmptyFraction(index) => write_parse_error!(formatter, "'invalid float with no fraction digits'", index), Self::InvalidPositiveMantissaSign(index) => write_parse_error!(formatter, "'invalid `+` sign before significant digits'", index), Self::MissingMantissaSign(index) => write_parse_error!(formatter, "'missing required `+/-` sign for significant digits'", index), Self::InvalidExponent(index) => write_parse_error!(formatter, "'exponent found but not allowed'", index), Self::InvalidPositiveExponentSign(index) => write_parse_error!(formatter, "'invalid `+` sign in exponent'", index), Self::MissingExponentSign(index) => write_parse_error!(formatter, "'missing required `+/-` sign for exponent'", index), Self::ExponentWithoutFraction(index) => write_parse_error!(formatter, "'invalid float containing exponent without fraction'", index), Self::InvalidLeadingZeros(index) => write_parse_error!(formatter, "'invalid number with leading zeros before digits'", index), Self::MissingExponent(index) => write_parse_error!(formatter, "'missing required exponent'", index), Self::MissingSign(index) => write_parse_error!(formatter, "'missing required `+/-` sign for integer'", index), Self::InvalidPositiveSign(index) => write_parse_error!(formatter, "'invalid `+` sign for an integer was found'", index), Self::InvalidNegativeSign(index) => write_parse_error!(formatter, "'invalid `-` sign for an unsigned type was found'", index), // NUMBER FORMAT ERRORS Self::InvalidMantissaRadix => format_message!(formatter, "'invalid radix for mantissa digits'"), Self::InvalidExponentBase => format_message!(formatter, "'invalid exponent base'"), Self::InvalidExponentRadix => format_message!(formatter, "'invalid radix for exponent digits'"), Self::InvalidDigitSeparator => format_message!(formatter, "'invalid digit separator: must be ASCII and not a digit or a `+/-` sign'"), Self::InvalidDecimalPoint => format_message!(formatter, "'invalid decimal point: must be ASCII and not a digit or a `+/-` sign'"), Self::InvalidExponentSymbol => format_message!(formatter, "'invalid exponent symbol: must be ASCII and not a digit or a `+/-` sign'"), Self::InvalidBasePrefix => format_message!(formatter, "'invalid base prefix character'"), Self::InvalidBaseSuffix => format_message!(formatter, "'invalid base suffix character'"), Self::InvalidPunctuation => format_message!(formatter, "'invalid punctuation: multiple characters overlap'"), Self::InvalidExponentFlags => format_message!(formatter, "'exponent flags set while disabling exponent notation'"), Self::InvalidMantissaSign => format_message!(formatter, "'disabled the `+` sign while requiring a sign for significant digits'"), Self::InvalidExponentSign => format_message!(formatter, "'disabled the `+` sign while requiring a sign for exponent digits'"), Self::InvalidSpecial => format_message!(formatter, "'special flags set while disabling special floats'"), Self::InvalidConsecutiveIntegerDigitSeparator => format_message!(formatter, "'enabled consecutive digit separators in the integer without setting a valid location'"), Self::InvalidConsecutiveFractionDigitSeparator => format_message!(formatter, "'enabled consecutive digit separators in the fraction without setting a valid location'"), Self::InvalidConsecutiveExponentDigitSeparator => format_message!(formatter, "'enabled consecutive digit separators in the exponent without setting a valid location'"), Self::InvalidFlags => format_message!(formatter, "'invalid flags enabled without the format feature'"), // OPTION ERRORS Self::InvalidNanString => options_message!(formatter, "'NaN string must started with `n`'"), Self::NanStringTooLong => options_message!(formatter, "'NaN string is too long'"), Self::InvalidInfString => options_message!(formatter, "'short infinity string must started with `i`'"), Self::InfStringTooLong => options_message!(formatter, "'short infinity string is too long'"), Self::InvalidInfinityString => options_message!(formatter, "'long infinity string must started with `i`'"), Self::InfinityStringTooLong => options_message!(formatter, "'long infinity string is too long'"), Self::InfinityStringTooShort => options_message!(formatter, "'long infinity string is too short'"), Self::InvalidFloatParseAlgorithm => options_message!(formatter, "'invalid combination of float parse algorithms'"), Self::InvalidRadix => options_message!(formatter, "'invalid radix for significant digits'"), Self::InvalidFloatPrecision => options_message!(formatter, "'invalid float precision: min digits is larger than max digits'"), Self::InvalidNegativeExponentBreak => options_message!(formatter, "'invalid negative exponent break: value is above 0'"), Self::InvalidPositiveExponentBreak => options_message!(formatter, "'invalid positive exponent break: value is below 0'"), // NOT AN ERROR Self::Success => write!(formatter, "'not actually an error'"), } } } #[cfg(feature = "std")] impl error::Error for Error { } lexical-util-0.8.5/src/extended_float.rs000064400000000000000000000024020072674642500164020ustar 00000000000000//! Extended precision floating-point type. //! //! Also contains helpers to convert to and from native rust floats. //! This representation stores the mantissa as a 64-bit unsigned integer, //! and the exponent as a 32-bit unsigned integer, allowed ~80 bits of //! precision (only 16 bits of the 32-bit integer are used, u32 is used //! for performance). Since there is no storage for the sign bit, //! this only works for positive floats. #![cfg(feature = "floats")] use crate::num::UnsignedInteger; /// Extended precision floating-point type. /// /// This doesn't have any methods because it's used for **very** different /// things for the Lemire, Bellepheron, and other algorithms. In Grisu, /// it's an unbiased representation, for Lemire, it's a biased representation. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct ExtendedFloat { /// Mantissa for the extended-precision float. pub mant: M, /// Binary exponent for the extended-precision float. pub exp: i32, } impl ExtendedFloat { /// Get the mantissa component. #[inline] pub fn mantissa(&self) -> M { self.mant } /// Get the exponent component. #[inline] pub fn exponent(&self) -> i32 { self.exp } } lexical-util-0.8.5/src/f16.rs000064400000000000000000000202570072674642500140210ustar 00000000000000//! Half-precision IEEE-754 floating point implementation. //! //! f16 is meant as an interchange format, and therefore there may be //! rounding error in using it for fast-path algorithms. Since there //! are no native operations using `f16`, this is of minimal concern. //! //! Some of this code has been implemented from //! [half-rs](https://github.com/starkat99/half-rs), to enable simple //! conversions to and from f32. #![cfg(feature = "f16")] #![doc(hidden)] use crate::num::Float; use core::cmp::Ordering; use core::{fmt, ops}; /// Half-precision IEEE-754 floating point type. #[allow(non_camel_case_types)] #[derive(Default, Copy, Clone)] pub struct f16 { /// Raw bitwise representation of the float as a 16-bit type. bits: u16, } unsafe impl Send for f16 { } unsafe impl Sync for f16 { } impl f16 { #[inline(always)] pub const fn to_bits(self) -> u16 { self.bits } #[inline(always)] pub const fn from_bits(bits: u16) -> Self { Self { bits, } } #[inline(always)] pub fn as_f32(self) -> f32 { f16_to_f32(self) } #[inline(always)] pub fn from_f32(value: f32) -> Self { f32_to_f16(value) } } impl PartialEq for f16 { #[inline(always)] fn eq(&self, other: &Self) -> bool { self.as_f32().eq(&other.as_f32()) } } impl PartialOrd for f16 { #[inline(always)] fn partial_cmp(&self, other: &Self) -> Option { self.as_f32().partial_cmp(&other.as_f32()) } } impl fmt::Debug for f16 { #[inline(always)] fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { self.as_f32().fmt(formatter) } } impl fmt::Display for f16 { #[inline(always)] fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { self.as_f32().fmt(formatter) } } impl ops::Add for f16 { type Output = Self; #[inline(always)] fn add(self, rhs: Self) -> Self::Output { Self::from_f32(self.as_f32() + rhs.as_f32()) } } impl ops::Div for f16 { type Output = Self; #[inline(always)] fn div(self, rhs: Self) -> Self::Output { Self::from_f32(self.as_f32() / rhs.as_f32()) } } impl ops::Mul for f16 { type Output = Self; #[inline(always)] fn mul(self, rhs: Self) -> Self::Output { Self::from_f32(self.as_f32() * rhs.as_f32()) } } impl ops::Sub for f16 { type Output = Self; #[inline(always)] fn sub(self, rhs: Self) -> Self::Output { Self::from_f32(self.as_f32() - rhs.as_f32()) } } impl ops::Rem for f16 { type Output = Self; #[inline(always)] fn rem(self, rhs: Self) -> Self::Output { Self::from_f32(self.as_f32() % rhs.as_f32()) } } impl ops::Neg for f16 { type Output = Self; #[inline(always)] fn neg(self) -> Self::Output { Self::from_bits(self.bits ^ (1 << 15)) } } impl ops::AddAssign for f16 { #[inline(always)] fn add_assign(&mut self, rhs: Self) { *self = *self + rhs; } } impl ops::DivAssign for f16 { #[inline(always)] fn div_assign(&mut self, rhs: Self) { *self = *self / rhs; } } impl ops::MulAssign for f16 { #[inline(always)] fn mul_assign(&mut self, rhs: Self) { *self = *self * rhs; } } impl ops::SubAssign for f16 { #[inline(always)] fn sub_assign(&mut self, rhs: Self) { *self = *self - rhs; } } impl ops::RemAssign for f16 { #[inline(always)] fn rem_assign(&mut self, rhs: Self) { *self = *self % rhs; } } // In the below functions, round to nearest, with ties to even. // Let us call the most significant bit that will be shifted out the round_bit. // // Round up if either // a) Removed part > tie. // (mantissa & round_bit) != 0 && (mantissa & (round_bit - 1)) != 0 // b) Removed part == tie, and retained part is odd. // (mantissa & round_bit) != 0 && (mantissa & (2 * round_bit)) != 0 // (If removed part == tie and retained part is even, do not round up.) // These two conditions can be combined into one: // (mantissa & round_bit) != 0 && (mantissa & ((round_bit - 1) | (2 * round_bit))) != 0 // which can be simplified into // (mantissa & round_bit) != 0 && (mantissa & (3 * round_bit - 1)) != 0 fn f16_to_f32(half: f16) -> f32 { let man_shift = f32::MANTISSA_SIZE - f16::MANTISSA_SIZE; let f16_bias = f16::EXPONENT_BIAS - f16::MANTISSA_SIZE; let f32_bias = f32::EXPONENT_BIAS - f32::MANTISSA_SIZE; // Check for signed zero if half.bits & (f16::SIGN_MASK - 1) == 0 { return f32::from_bits((half.bits as u32) << 16); } let half_sign = (half.bits & f16::SIGN_MASK) as u32; let half_exp = (half.bits & f16::EXPONENT_MASK) as u32; let half_man = (half.bits & f16::MANTISSA_MASK) as u32; if half.is_nan() { return f32::from_bits((half_sign << 16) | 0x7FC0_0000u32 | (half_man << man_shift)); } else if half.is_inf() { return f32::from_bits((half_sign << 16) | f32::INFINITY_BITS); } // Calculate single-precision components with adjusted exponent let sign = half_sign << 16; // Unbias exponent let unbiased_exp = ((half_exp as i32) >> f16::MANTISSA_SIZE) - f16_bias; // Check for subnormals, which will be normalized by adjusting exponent if half_exp == 0 { // Calculate how much to adjust the exponent by let e = (half_man as u16).leading_zeros() - (16 - f16::MANTISSA_SIZE as u32); // Rebias and adjust exponent let exp = (f32_bias as u32 - f16_bias as u32 - e) << f32::MANTISSA_SIZE; let man = (half_man << (f16_bias as u32 - 1 + e)) & f32::MANTISSA_MASK; return f32::from_bits(sign | exp | man); } // Rebias exponent for a normalized normal let exp = ((unbiased_exp + f32_bias) as u32) << f32::MANTISSA_SIZE; let man = (half_man & f16::MANTISSA_MASK as u32) << man_shift; f32::from_bits(sign | exp | man) } fn f32_to_f16(value: f32) -> f16 { let man_shift = f32::MANTISSA_SIZE - f16::MANTISSA_SIZE; let f16_bias = f16::EXPONENT_BIAS - f16::MANTISSA_SIZE; let f32_bias = f32::EXPONENT_BIAS - f32::MANTISSA_SIZE; // Convert to raw bytes let x = value.to_bits(); // Extract IEEE754 components let sign = x & f32::SIGN_MASK; let exp = x & f32::EXPONENT_MASK; let man = x & f32::MANTISSA_MASK; // Check for all exponent bits being set, which is Infinity or NaN if value.is_nan() { return f16::from_bits((sign >> 16) as u16 | 0x7e00 | (man >> man_shift) as u16); } else if value.is_inf() { return f16::from_bits((sign >> 16) as u16 | f16::INFINITY_BITS); } // The number is normalized, start assembling half precision version let half_sign = sign >> 16; // Unbias the exponent, then bias for half precision let unbiased_exp = ((exp >> f32::MANTISSA_SIZE) as i32) - f32_bias; let half_exp = unbiased_exp + f16_bias; // Check for exponent overflow, return +infinity if unbiased_exp >= 0x1F { return f16::from_bits(half_sign as u16 | f16::INFINITY_BITS); } // Check for underflow if half_exp <= 0 { // Check mantissa for what we can do if f16_bias - 1 - half_exp > f32::MANTISSA_SIZE + 1 { // No rounding possibility, so this is a full underflow, return signed zero return f16::from_bits(half_sign as u16); } // Don't forget about hidden leading mantissa bit when assembling mantissa let man = man | f32::HIDDEN_BIT_MASK; let mut half_man = man >> (f16_bias - 1 - half_exp); // Check for rounding (see comment above functions) let round_bit = 1 << (man_shift - half_exp); if (man & round_bit) != 0 && (man & (3 * round_bit - 1)) != 0 { half_man += 1; } // No exponent for subnormals return f16::from_bits((half_sign | half_man) as u16); } // Rebias the exponent let half_exp = (half_exp as u32) << f16::MANTISSA_SIZE; let half_man = man >> man_shift; let round_bit = 1 << (man_shift - 1); if (man & round_bit) != 0 && (man & (3 * round_bit - 1)) != 0 { // Round it f16::from_bits(((half_sign | half_exp | half_man) + 1) as u16) } else { f16::from_bits((half_sign | half_exp | half_man) as u16) } } lexical-util-0.8.5/src/feature_format.rs000064400000000000000000002360350072674642500164330ustar 00000000000000//! Configuration options for parsing and formatting numbers. //! //! This comprises 2 parts: a low-level API for generating packed structs //! containing enumerating for number formats (both syntax and lexer). //! //! # Syntax Format //! //! The syntax format defines **which** numeric string are valid. //! For example, if exponent notation is required or not //! allowed. //! //! # Control Format //! //! The control format defines what characters are valid, that is, which //! characters should be consider valid to continue tokenization. #![cfg(feature = "format")] // Sample test code for each language used: // // Rust // ---- // // Setup: // Save to `main.rs` and run `rustc main.rs -o main`. // // Code: // ```text // pub fn main() { // println!("{:?}", 3_.0f32); // println!("{:?}", "3_.0".parse::()); // } // ``` // // Python // ------ // // Setup: // Run `python` to enter the interpreter. // // Code: // ```text // print(3_.0) // print(float("3_.0")) // ``` // // C++ // --- // // Setup: // Save to `main.cc` and run `g++ main.cc -o main -std=c++XX`, // where XX is one of the following values: // - 98 // - 03 // - 11 // - 14 // - 17 // // Code: // ```text // #include // #include // #include // #include // #include // // double parse(const char* string) { // char* end; // double result = strtod(string, &end); // if (std::distance(string, reinterpret_cast(end)) != strlen(string)) { // throw std::invalid_argument("did not consume entire string."); // } // return result; // } // // int main() { // std::cout << 3'.0 << std::endl; // std::cout << parse("3'.0") << std::endl; // } // ``` // // C // - // // Setup: // Save to `main.c` and run `gcc main.c -o main -std=cXX`, // where XX is one of the following values: // - 89 // - 90 // - 99 // - 11 // - 18 // // Code: // ```text // #include // #include // #include // #include // // size_t distance(const char* first, const char* last) { // uintptr_t x = (uintptr_t) first; // uintptr_t y = (uintptr_t) last; // return (size_t) (y - x); // } // // double parse(const char* string) { // char* end; // double result = strtod(string, &end); // if (distance(string, (const char*) end) != strlen(string)) { // abort(); // } // return result; // } // // int main() { // printf("%f\n", 3'.); // printf("%f\n", parse("3'.")); // } // ``` // // Ruby // ---- // // Setup: // Run `irb` to enter the interpreter. // // Code: // ```text // puts 3.0_1; // puts "3.0_1".to_f; // ``` // Swift // ----- // // Setup: // Run `swift` to enter the interpreter. // // Code: // ```text // print(3.0); // print(Float("3.0")); // ``` // Golang // ------ // // Setup: // Save to `main.go` and run `go run main.go` // // Code: // ```text // package main // // import ( // "fmt" // "strconv" // ) // // func main() { // fmt.Println(3.0) // fmt.Println(strconv.ParseFloat("3.0", 64)) // } // ``` // // Haskell // ------- // // Setup: // Run `ghci` to enter the interpreter. // // Code: // ```text // :m Numeric // showFloat 3.0 "" // let x = "3.0" // read x :: Float // ``` // // Javascript // ---------- // // Setup: // Run `nodejs` (or `node`) to enter the interpreter. // // Code: // ```text // console.log(3.0) // console.log(parseFloat("3.0")) // ``` // // Perl // ---- // // Setup: // Run `perl -de1` to enter the interpret. // // Code: // ```text // print 3.01; // print '3.01' * 1; // ``` // // PHP // --- // // Setup: // Run `php -a` to enter the interpret. // // Code: // ```text // printf("%f\n", 3.0); // printf("%f\n", floatval("3.0")); // ``` // // Java // ---- // // Setup: // Save to `main.java` and run `javac main.java`, then run `java Main`. // // Code: // ```text // class Main { // public static void main(String args[]) { // System.out.println(3.0); // System.out.println(Float.parseFloat("3.0")); // } // } // ``` // // R // - // // Setup: // Run `R` to enter the interpret. // // Code: // ```text // print(3.0); // print(as.numeric("3.0")); // ``` // // Kotlin // ------ // // Setup: // Save file to `main.kt` and run `kotlinc main.kt -d main.jar`, // then run `java -jar main.jar`. // // Code: // ```text // fun main() { // println(3.0) // println("3.0".toDouble()) // } // ``` // // Julia // ----- // // Setup: // Run `julia` to enter the interpret. // // Code: // ```text // print(3.0); // print(parse(Float64, "3.0")); // ``` // // C# // -- // // Note: // Mono accepts both integer and fraction decimal separators, Mono is // just buggy, see https://github.com/dotnet/csharplang/issues/55#issuecomment-574902516. // // Setup: // Run `csharp -langversion:X` to enter the interpret, // where XX is one of the following values: // - ISO-1 // - ISO-2 // - 3 // - 4 // - 5 // - 6 // - 7 // // Code: // ```text // Console.WriteLine("{0}", 3.0); // Console.WriteLine("{0}", float.Parse("3.0")); // ``` // // Kawa // ---- // // Setup: // Run `kawa` to enter the interpreter. // // Code: // ```text // 3.0 // (string->number "3.0") // ``` // // Gambit-C // -------- // // Setup: // Run `gsc` to enter the interpreter. // // Code: // ```text // 3.0 // (string->number "3.0") // ``` // // Guile // ----- // // Setup: // Run `guile` to enter the interpreter. // // Code: // ```text // 3.0 // (string->number "3.0") // ``` // // Clojure // ------- // // Setup: // Run `clojure` to enter the interpreter. // // Code: // ```text // 3.0 // (Float/parseFloat "3.0") // ``` // // Erlang // ------ // // Setup: // Run `erl` to enter the interpreter. // // Code: // ```text // io:format("~p~n", [3.0]). // string:to_float("3.0"). // ``` // // Elm // --- // // Setup: // Run `elm repl` to enter the interpreter. // // Code: // ```text // 3.0 // String.toFloat "3.0" // ``` // // Scala // ----- // // Setup: // Run `scala` to enter the interpreter. // // Code: // ```text // 3.0 // "3.0".toFloat // ``` // // Elixir // ------ // // Setup: // Run `iex` to enter the interpreter. // // Code: // ```text // 3.0; // String.to_float("3.0"); // ``` // // FORTRAN // ------- // // Setup: // Save to `main.f90` and run `gfortran -o main main.f90` // // Code: // ```text // program main // real :: x // character (len=30) :: word // word = "3." // read(word, *) x // print *, 3. // print *, x // end program main // ``` // // D // - // // Setup: // Save to `main.d` and run `dmd -run main.d` // // Code: // ```text // import std.conv; // import std.stdio; // // void main() // { // writeln(3.0); // writeln(to!double("3.0")); // } // ``` // // Coffeescript // ------------ // // Setup: // Run `coffee` to enter the interpreter. // // Code: // ```text // 3.0; // parseFloat("3.0"); // ``` // // Cobol // ----- // // Setup: // Save to `main.cbl` and run `cobc main.cbl` then `cobcrun main`. // // Code: // ```text // IDENTIFICATION DIVISION. // PROGRAM-ID. main. // // DATA DIVISION. // WORKING-STORAGE SECTION. // 01 R PIC X(20) VALUE "3.0". // 01 TOTAL USAGE IS COMP-2. // // PROCEDURE DIVISION. // COMPUTE TOTAL = FUNCTION NUMVAL(R). // Display 3.0. // Display TOTAL. // STOP RUN. // ``` // // F# // -- // // Setup: // Run `dotnet fsi` to enter the interpreter. // // Code: // ```text // printfn "%f" 3.0;; // let f = float "3.0";; // printfn "%f" f;; // ``` // // Visual Basic // ------------ // // Setup: // Save to `main.vb` and run `vbnc main.vb`. // // Code: // ```text // Imports System // // Module Module1 // Sub Main() // Console.WriteLine(Format$(3.0, "0.0000000000000")) // Console.WriteLine(Format$(CDbl("3.0"), "0.0000000000000")) // End Sub // End Module // ``` // // OCaml // ----- // // Setup: // Save to `main.ml` and run `ocamlc -o main main.ml`. // // Code: // ```text // Printf.printf "%f\n" 3.0 // let () = // let f = float_of_string "3.0" in // Printf.printf "%f\n" f // ``` // // Objective-C // ----------- // // Setup: // Save to `main.m` and run `gcc -o main -lobjc -lgnustep-base main.m -fconstant-string-class=NSConstantString`. // // Code: // ```text // #import // #import // // int main(int argv, char* argc[]) // { // printf("%f\n", 3.0); // NSString *s = @"3.0"; // double f = [s doubleValue]; // printf("%f\n", f); // } // ``` // // ReasonML // -------- // // Setup: // Run `rtop` to enter the interpreter. // // Code: // ```text // Printf.printf("%f\n", 3.0); // Printf.printf("%f\n", float_of_string("3.0")); // ``` // // Zig // --- // // Setup: // Save to `main.zig` and run `zig build-exe main.zig` // // Code: // ```text // const std = @import("std"); // // pub fn main() void { // const f: f64 = 3.0; // std.debug.warn("{}\n", f); // const x: f64 = std.fmt.parseFloat(f64, "3.0") catch unreachable; // std.debug.warn("{}\n", x); // } // ``` // // // Octave (and Matlab) // ------------------- // // Setup: // Run `octave` to enter the interpreter, or // run `octave --traditional` to enter the Matlab interpret. // // Code: // ```text // 3.0 // str2double("3.0") // ``` // // Sage // ---- // // Setup: // Run `sage` to enter the interpreter. // // Code: // ```text // 3.0 // float("3.0") // ``` // // JSON // ---- // // Setup: // Run `node` (or `nodejs`) to enter the JS interpreter. // // Code: // ```text // JSON.parse("3.0") // ``` // // TOML // ---- // // Setup: // Run `python` to enter the Python interpreter. // // Code: // ```text // import tomlkit // tomlkit.parse("a = 3.0") // ``` // // XML // --- // // Setup: // Run `python` to enter the Python interpreter. // // Code: // ```text // from lxml import etree // // def validate_xml(xsd, xml): // '''Validate XML file against schema''' // // schema = etree.fromstring(xsd) // doc = etree.fromstring(xml) // xmlschema = etree.XMLSchema(schema) // // return xmlschema.validate(doc) // // // xsd = b''' // // // ''' // // xml = b''' // 3.0 // ''' // // validate_xml(xsd, xml) // ``` // // SQLite // ------ // // Setup: // Run `sqlite3 :memory:` to enter the sqlite3 interpreter // with an in-memory database. // // Code: // ```text // CREATE TABLE stocks (price real); // INSERT INTO stocks VALUES (3.0); // SELECT * FROM stocks; // ``` // // PostgreSQL // ---------- // // Setup: // Run `initdb -D db` to create a database data direction, // then run `pg_ctl -D db start` to start the server, then run // `createdb` to create a user database and `psql` to start the // interpreter. // // Code: // ```text // CREATE TABLE stocks (price real); // INSERT INTO stocks VALUES (3.0); // SELECT * FROM stocks; // ``` // // MySQL // ----- // // Setup: // Run `mysqld` to start the server, then run `mysql` to start the // interpreter. // // Code: // ```text // USE mysql; // CREATE TABLE stocks (price real); // INSERT INTO stocks VALUES (3.0); // SELECT * FROM stocks; // ``` // // MongoDB // ------- // // Setup: // Run `mongod --dbpath data/db` to start the server, then run // `mongo` to start the interpreter. // // Code: // ```text // use mydb // db.movie.insert({"name": 3.0}) // db.movie.find() // ``` use crate::error::Error; use crate::format_builder::NumberFormatBuilder; use crate::format_flags as flags; use core::num; use static_assertions::const_assert; /// Add multiple flags to SyntaxFormat. macro_rules! from_flag { ($format:ident, $flag:ident) => {{ $format & flags::$flag != 0 }}; } /// Wrapper for the 128-bit packed struct. /// /// See `NumberFormatBuilder` for the `FORMAT` fields /// for the packed struct. #[doc(hidden)] pub struct NumberFormat; #[rustfmt::skip] impl NumberFormat { // CONSTRUCTORS /// Create new instance (for methods and validation). pub const fn new() -> Self { Self {} } // VALIDATION /// Determine if the number format is valid. pub const fn is_valid(&self) -> bool { self.error().is_success() } /// Get the error type from the format. #[allow(clippy::if_same_then_else)] pub const fn error(&self) -> Error { if !flags::is_valid_radix(self.mantissa_radix()) { Error::InvalidMantissaRadix } else if !flags::is_valid_radix(self.exponent_base()) { Error::InvalidExponentBase } else if !flags::is_valid_radix(self.exponent_radix()) { Error::InvalidExponentRadix } else if !flags::is_valid_digit_separator(FORMAT) { Error::InvalidDigitSeparator } else if !flags::is_valid_base_prefix(FORMAT) { Error::InvalidBasePrefix } else if !flags::is_valid_base_suffix(FORMAT) { Error::InvalidBaseSuffix } else if !flags::is_valid_punctuation(FORMAT) { Error::InvalidPunctuation } else if !flags::is_valid_exponent_flags(FORMAT) { Error::InvalidExponentFlags } else if self.no_positive_mantissa_sign() && self.required_mantissa_sign() { Error::InvalidMantissaSign } else if self.no_positive_exponent_sign() && self.required_exponent_sign() { Error::InvalidExponentSign } else if self.no_special() && self.case_sensitive_special() { Error::InvalidSpecial } else if self.no_special() && self.special_digit_separator() { Error::InvalidSpecial } else if self.integer_digit_separator_flags() == flags::INTEGER_CONSECUTIVE_DIGIT_SEPARATOR { Error::InvalidConsecutiveIntegerDigitSeparator } else if self.fraction_digit_separator_flags() == flags::FRACTION_CONSECUTIVE_DIGIT_SEPARATOR { Error::InvalidConsecutiveFractionDigitSeparator } else if self.exponent_digit_separator_flags() == flags::EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR { Error::InvalidConsecutiveExponentDigitSeparator } else { Error::Success } } // NON-DIGIT SEPARATOR FLAGS & MASKS /// If digits are required before the decimal point. pub const REQUIRED_INTEGER_DIGITS: bool = from_flag!(FORMAT, REQUIRED_INTEGER_DIGITS); /// Get if digits are required before the decimal point. #[inline(always)] pub const fn required_integer_digits(&self) -> bool { Self::REQUIRED_INTEGER_DIGITS } /// If digits are required after the decimal point. pub const REQUIRED_FRACTION_DIGITS: bool = from_flag!(FORMAT, REQUIRED_FRACTION_DIGITS); /// Get if digits are required after the decimal point. #[inline(always)] pub const fn required_fraction_digits(&self) -> bool { Self::REQUIRED_FRACTION_DIGITS } /// If digits are required after the exponent character. pub const REQUIRED_EXPONENT_DIGITS: bool = from_flag!(FORMAT, REQUIRED_EXPONENT_DIGITS); /// Get if digits are required after the exponent character. #[inline(always)] pub const fn required_exponent_digits(&self) -> bool { Self::REQUIRED_EXPONENT_DIGITS } /// If significant digits are required. pub const REQUIRED_MANTISSA_DIGITS: bool = from_flag!(FORMAT, REQUIRED_MANTISSA_DIGITS); /// Get if significant digits are required. #[inline(always)] pub const fn required_mantissa_digits(&self) -> bool { Self::REQUIRED_MANTISSA_DIGITS } /// If at least 1 digit in the number is required. pub const REQUIRED_DIGITS: bool = from_flag!(FORMAT, REQUIRED_DIGITS); /// Get if at least 1 digit in the number is required. #[inline(always)] pub const fn required_digits(&self) -> bool { Self::REQUIRED_DIGITS } /// If a positive sign before the mantissa is not allowed. pub const NO_POSITIVE_MANTISSA_SIGN: bool = from_flag!(FORMAT, NO_POSITIVE_MANTISSA_SIGN); /// Get if a positive sign before the mantissa is not allowed. #[inline(always)] pub const fn no_positive_mantissa_sign(&self) -> bool { Self::NO_POSITIVE_MANTISSA_SIGN } /// If a sign symbol before the mantissa is required. pub const REQUIRED_MANTISSA_SIGN: bool = from_flag!(FORMAT, REQUIRED_MANTISSA_SIGN); /// Get if a sign symbol before the mantissa is required. #[inline(always)] pub const fn required_mantissa_sign(&self) -> bool { Self::REQUIRED_MANTISSA_SIGN } /// If exponent notation is not allowed. pub const NO_EXPONENT_NOTATION: bool = from_flag!(FORMAT, NO_EXPONENT_NOTATION); /// Get if exponent notation is not allowed. #[inline(always)] pub const fn no_exponent_notation(&self) -> bool { Self::NO_EXPONENT_NOTATION } /// If a positive sign before the exponent is not allowed. pub const NO_POSITIVE_EXPONENT_SIGN: bool = from_flag!(FORMAT, NO_POSITIVE_EXPONENT_SIGN); /// Get if a positive sign before the exponent is not allowed. #[inline(always)] pub const fn no_positive_exponent_sign(&self) -> bool { Self::NO_POSITIVE_EXPONENT_SIGN } /// If a sign symbol before the exponent is required. pub const REQUIRED_EXPONENT_SIGN: bool = from_flag!(FORMAT, REQUIRED_EXPONENT_SIGN); /// Get if a sign symbol before the exponent is required. #[inline(always)] pub const fn required_exponent_sign(&self) -> bool { Self::REQUIRED_EXPONENT_SIGN } /// If an exponent without fraction is not allowed. pub const NO_EXPONENT_WITHOUT_FRACTION: bool = from_flag!(FORMAT, NO_EXPONENT_WITHOUT_FRACTION); /// Get if an exponent without fraction is not allowed. #[inline(always)] pub const fn no_exponent_without_fraction(&self) -> bool { Self::NO_EXPONENT_WITHOUT_FRACTION } /// If special (non-finite) values are not allowed. pub const NO_SPECIAL: bool = from_flag!(FORMAT, NO_SPECIAL); /// Get if special (non-finite) values are not allowed. #[inline(always)] pub const fn no_special(&self) -> bool { Self::NO_SPECIAL } /// If special (non-finite) values are case-sensitive. pub const CASE_SENSITIVE_SPECIAL: bool = from_flag!(FORMAT, CASE_SENSITIVE_SPECIAL); /// Get if special (non-finite) values are case-sensitive. #[inline(always)] pub const fn case_sensitive_special(&self) -> bool { Self::CASE_SENSITIVE_SPECIAL } /// If leading zeros before an integer are not allowed. pub const NO_INTEGER_LEADING_ZEROS: bool = from_flag!(FORMAT, NO_INTEGER_LEADING_ZEROS); /// Get if leading zeros before an integer are not allowed. #[inline(always)] pub const fn no_integer_leading_zeros(&self) -> bool { Self::NO_INTEGER_LEADING_ZEROS } /// If leading zeros before a float are not allowed. pub const NO_FLOAT_LEADING_ZEROS: bool = from_flag!(FORMAT, NO_FLOAT_LEADING_ZEROS); /// Get if leading zeros before a float are not allowed. #[inline(always)] pub const fn no_float_leading_zeros(&self) -> bool { Self::NO_FLOAT_LEADING_ZEROS } /// If exponent notation is required. pub const REQUIRED_EXPONENT_NOTATION: bool = from_flag!(FORMAT, REQUIRED_EXPONENT_NOTATION); /// Get if exponent notation is required. #[inline(always)] pub const fn required_exponent_notation(&self) -> bool { Self::REQUIRED_EXPONENT_NOTATION } /// If exponent characters are case-sensitive. pub const CASE_SENSITIVE_EXPONENT: bool = from_flag!(FORMAT, CASE_SENSITIVE_EXPONENT); /// Get if exponent characters are case-sensitive. #[inline(always)] pub const fn case_sensitive_exponent(&self) -> bool { Self::CASE_SENSITIVE_EXPONENT } /// If base prefixes are case-sensitive. pub const CASE_SENSITIVE_BASE_PREFIX: bool = from_flag!(FORMAT, CASE_SENSITIVE_BASE_PREFIX); /// Get if base prefixes are case-sensitive. #[inline(always)] pub const fn case_sensitive_base_prefix(&self) -> bool { Self::CASE_SENSITIVE_BASE_PREFIX } /// If base suffixes are case-sensitive. pub const CASE_SENSITIVE_BASE_SUFFIX: bool = from_flag!(FORMAT, CASE_SENSITIVE_BASE_SUFFIX); /// Get if base suffixes are case-sensitive. #[inline(always)] pub const fn case_sensitive_base_suffix(&self) -> bool { Self::CASE_SENSITIVE_BASE_SUFFIX } // DIGIT SEPARATOR FLAGS & MASKS // If digit separators are allowed between integer digits. pub const INTEGER_INTERNAL_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, INTEGER_INTERNAL_DIGIT_SEPARATOR); /// Get if digit separators are allowed between integer digits. #[inline(always)] pub const fn integer_internal_digit_separator(&self) -> bool { Self::INTEGER_INTERNAL_DIGIT_SEPARATOR } /// If digit separators are allowed between fraction digits. pub const FRACTION_INTERNAL_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, FRACTION_INTERNAL_DIGIT_SEPARATOR); /// Get if digit separators are allowed between fraction digits. #[inline(always)] pub const fn fraction_internal_digit_separator(&self) -> bool { Self::FRACTION_INTERNAL_DIGIT_SEPARATOR } /// If digit separators are allowed between exponent digits. pub const EXPONENT_INTERNAL_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, EXPONENT_INTERNAL_DIGIT_SEPARATOR); /// Get if digit separators are allowed between exponent digits. #[inline(always)] pub const fn exponent_internal_digit_separator(&self) -> bool { Self::EXPONENT_INTERNAL_DIGIT_SEPARATOR } /// If digit separators are allowed between digits. pub const INTERNAL_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, INTERNAL_DIGIT_SEPARATOR); /// Get if digit separators are allowed between digits. #[inline(always)] pub const fn internal_digit_separator(&self) -> bool { Self::INTERNAL_DIGIT_SEPARATOR } /// If a digit separator is allowed before any integer digits. pub const INTEGER_LEADING_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, INTEGER_LEADING_DIGIT_SEPARATOR); /// Get if a digit separator is allowed before any integer digits. #[inline(always)] pub const fn integer_leading_digit_separator(&self) -> bool { Self::INTEGER_LEADING_DIGIT_SEPARATOR } /// If a digit separator is allowed before any integer digits. pub const FRACTION_LEADING_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, FRACTION_LEADING_DIGIT_SEPARATOR); /// Get if a digit separator is allowed before any fraction digits. #[inline(always)] pub const fn fraction_leading_digit_separator(&self) -> bool { Self::FRACTION_LEADING_DIGIT_SEPARATOR } /// If a digit separator is allowed before any exponent digits. pub const EXPONENT_LEADING_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, EXPONENT_LEADING_DIGIT_SEPARATOR); /// Get if a digit separator is allowed before any exponent digits. #[inline(always)] pub const fn exponent_leading_digit_separator(&self) -> bool { Self::EXPONENT_LEADING_DIGIT_SEPARATOR } /// If a digit separator is allowed before any digits. pub const LEADING_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, LEADING_DIGIT_SEPARATOR); /// Get if a digit separator is allowed before any digits. #[inline(always)] pub const fn leading_digit_separator(&self) -> bool { Self::LEADING_DIGIT_SEPARATOR } /// If a digit separator is allowed after any integer digits. pub const INTEGER_TRAILING_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, INTEGER_TRAILING_DIGIT_SEPARATOR); /// Get if a digit separator is allowed after any integer digits. #[inline(always)] pub const fn integer_trailing_digit_separator(&self) -> bool { Self::INTEGER_TRAILING_DIGIT_SEPARATOR } /// If a digit separator is allowed after any fraction digits. pub const FRACTION_TRAILING_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, FRACTION_TRAILING_DIGIT_SEPARATOR); /// Get if a digit separator is allowed after any fraction digits. #[inline(always)] pub const fn fraction_trailing_digit_separator(&self) -> bool { Self::FRACTION_TRAILING_DIGIT_SEPARATOR } /// If a digit separator is allowed after any exponent digits. pub const EXPONENT_TRAILING_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, EXPONENT_TRAILING_DIGIT_SEPARATOR); /// Get if a digit separator is allowed after any exponent digits. #[inline(always)] pub const fn exponent_trailing_digit_separator(&self) -> bool { Self::EXPONENT_TRAILING_DIGIT_SEPARATOR } /// If a digit separator is allowed after any digits. pub const TRAILING_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, TRAILING_DIGIT_SEPARATOR); /// Get if a digit separator is allowed after any digits. #[inline(always)] pub const fn trailing_digit_separator(&self) -> bool { Self::TRAILING_DIGIT_SEPARATOR } /// If multiple consecutive integer digit separators are allowed. pub const INTEGER_CONSECUTIVE_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, INTEGER_CONSECUTIVE_DIGIT_SEPARATOR); /// Get if multiple consecutive integer digit separators are allowed. #[inline(always)] pub const fn integer_consecutive_digit_separator(&self) -> bool { Self::INTEGER_CONSECUTIVE_DIGIT_SEPARATOR } /// If multiple consecutive fraction digit separators are allowed. pub const FRACTION_CONSECUTIVE_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, FRACTION_CONSECUTIVE_DIGIT_SEPARATOR); /// Get if multiple consecutive fraction digit separators are allowed. #[inline(always)] pub const fn fraction_consecutive_digit_separator(&self) -> bool { Self::FRACTION_CONSECUTIVE_DIGIT_SEPARATOR } /// If multiple consecutive exponent digit separators are allowed. pub const EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR); /// Get if multiple consecutive exponent digit separators are allowed. #[inline(always)] pub const fn exponent_consecutive_digit_separator(&self) -> bool { Self::EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR } /// If multiple consecutive digit separators are allowed. pub const CONSECUTIVE_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, CONSECUTIVE_DIGIT_SEPARATOR); /// Get if multiple consecutive digit separators are allowed. #[inline(always)] pub const fn consecutive_digit_separator(&self) -> bool { Self::CONSECUTIVE_DIGIT_SEPARATOR } /// If any digit separators are allowed in special (non-finite) values. pub const SPECIAL_DIGIT_SEPARATOR: bool = from_flag!(FORMAT, SPECIAL_DIGIT_SEPARATOR); /// Get if any digit separators are allowed in special (non-finite) values. #[inline(always)] pub const fn special_digit_separator(&self) -> bool { Self::SPECIAL_DIGIT_SEPARATOR } // CHARACTERS /// The digit separator character in the packed struct. pub const DIGIT_SEPARATOR: u8 = flags::digit_separator(FORMAT); /// Get the digit separator character. /// /// If the digit separator is 0, digit separators are not allowed. #[inline(always)] pub const fn digit_separator(&self) -> u8 { Self::DIGIT_SEPARATOR } /// The base prefix character in the packed struct. pub const BASE_PREFIX: u8 = flags::base_prefix(FORMAT); /// Get the character for the base prefix. /// /// If the base prefix is 0, base prefixes are not allowed. /// The number will have then have the format `0$base_prefix...`. /// For example, a hex base prefix would be `0x`. Base prefixes are /// always optional. #[inline(always)] pub const fn base_prefix(&self) -> u8 { Self::BASE_PREFIX } /// The base suffix character in the packed struct. pub const BASE_SUFFIX: u8 = flags::base_suffix(FORMAT); /// Character for the base suffix. /// /// If not provided, base suffixes are not allowed. /// The number will have then have the format `...$base_suffix`. /// For example, a hex base prefix would be `0x`. Base prefixes are /// always optional. #[inline(always)] pub const fn base_suffix(&self) -> u8 { Self::BASE_SUFFIX } // RADIX /// The radix for the significant digits in the packed struct. pub const MANTISSA_RADIX: u32 = flags::mantissa_radix(FORMAT); /// Get the radix for the mantissa digits. #[inline(always)] pub const fn mantissa_radix(&self) -> u32 { Self::MANTISSA_RADIX } /// The radix for the significant digits in the packed struct. /// Alias for `MANTISSA_RADIX`. pub const RADIX: u32 = Self::MANTISSA_RADIX; /// Get the radix for the significant digits. #[inline(always)] pub const fn radix(&self) -> u32 { Self::RADIX } /// The base for the exponent. pub const EXPONENT_BASE: u32 = flags::exponent_base(FORMAT); /// Get the base for the exponent. /// /// IE, a base of 2 means we have `mantissa * 2^exponent`. /// If not provided, it defaults to `radix`. #[inline(always)] pub const fn exponent_base(&self) -> u32 { Self::EXPONENT_BASE } /// The radix for the exponent digits. pub const EXPONENT_RADIX: u32 = flags::exponent_radix(FORMAT); /// Get the radix for the exponent digits. /// /// If not provided, defaults to `radix`. #[inline(always)] pub const fn exponent_radix(&self) -> u32 { Self::EXPONENT_RADIX } // FLAGS /// Get the flags from the number format. #[inline(always)] pub const fn flags(&self) -> u128 { FORMAT & flags::FLAG_MASK } /// Get the interface flags from the number format. #[inline(always)] pub const fn interface_flags(&self) -> u128 { FORMAT & flags::INTERFACE_FLAG_MASK } /// Get the digit separator flags from the number format. #[inline(always)] pub const fn digit_separator_flags(&self) -> u128 { FORMAT & flags::DIGIT_SEPARATOR_FLAG_MASK } /// Get the exponent flags from the number format. #[inline(always)] pub const fn exponent_flags(&self) -> u128 { FORMAT & flags::EXPONENT_FLAG_MASK } /// Get the integer digit separator flags from the number format. #[inline(always)] pub const fn integer_digit_separator_flags(&self) -> u128 { FORMAT & flags::INTEGER_DIGIT_SEPARATOR_FLAG_MASK } /// Get the fraction digit separator flags from the number format. #[inline(always)] pub const fn fraction_digit_separator_flags(&self) -> u128 { FORMAT & flags::FRACTION_DIGIT_SEPARATOR_FLAG_MASK } /// Get the exponent digit separator flags from the number format. #[inline(always)] pub const fn exponent_digit_separator_flags(&self) -> u128 { FORMAT & flags::EXPONENT_DIGIT_SEPARATOR_FLAG_MASK } // BUILDER /// Get the number format builder from the format. #[inline] pub const fn builder() -> NumberFormatBuilder { NumberFormatBuilder::new() } /// Get the number format builder from the format. #[inline] pub const fn rebuild() -> NumberFormatBuilder { NumberFormatBuilder::rebuild(FORMAT) } } // PRE-DEFINED CONSTANTS // --------------------- // // Sample Format Shorthand: // ------------------------ // // The format shorthand lists the test cases, and if applicable, // the digit separator character. For example, the shorthand // `[134-_]` specifies it passes tests 1, 3, and 4, and uses // `'_'` as a digit-separator character. Meanwhile, `[0]` means it // passes test 0, and has no digit separator. // RUST LITERAL [4569ABFGHIJKMN-_] /// Number format for a Rust literal floating-point number. #[rustfmt::skip] pub const RUST_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .required_digits(true) .no_positive_mantissa_sign(true) .no_special(true) .internal_digit_separator(true) .trailing_digit_separator(true) .consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ RUST_LITERAL }> {}.is_valid()); // RUST STRING [0134567MN] /// Number format to parse a Rust float from string. #[rustfmt::skip] pub const RUST_STRING: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ RUST_STRING }> {}.is_valid()); /// Number format for a Python literal floating-point number. pub const PYTHON_LITERAL: u128 = PYTHON3_LITERAL; /// Number format to parse a Python float from string. pub const PYTHON_STRING: u128 = PYTHON3_STRING; /// Number format for a Python3 literal floating-point number. pub const PYTHON3_LITERAL: u128 = PYTHON36_LITERAL; // PYTHON3 STRING [0134567MN] /// Number format to parse a Python3 float from string. #[rustfmt::skip] pub const PYTHON3_STRING: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ PYTHON3_STRING }> {}.is_valid()); // PYTHON3.6+ LITERAL [013456N-_] /// Number format for a Python3.6 or higher literal floating-point number. #[rustfmt::skip] pub const PYTHON36_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .no_special(true) .no_integer_leading_zeros(true) .internal_digit_separator(true) .build(); const_assert!(NumberFormat::<{ PYTHON36_LITERAL }> {}.is_valid()); // PYTHON3.5- LITERAL [013456N] /// Number format for a Python3.5 or lower literal floating-point number. #[rustfmt::skip] pub const PYTHON35_LITERAL: u128 = NumberFormatBuilder::new() .no_special(true) .no_integer_leading_zeros(true) .build(); const_assert!(NumberFormat::<{ PYTHON35_LITERAL }> {}.is_valid()); // PYTHON2 LITERAL [013456MN] /// Number format for a Python2 literal floating-point number. #[rustfmt::skip] pub const PYTHON2_LITERAL: u128 = NumberFormatBuilder::new() .no_special(true) .build(); const_assert!(NumberFormat::<{ PYTHON2_LITERAL }> {}.is_valid()); // PYTHON2 STRING [0134567MN] /// Number format to parse a Python2 float from string. #[rustfmt::skip] pub const PYTHON2_STRING: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ PYTHON2_STRING }> {}.is_valid()); /// Number format for a C++ literal floating-point number. pub const CXX_LITERAL: u128 = CXX20_LITERAL; /// Number format to parse a C++ float from string. pub const CXX_STRING: u128 = CXX20_STRING; /// Number format for a C++ literal hexadecimal floating-point number. #[cfg(feature = "power-of-two")] pub const CXX_HEX_LITERAL: u128 = CXX20_HEX_LITERAL; /// Number format to parse a C++ hexadecimal float from string. #[cfg(feature = "power-of-two")] pub const CXX_HEX_STRING: u128 = CXX20_HEX_STRING; // C++20 LITERAL [013456789ABMN-'] /// Number format for a C++20 literal floating-point number. #[rustfmt::skip] pub const CXX20_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'\'')) .case_sensitive_special(true) .internal_digit_separator(true) .build(); const_assert!(NumberFormat::<{ CXX20_LITERAL }> {}.is_valid()); // C++20 STRING [0134567MN] /// Number format for a C++20 string floating-point number. #[rustfmt::skip] pub const CXX20_STRING: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ CXX20_STRING }> {}.is_valid()); // C++20 HEX LITERAL [013456789ABMN-'] /// Number format for a C++20 literal hexadecimal floating-point number. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const CXX20_HEX_LITERAL: u128 = NumberFormatBuilder::new() .required_exponent_notation(true) .digit_separator(num::NonZeroU8::new(b'\'')) .mantissa_radix(16) .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .case_sensitive_special(true) .internal_digit_separator(true) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ CXX20_HEX_LITERAL }> {}.is_valid()); // C++20 HEX STRING [0134567MN] /// Number format for a C++20 string hexadecimal floating-point number. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const CXX20_HEX_STRING: u128 = NumberFormatBuilder::new() .mantissa_radix(16) .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ CXX20_HEX_STRING }> {}.is_valid()); // C++17 LITERAL [013456789ABMN-'] /// Number format for a C++17 literal floating-point number. #[rustfmt::skip] pub const CXX17_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'\'')) .case_sensitive_special(true) .internal_digit_separator(true) .build(); const_assert!(NumberFormat::<{ CXX17_LITERAL }> {}.is_valid()); // C++17 STRING [0134567MN] /// Number format for a C++17 string floating-point number. #[rustfmt::skip] pub const CXX17_STRING: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ CXX17_STRING }> {}.is_valid()); // C++17 HEX LITERAL [013456789ABMN-'] /// Number format for a C++17 literal hexadecimal floating-point number. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const CXX17_HEX_LITERAL: u128 = NumberFormatBuilder::new() .required_exponent_notation(true) .digit_separator(num::NonZeroU8::new(b'\'')) .mantissa_radix(16) .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .case_sensitive_special(true) .internal_digit_separator(true) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ CXX17_HEX_LITERAL }> {}.is_valid()); // C++17 HEX STRING [0134567MN] /// Number format for a C++17 string hexadecimal floating-point number. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const CXX17_HEX_STRING: u128 = NumberFormatBuilder::new() .mantissa_radix(16) .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ CXX17_HEX_STRING }> {}.is_valid()); // C++14 LITERAL [013456789ABMN-'] /// Number format for a C++14 literal floating-point number. #[rustfmt::skip] pub const CXX14_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'\'')) .case_sensitive_special(true) .internal_digit_separator(true) .build(); const_assert!(NumberFormat::<{ CXX14_LITERAL }> {}.is_valid()); // C++14 STRING [0134567MN] /// Number format for a C++14 string floating-point number. #[rustfmt::skip] pub const CXX14_STRING: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ CXX14_STRING }> {}.is_valid()); // C++14 HEX STRING [0134567MN] /// Number format for a C++14 string hexadecimal floating-point number. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const CXX14_HEX_STRING: u128 = NumberFormatBuilder::new() .mantissa_radix(16) .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ CXX14_HEX_STRING }> {}.is_valid()); // C++11 LITERAL [01345678MN] /// Number format for a C++11 literal floating-point number. #[rustfmt::skip] pub const CXX11_LITERAL: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ CXX11_LITERAL }> {}.is_valid()); // C++11 STRING [0134567MN] /// Number format for a C++11 string floating-point number. #[rustfmt::skip] pub const CXX11_STRING: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ CXX11_STRING }> {}.is_valid()); // C++11 HEX STRING [0134567MN] /// Number format for a C++11 string hexadecimal floating-point number. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const CXX11_HEX_STRING: u128 = NumberFormatBuilder::new() .mantissa_radix(16) .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ CXX11_HEX_STRING }> {}.is_valid()); // C++03 LITERAL [01345678MN] /// Number format for a C++03 literal floating-point number. #[rustfmt::skip] pub const CXX03_LITERAL: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ CXX03_LITERAL }> {}.is_valid()); // C++03 STRING [0134567MN] /// Number format for a C++03 string floating-point number. #[rustfmt::skip] pub const CXX03_STRING: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ CXX03_STRING }> {}.is_valid()); // C++98 LITERAL [01345678MN] /// Number format for a C++98 literal floating-point number. #[rustfmt::skip] pub const CXX98_LITERAL: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ CXX98_LITERAL }> {}.is_valid()); // C++98 STRING [0134567MN] /// Number format for a C++98 string floating-point number. #[rustfmt::skip] pub const CXX98_STRING: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ CXX98_STRING }> {}.is_valid()); /// Number format for a C literal floating-point number. pub const C_LITERAL: u128 = C18_LITERAL; /// Number format to parse a C float from string. pub const C_STRING: u128 = C18_STRING; /// Number format for a C literal hexadecimal floating-point number. #[cfg(feature = "power-of-two")] pub const C_HEX_LITERAL: u128 = C18_HEX_LITERAL; /// Number format to parse a C hexadecimal float from string. #[cfg(feature = "power-of-two")] pub const C_HEX_STRING: u128 = C18_HEX_STRING; // C18 LITERAL [01345678MN] /// Number format for a C++98 literal floating-point number. #[rustfmt::skip] pub const C18_LITERAL: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ C18_LITERAL }> {}.is_valid()); // C18 STRING [0134567MN] /// Number format for a C++98 string floating-point number. #[rustfmt::skip] pub const C18_STRING: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ C18_STRING }> {}.is_valid()); // C18 HEX LITERAL [01345678MN] /// Number format for a C++98 literal hexadecimal floating-point number. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const C18_HEX_LITERAL: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .required_exponent_notation(true) .mantissa_radix(16) .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ C18_HEX_LITERAL }> {}.is_valid()); // C18 HEX STRING [0134567MN] /// Number format for a C18 string hexadecimal floating-point number. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const C18_HEX_STRING: u128 = NumberFormatBuilder::new() .mantissa_radix(16) .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ C18_HEX_STRING }> {}.is_valid()); // C11 LITERAL [01345678MN] /// Number format for a C++98 literal floating-point number. #[rustfmt::skip] pub const C11_LITERAL: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ C11_LITERAL }> {}.is_valid()); // C11 STRING [0134567MN] /// Number format for a C++98 string floating-point number. #[rustfmt::skip] pub const C11_STRING: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ C11_STRING }> {}.is_valid()); // C11 HEX LITERAL [01345678MN] /// Number format for a C++98 literal hexadecimal floating-point number. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const C11_HEX_LITERAL: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .required_exponent_notation(true) .mantissa_radix(16) .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ C11_HEX_LITERAL }> {}.is_valid()); // C11 HEX STRING [0134567MN] /// Number format for a C11 string hexadecimal floating-point number. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const C11_HEX_STRING: u128 = NumberFormatBuilder::new() .mantissa_radix(16) .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ C11_HEX_STRING }> {}.is_valid()); // C99 LITERAL [01345678MN] /// Number format for a C++98 literal floating-point number. #[rustfmt::skip] pub const C99_LITERAL: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ C99_LITERAL }> {}.is_valid()); // C99 STRING [0134567MN] /// Number format for a C++98 string floating-point number. #[rustfmt::skip] pub const C99_STRING: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ C99_STRING }> {}.is_valid()); // C99 HEX LITERAL [01345678MN] /// Number format for a C++98 literal hexadecimal floating-point number. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const C99_HEX_LITERAL: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .required_exponent_notation(true) .mantissa_radix(16) .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ C99_HEX_LITERAL }> {}.is_valid()); // C99 HEX STRING [0134567MN] /// Number format for a C99 string hexadecimal floating-point number. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const C99_HEX_STRING: u128 = NumberFormatBuilder::new() .mantissa_radix(16) .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ C99_HEX_STRING }> {}.is_valid()); // C90 LITERAL [013456MN] /// Number format for a C++98 literal floating-point number. #[rustfmt::skip] pub const C90_LITERAL: u128 = NumberFormatBuilder::new() .no_special(true) .build(); const_assert!(NumberFormat::<{ C90_LITERAL }> {}.is_valid()); // C90 STRING [0134567MN] /// Number format for a C++98 string floating-point number. #[rustfmt::skip] pub const C90_STRING: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ C90_STRING }> {}.is_valid()); // C90 HEX STRING [0134567MN] /// Number format for a C90 string hexadecimal floating-point number. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const C90_HEX_STRING: u128 = NumberFormatBuilder::new() .mantissa_radix(16) .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ C90_HEX_STRING }> {}.is_valid()); // C89 LITERAL [013456MN] /// Number format for a C++98 literal floating-point number. #[rustfmt::skip] pub const C89_LITERAL: u128 = NumberFormatBuilder::new() .no_special(true) .build(); const_assert!(NumberFormat::<{ C89_LITERAL }> {}.is_valid()); // C89 STRING [0134567MN] /// Number format for a C++98 string floating-point number. #[rustfmt::skip] pub const C89_STRING: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ C89_STRING }> {}.is_valid()); // C89 HEX STRING [0134567MN] /// Number format for a C89 string hexadecimal floating-point number. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const C89_HEX_STRING: u128 = NumberFormatBuilder::new() .mantissa_radix(16) .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ C89_HEX_STRING }> {}.is_valid()); // RUBY LITERAL [345689AMN-_] /// Number format for a Ruby literal floating-point number. #[rustfmt::skip] pub const RUBY_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .required_digits(true) .no_special(true) .no_integer_leading_zeros(true) .no_float_leading_zeros(true) .internal_digit_separator(true) .build(); const_assert!(NumberFormat::<{ RUBY_LITERAL }> {}.is_valid()); // RUBY OCTAL LITERAL [345689AN-_] /// Number format for a Ruby literal floating-point number. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const RUBY_OCTAL_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .mantissa_radix(8) .required_digits(true) .no_special(true) .internal_digit_separator(true) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ RUBY_OCTAL_LITERAL }> {}.is_valid()); // RUBY STRING [01234569ABMN-_] // Note: Amazingly, Ruby 1.8+ do not allow parsing special values. /// Number format to parse a Ruby float from string. #[rustfmt::skip] pub const RUBY_STRING: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .no_special(true) .internal_digit_separator(true) .build(); const_assert!(NumberFormat::<{ RUBY_STRING }> {}.is_valid()); // SWIFT LITERAL [34569ABFGHIJKMN-_] /// Number format for a Swift literal floating-point number. #[rustfmt::skip] pub const SWIFT_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .required_digits(true) .no_special(true) .internal_digit_separator(true) .trailing_digit_separator(true) .consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ SWIFT_LITERAL }> {}.is_valid()); // SWIFT STRING [134567MN] /// Number format to parse a Swift float from string. #[rustfmt::skip] pub const SWIFT_STRING: u128 = NumberFormatBuilder::new() .required_fraction_digits(true) .build(); const_assert!(NumberFormat::<{ SWIFT_STRING }> {}.is_valid()); // GO LITERAL [13456MN] /// Number format for a Golang literal floating-point number. #[rustfmt::skip] pub const GO_LITERAL: u128 = NumberFormatBuilder::new() .required_fraction_digits(true) .no_special(true) .build(); const_assert!(NumberFormat::<{ GO_LITERAL }> {}.is_valid()); // GO STRING [134567MN] /// Number format to parse a Golang float from string. #[rustfmt::skip] pub const GO_STRING: u128 = NumberFormatBuilder::new() .required_fraction_digits(true) .build(); const_assert!(NumberFormat::<{ GO_STRING }> {}.is_valid()); // HASKELL LITERAL [456MN] /// Number format for a Haskell literal floating-point number. #[rustfmt::skip] pub const HASKELL_LITERAL: u128 = NumberFormatBuilder::new() .required_digits(true) .no_positive_mantissa_sign(true) .no_special(true) .build(); const_assert!(NumberFormat::<{ HASKELL_LITERAL }> {}.is_valid()); // HASKELL STRING [45678MN] /// Number format to parse a Haskell float from string. #[rustfmt::skip] pub const HASKELL_STRING: u128 = NumberFormatBuilder::new() .required_digits(true) .no_positive_mantissa_sign(true) .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ HASKELL_STRING }> {}.is_valid()); // JAVASCRIPT LITERAL [01345678M] /// Number format for a Javascript literal floating-point number. #[rustfmt::skip] pub const JAVASCRIPT_LITERAL: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .no_float_leading_zeros(true) .build(); const_assert!(NumberFormat::<{ JAVASCRIPT_LITERAL }> {}.is_valid()); // JAVASCRIPT STRING [012345678MN] /// Number format to parse a Javascript float from string. #[rustfmt::skip] pub const JAVASCRIPT_STRING: u128 = NumberFormatBuilder::new() .required_exponent_digits(false) .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ JAVASCRIPT_STRING }> {}.is_valid()); // PERL LITERAL [0134569ABDEFGHIJKMN-_] /// Number format for a Perl literal floating-point number. #[rustfmt::skip] pub const PERL_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .no_special(true) .internal_digit_separator(true) .fraction_leading_digit_separator(true) .exponent_leading_digit_separator(true) .trailing_digit_separator(true) .consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ PERL_LITERAL }> {}.is_valid()); // PERL STRING [01234567MN] /// Number format to parse a Perl float from string. pub const PERL_STRING: u128 = PERMISSIVE; // PHP LITERAL [01345678MN] /// Number format for a PHP literal floating-point number. #[rustfmt::skip] pub const PHP_LITERAL: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ PHP_LITERAL }> {}.is_valid()); // PHP STRING [0123456MN] /// Number format to parse a PHP float from string. #[rustfmt::skip] pub const PHP_STRING: u128 = NumberFormatBuilder::new() .required_exponent_digits(false) .no_special(true) .build(); const_assert!(NumberFormat::<{ PHP_STRING }> {}.is_valid()); // JAVA LITERAL [0134569ABIJKMN-_] /// Number format for a Java literal floating-point number. #[rustfmt::skip] pub const JAVA_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .no_special(true) .internal_digit_separator(true) .consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ JAVA_LITERAL }> {}.is_valid()); // JAVA STRING [01345678MN] /// Number format to parse a Java float from string. #[rustfmt::skip] pub const JAVA_STRING: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ JAVA_STRING }> {}.is_valid()); // R LITERAL [01345678MN] /// Number format for a R literal floating-point number. #[rustfmt::skip] pub const R_LITERAL: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ R_LITERAL }> {}.is_valid()); // R STRING [01234567MN] /// Number format to parse a R float from string. pub const R_STRING: u128 = PERMISSIVE; // KOTLIN LITERAL [0134569ABIJKN-_] /// Number format for a Kotlin literal floating-point number. #[rustfmt::skip] pub const KOTLIN_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .no_special(true) .no_integer_leading_zeros(true) .internal_digit_separator(true) .consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ KOTLIN_LITERAL }> {}.is_valid()); // KOTLIN STRING [0134568MN] /// Number format to parse a Kotlin float from string. #[rustfmt::skip] pub const KOTLIN_STRING: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ KOTLIN_STRING }> {}.is_valid()); // JULIA LITERAL [01345689AMN-_] /// Number format for a Julia literal floating-point number. #[rustfmt::skip] pub const JULIA_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .case_sensitive_special(true) .integer_internal_digit_separator(true) .fraction_internal_digit_separator(true) .build(); const_assert!(NumberFormat::<{ JULIA_LITERAL }> {}.is_valid()); // JULIA STRING [01345678MN] /// Number format to parse a Julia float from string. #[rustfmt::skip] pub const JULIA_STRING: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ JULIA_STRING }> {}.is_valid()); // JULIA HEX LITERAL [01345689AMN-_] /// Number format for a Julia literal floating-point number. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const JULIA_HEX_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .mantissa_radix(16) .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .case_sensitive_special(true) .integer_internal_digit_separator(true) .fraction_internal_digit_separator(true) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ JULIA_HEX_LITERAL }> {}.is_valid()); // JULIA HEX STRING [01345678MN] /// Number format to parse a Julia float from string. #[rustfmt::skip] #[cfg(feature = "power-of-two")] pub const JULIA_HEX_STRING: u128 = NumberFormatBuilder::new() .mantissa_radix(16) .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .build(); #[cfg(feature = "power-of-two")] const_assert!(NumberFormat::<{ JULIA_HEX_STRING }> {}.is_valid()); /// Number format for a C# literal floating-point number. pub const CSHARP_LITERAL: u128 = CSHARP7_LITERAL; /// Number format to parse a C# float from string. pub const CSHARP_STRING: u128 = CSHARP7_STRING; // CSHARP7 LITERAL [034569ABIJKMN-_] /// Number format for a C#7 literal floating-point number. #[rustfmt::skip] pub const CSHARP7_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .required_fraction_digits(true) .no_special(true) .internal_digit_separator(true) .consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ CSHARP7_LITERAL }> {}.is_valid()); // CSHARP7 STRING [0134568MN] /// Number format to parse a C#7 float from string. #[rustfmt::skip] pub const CSHARP7_STRING: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ CSHARP7_STRING }> {}.is_valid()); // CSHARP6 LITERAL [03456MN] /// Number format for a C#6 literal floating-point number. #[rustfmt::skip] pub const CSHARP6_LITERAL: u128 = NumberFormatBuilder::new() .required_fraction_digits(true) .no_special(true) .build(); const_assert!(NumberFormat::<{ CSHARP6_LITERAL }> {}.is_valid()); // CSHARP6 STRING [0134568MN] /// Number format to parse a C#6 float from string. #[rustfmt::skip] pub const CSHARP6_STRING: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ CSHARP6_STRING }> {}.is_valid()); // CSHARP5 LITERAL [03456MN] /// Number format for a C#5 literal floating-point number. #[rustfmt::skip] pub const CSHARP5_LITERAL: u128 = NumberFormatBuilder::new() .required_fraction_digits(true) .no_special(true) .build(); const_assert!(NumberFormat::<{ CSHARP5_LITERAL }> {}.is_valid()); // CSHARP5 STRING [0134568MN] /// Number format to parse a C#5 float from string. #[rustfmt::skip] pub const CSHARP5_STRING: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ CSHARP5_STRING }> {}.is_valid()); // CSHARP4 LITERAL [03456MN] /// Number format for a C#4 literal floating-point number. #[rustfmt::skip] pub const CSHARP4_LITERAL: u128 = NumberFormatBuilder::new() .required_fraction_digits(true) .no_special(true) .build(); const_assert!(NumberFormat::<{ CSHARP4_LITERAL }> {}.is_valid()); // CSHARP4 STRING [0134568MN] /// Number format to parse a C#4 float from string. #[rustfmt::skip] pub const CSHARP4_STRING: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ CSHARP4_STRING }> {}.is_valid()); // CSHARP3 LITERAL [03456MN] /// Number format for a C#3 literal floating-point number. #[rustfmt::skip] pub const CSHARP3_LITERAL: u128 = NumberFormatBuilder::new() .required_fraction_digits(true) .no_special(true) .build(); const_assert!(NumberFormat::<{ CSHARP3_LITERAL }> {}.is_valid()); // CSHARP3 STRING [0134568MN] /// Number format to parse a C#3 float from string. #[rustfmt::skip] pub const CSHARP3_STRING: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ CSHARP3_STRING }> {}.is_valid()); // CSHARP2 LITERAL [03456MN] /// Number format for a C#2 literal floating-point number. #[rustfmt::skip] pub const CSHARP2_LITERAL: u128 = NumberFormatBuilder::new() .required_fraction_digits(true) .no_special(true) .build(); const_assert!(NumberFormat::<{ CSHARP2_LITERAL }> {}.is_valid()); // CSHARP2 STRING [0134568MN] /// Number format to parse a C#2 float from string. #[rustfmt::skip] pub const CSHARP2_STRING: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ CSHARP2_STRING }> {}.is_valid()); // CSHARP1 LITERAL [03456MN] /// Number format for a C#1 literal floating-point number. #[rustfmt::skip] pub const CSHARP1_LITERAL: u128 = NumberFormatBuilder::new() .required_fraction_digits(true) .no_special(true) .build(); const_assert!(NumberFormat::<{ CSHARP1_LITERAL }> {}.is_valid()); // CSHARP1 STRING [0134568MN] /// Number format to parse a C#1 float from string. #[rustfmt::skip] pub const CSHARP1_STRING: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ CSHARP1_STRING }> {}.is_valid()); // KAWA LITERAL [013456MN] /// Number format for a Kawa literal floating-point number. #[rustfmt::skip] pub const KAWA_LITERAL: u128 = NumberFormatBuilder::new() .no_special(true) .build(); const_assert!(NumberFormat::<{ KAWA_LITERAL }> {}.is_valid()); // KAWA STRING [013456MN] /// Number format to parse a Kawa float from string. #[rustfmt::skip] pub const KAWA_STRING: u128 = NumberFormatBuilder::new() .no_special(true) .build(); const_assert!(NumberFormat::<{ KAWA_STRING }> {}.is_valid()); // GAMBITC LITERAL [013456MN] /// Number format for a Gambit-C literal floating-point number. #[rustfmt::skip] pub const GAMBITC_LITERAL: u128 = NumberFormatBuilder::new() .no_special(true) .build(); const_assert!(NumberFormat::<{ GAMBITC_LITERAL }> {}.is_valid()); // GAMBITC STRING [013456MN] /// Number format to parse a Gambit-C float from string. #[rustfmt::skip] pub const GAMBITC_STRING: u128 = NumberFormatBuilder::new() .no_special(true) .build(); const_assert!(NumberFormat::<{ GAMBITC_STRING }> {}.is_valid()); // GUILE LITERAL [013456MN] /// Number format for a Guile literal floating-point number. #[rustfmt::skip] pub const GUILE_LITERAL: u128 = NumberFormatBuilder::new() .no_special(true) .build(); const_assert!(NumberFormat::<{ GUILE_LITERAL }> {}.is_valid()); // GUILE STRING [013456MN] /// Number format to parse a Guile float from string. #[rustfmt::skip] pub const GUILE_STRING: u128 = NumberFormatBuilder::new() .no_special(true) .build(); const_assert!(NumberFormat::<{ GUILE_STRING }> {}.is_valid()); // CLOJURE LITERAL [13456MN] /// Number format for a Clojure literal floating-point number. #[rustfmt::skip] pub const CLOJURE_LITERAL: u128 = NumberFormatBuilder::new() .required_integer_digits(true) .no_special(true) .build(); const_assert!(NumberFormat::<{ CLOJURE_LITERAL }> {}.is_valid()); // CLOJURE STRING [01345678MN] /// Number format to parse a Clojure float from string. #[rustfmt::skip] pub const CLOJURE_STRING: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ CLOJURE_STRING }> {}.is_valid()); // ERLANG LITERAL [34578MN] /// Number format for an Erlang literal floating-point number. #[rustfmt::skip] pub const ERLANG_LITERAL: u128 = NumberFormatBuilder::new() .required_digits(true) .no_exponent_without_fraction(true) .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ ERLANG_LITERAL }> {}.is_valid()); // ERLANG STRING [345MN] /// Number format to parse an Erlang float from string. #[rustfmt::skip] pub const ERLANG_STRING: u128 = NumberFormatBuilder::new() .required_digits(true) .no_exponent_without_fraction(true) .no_special(true) .build(); const_assert!(NumberFormat::<{ ERLANG_STRING }> {}.is_valid()); // ELM LITERAL [456] /// Number format for an Elm literal floating-point number. #[rustfmt::skip] pub const ELM_LITERAL: u128 = NumberFormatBuilder::new() .required_digits(true) .no_positive_mantissa_sign(true) .no_integer_leading_zeros(true) .no_float_leading_zeros(true) .no_special(true) .build(); const_assert!(NumberFormat::<{ ELM_LITERAL }> {}.is_valid()); // ELM STRING [01345678MN] // Note: There is no valid representation of NaN, just Infinity. /// Number format to parse an Elm float from string. #[rustfmt::skip] pub const ELM_STRING: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ ELM_STRING }> {}.is_valid()); // SCALA LITERAL [3456] /// Number format for a Scala literal floating-point number. #[rustfmt::skip] pub const SCALA_LITERAL: u128 = NumberFormatBuilder::new() .required_digits(true) .no_special(true) .no_integer_leading_zeros(true) .no_float_leading_zeros(true) .build(); const_assert!(NumberFormat::<{ SCALA_LITERAL }> {}.is_valid()); // SCALA STRING [01345678MN] /// Number format to parse a Scala float from string. #[rustfmt::skip] pub const SCALA_STRING: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ SCALA_STRING }> {}.is_valid()); // ELIXIR LITERAL [3459ABMN-_] /// Number format for an Elixir literal floating-point number. #[rustfmt::skip] pub const ELIXIR_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .required_digits(true) .no_exponent_without_fraction(true) .no_special(true) .internal_digit_separator(true) .build(); const_assert!(NumberFormat::<{ ELIXIR_LITERAL }> {}.is_valid()); // ELIXIR STRING [345MN] /// Number format to parse an Elixir float from string. #[rustfmt::skip] pub const ELIXIR_STRING: u128 = NumberFormatBuilder::new() .required_digits(true) .no_exponent_without_fraction(true) .no_special(true) .build(); const_assert!(NumberFormat::<{ ELIXIR_STRING }> {}.is_valid()); // FORTRAN LITERAL [013456MN] /// Number format for a FORTRAN literal floating-point number. #[rustfmt::skip] pub const FORTRAN_LITERAL: u128 = NumberFormatBuilder::new() .no_special(true) .build(); const_assert!(NumberFormat::<{ FORTRAN_LITERAL }> {}.is_valid()); // FORTRAN STRING [0134567MN] /// Number format to parse a FORTRAN float from string. #[rustfmt::skip] pub const FORTRAN_STRING: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ FORTRAN_STRING }> {}.is_valid()); // D LITERAL [0134569ABFGHIJKN-_] /// Number format for a D literal floating-point number. #[rustfmt::skip] pub const D_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .no_special(true) .no_integer_leading_zeros(true) .internal_digit_separator(true) .trailing_digit_separator(true) .consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ D_LITERAL }> {}.is_valid()); // D STRING [01345679AFGMN-_] /// Number format to parse a D float from string. #[rustfmt::skip] pub const D_STRING: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .integer_internal_digit_separator(true) .fraction_internal_digit_separator(true) .integer_trailing_digit_separator(true) .fraction_trailing_digit_separator(true) .build(); const_assert!(NumberFormat::<{ D_STRING }> {}.is_valid()); // COFFEESCRIPT LITERAL [01345678] /// Number format for a Coffeescript literal floating-point number. #[rustfmt::skip] pub const COFFEESCRIPT_LITERAL: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .no_integer_leading_zeros(true) .no_float_leading_zeros(true) .build(); const_assert!(NumberFormat::<{ COFFEESCRIPT_LITERAL }> {}.is_valid()); // COFFEESCRIPT STRING [012345678MN] /// Number format to parse a Coffeescript float from string. #[rustfmt::skip] pub const COFFEESCRIPT_STRING: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ COFFEESCRIPT_STRING }> {}.is_valid()); // COBOL LITERAL [0345MN] /// Number format for a Cobol literal floating-point number. #[rustfmt::skip] pub const COBOL_LITERAL: u128 = NumberFormatBuilder::new() .required_fraction_digits(true) .no_exponent_without_fraction(true) .no_special(true) .build(); const_assert!(NumberFormat::<{ COBOL_LITERAL }> {}.is_valid()); // COBOL STRING [012356MN] /// Number format to parse a Cobol float from string. #[rustfmt::skip] pub const COBOL_STRING: u128 = NumberFormatBuilder::new() .required_exponent_sign(true) .no_special(true) .build(); const_assert!(NumberFormat::<{ COBOL_STRING }> {}.is_valid()); // FSHARP LITERAL [13456789ABIJKMN-_] /// Number format for a F# literal floating-point number. #[rustfmt::skip] pub const FSHARP_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .required_integer_digits(true) .required_exponent_digits(true) .case_sensitive_special(true) .internal_digit_separator(true) .consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ FSHARP_LITERAL }> {}.is_valid()); // FSHARP STRING [013456789ABCDEFGHIJKLMN-_] /// Number format to parse a F# float from string. #[rustfmt::skip] pub const FSHARP_STRING: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .internal_digit_separator(true) .leading_digit_separator(true) .trailing_digit_separator(true) .consecutive_digit_separator(true) .special_digit_separator(true) .build(); const_assert!(NumberFormat::<{ FSHARP_STRING }> {}.is_valid()); // VB LITERAL [03456MN] /// Number format for a Visual Basic literal floating-point number. #[rustfmt::skip] pub const VB_LITERAL: u128 = NumberFormatBuilder::new() .required_fraction_digits(true) .no_special(true) .build(); const_assert!(NumberFormat::<{ VB_LITERAL }> {}.is_valid()); // VB STRING [01345678MN] /// Number format to parse a Visual Basic float from string. // Note: To my knowledge, Visual Basic cannot parse infinity. #[rustfmt::skip] pub const VB_STRING: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ VB_STRING }> {}.is_valid()); // OCAML LITERAL [1456789ABDFGHIJKMN-_] /// Number format for an OCaml literal floating-point number. #[rustfmt::skip] pub const OCAML_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .required_integer_digits(true) .required_exponent_digits(true) .no_positive_mantissa_sign(true) .case_sensitive_special(true) .internal_digit_separator(true) .fraction_leading_digit_separator(true) .trailing_digit_separator(true) .consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ OCAML_LITERAL }> {}.is_valid()); // OCAML STRING [01345679ABCDEFGHIJKLMN-_] /// Number format to parse an OCaml float from string. #[rustfmt::skip] pub const OCAML_STRING: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .internal_digit_separator(true) .leading_digit_separator(true) .trailing_digit_separator(true) .consecutive_digit_separator(true) .special_digit_separator(true) .build(); const_assert!(NumberFormat::<{ OCAML_STRING }> {}.is_valid()); // OBJECTIVEC LITERAL [013456MN] /// Number format for an Objective-C literal floating-point number. #[rustfmt::skip] pub const OBJECTIVEC_LITERAL: u128 = NumberFormatBuilder::new() .no_special(true) .build(); const_assert!(NumberFormat::<{ OBJECTIVEC_LITERAL }> {}.is_valid()); // OBJECTIVEC STRING [013456MN] /// Number format to parse an Objective-C float from string. #[rustfmt::skip] pub const OBJECTIVEC_STRING: u128 = NumberFormatBuilder::new() .no_special(true) .build(); const_assert!(NumberFormat::<{ OBJECTIVEC_STRING }> {}.is_valid()); // REASONML LITERAL [13456789ABDFGHIJKMN-_] /// Number format for a ReasonML literal floating-point number. #[rustfmt::skip] pub const REASONML_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .required_integer_digits(true) .required_exponent_digits(true) .case_sensitive_special(true) .internal_digit_separator(true) .fraction_leading_digit_separator(true) .trailing_digit_separator(true) .consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ REASONML_LITERAL }> {}.is_valid()); // REASONML STRING [01345679ABCDEFGHIJKLMN-_] /// Number format to parse a ReasonML float from string. #[rustfmt::skip] pub const REASONML_STRING: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .internal_digit_separator(true) .leading_digit_separator(true) .trailing_digit_separator(true) .consecutive_digit_separator(true) .special_digit_separator(true) .build(); const_assert!(NumberFormat::<{ REASONML_STRING }> {}.is_valid()); // OCTAVE LITERAL [013456789ABDFGHIJKMN-_] // Note: Octave accepts both NaN and nan, Inf and inf. /// Number format for an Octave literal floating-point number. #[rustfmt::skip] pub const OCTAVE_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .case_sensitive_special(true) .internal_digit_separator(true) .fraction_leading_digit_separator(true) .trailing_digit_separator(true) .consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ OCTAVE_LITERAL }> {}.is_valid()); // OCTAVE STRING [01345679ABCDEFGHIJKMN-,] /// Number format to parse an Octave float from string. #[rustfmt::skip] pub const OCTAVE_STRING: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b',')) .internal_digit_separator(true) .leading_digit_separator(true) .trailing_digit_separator(true) .consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ OCTAVE_STRING }> {}.is_valid()); // MATLAB LITERAL [013456789ABDFGHIJKMN-_] // Note: Matlab accepts both NaN and nan, Inf and inf. /// Number format for an Matlab literal floating-point number. #[rustfmt::skip] pub const MATLAB_LITERAL: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .case_sensitive_special(true) .internal_digit_separator(true) .fraction_leading_digit_separator(true) .trailing_digit_separator(true) .consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ MATLAB_LITERAL }> {}.is_valid()); // MATLAB STRING [01345679ABCDEFGHIJKMN-,] /// Number format to parse an Matlab float from string. #[rustfmt::skip] pub const MATLAB_STRING: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b',')) .internal_digit_separator(true) .leading_digit_separator(true) .trailing_digit_separator(true) .consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ MATLAB_STRING }> {}.is_valid()); // ZIG LITERAL [1456MN] /// Number format for a Zig literal floating-point number. #[rustfmt::skip] pub const ZIG_LITERAL: u128 = NumberFormatBuilder::new() .required_integer_digits(true) .no_positive_mantissa_sign(true) .no_special(true) .build(); const_assert!(NumberFormat::<{ ZIG_LITERAL }> {}.is_valid()); // ZIG STRING [01234567MN] /// Number format to parse a Zig float from string. pub const ZIG_STRING: u128 = PERMISSIVE; // SAGE LITERAL [012345678MN] // Note: Both Infinity and infinity are accepted. /// Number format for a Sage literal floating-point number. #[rustfmt::skip] pub const SAGE_LITERAL: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ SAGE_LITERAL }> {}.is_valid()); // SAGE STRING [01345679ABMN-_] /// Number format to parse a Sage float from string. #[rustfmt::skip] pub const SAGE_STRING: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .internal_digit_separator(true) .build(); const_assert!(NumberFormat::<{ SAGE_STRING }> {}.is_valid()); // JSON [456] /// Number format for a JSON literal floating-point number. #[rustfmt::skip] pub const JSON: u128 = NumberFormatBuilder::new() .required_digits(true) .no_positive_mantissa_sign(true) .no_special(true) .no_integer_leading_zeros(true) .no_float_leading_zeros(true) .build(); const_assert!(NumberFormat::<{ JSON }> {}.is_valid()); // TOML [34569AB] /// Number format for a TOML literal floating-point number. #[rustfmt::skip] pub const TOML: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .required_digits(false) .no_special(true) .no_integer_leading_zeros(true) .no_float_leading_zeros(true) .internal_digit_separator(true) .build(); const_assert!(NumberFormat::<{ TOML }> {}.is_valid()); // YAML (defined in-terms of JSON schema). /// Number format for a YAML literal floating-point number. pub const YAML: u128 = JSON; // XML [01234578MN] /// Number format for a XML literal floating-point number. #[rustfmt::skip] pub const XML: u128 = NumberFormatBuilder::new() .required_exponent_digits(false) .case_sensitive_special(true) .build(); const_assert!(NumberFormat::<{ XML }> {}.is_valid()); // SQLITE [013456MN] /// Number format for a SQLite literal floating-point number. #[rustfmt::skip] pub const SQLITE: u128 = NumberFormatBuilder::new() .no_special(true) .build(); const_assert!(NumberFormat::<{ SQLITE }> {}.is_valid()); // POSTGRESQL [013456MN] /// Number format for a PostgreSQL literal floating-point number. #[rustfmt::skip] pub const POSTGRESQL: u128 = NumberFormatBuilder::new() .no_special(true) .build(); const_assert!(NumberFormat::<{ POSTGRESQL }> {}.is_valid()); // MYSQL [013456MN] /// Number format for a MySQL literal floating-point number. #[rustfmt::skip] pub const MYSQL: u128 = NumberFormatBuilder::new() .no_special(true) .build(); const_assert!(NumberFormat::<{ MYSQL }> {}.is_valid()); // MONGODB [01345678M] /// Number format for a MongoDB literal floating-point number. #[rustfmt::skip] pub const MONGODB: u128 = NumberFormatBuilder::new() .case_sensitive_special(true) .no_float_leading_zeros(true) .build(); const_assert!(NumberFormat::<{ MONGODB }> {}.is_valid()); // HIDDEN DEFAULTS AND INTERFACES /// Number format when no flags are set. #[doc(hidden)] #[rustfmt::skip] pub const PERMISSIVE: u128 = NumberFormatBuilder::new() .required_exponent_digits(false) .required_mantissa_digits(false) .build(); const_assert!(NumberFormat::<{ PERMISSIVE }> {}.is_valid()); /// Number format when all digit separator flags are set. #[doc(hidden)] #[rustfmt::skip] pub const IGNORE: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .digit_separator_flags(true) .required_exponent_digits(false) .required_mantissa_digits(false) .build(); const_assert!(NumberFormat::<{ IGNORE }> {}.is_valid()); lexical-util-0.8.5/src/format.rs000064400000000000000000000472370072674642500147240ustar 00000000000000//! Public API for the number format packed struct. //! //! This has a consistent API whether or not the `format` feature is //! enabled, however, most functionality will be disabled if the feature //! is not enabled. //! //! # Pre-Defined Formats //! //! These are the pre-defined formats for parsing numbers from various //! programming, markup, and data languages. //! //! - [STANDARD](crate::format::STANDARD) #![cfg_attr(feature = "format", doc = " - [RUST_LITERAL](crate::format::RUST_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [RUST_STRING](crate::format::RUST_STRING)")] #![cfg_attr(feature = "format", doc = " - [PYTHON_LITERAL](crate::format::PYTHON_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [PYTHON_STRING](crate::format::PYTHON_STRING)")] #![cfg_attr(feature = "format", doc = " - [PYTHON3_LITERAL](crate::format::PYTHON3_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [PYTHON3_STRING](crate::format::PYTHON3_STRING)")] #![cfg_attr(feature = "format", doc = " - [PYTHON36_LITERAL](crate::format::PYTHON36_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [PYTHON35_LITERAL](crate::format::PYTHON35_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [PYTHON2_LITERAL](crate::format::PYTHON2_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [PYTHON2_STRING](crate::format::PYTHON2_STRING)")] #![cfg_attr(feature = "format", doc = " - [CXX_LITERAL](crate::format::CXX_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [CXX_STRING](crate::format::CXX_STRING)")] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [CXX_HEX_LITERAL](crate::format::CXX_HEX_LITERAL)" )] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [CXX_HEX_STRING](crate::format::CXX_HEX_STRING)" )] #![cfg_attr(feature = "format", doc = " - [CXX20_LITERAL](crate::format::CXX20_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [CXX20_STRING](crate::format::CXX20_STRING)")] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [CXX20_HEX_LITERAL](crate::format::CXX20_HEX_LITERAL)" )] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [CXX20_HEX_STRING](crate::format::CXX20_HEX_STRING)" )] #![cfg_attr(feature = "format", doc = " - [CXX17_LITERAL](crate::format::CXX17_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [CXX17_STRING](crate::format::CXX17_STRING)")] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [CXX17_HEX_LITERAL](crate::format::CXX17_HEX_LITERAL)" )] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [CXX17_HEX_STRING](crate::format::CXX17_HEX_STRING)" )] #![cfg_attr(feature = "format", doc = " - [CXX14_LITERAL](crate::format::CXX14_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [CXX14_STRING](crate::format::CXX14_STRING)")] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [CXX14_HEX_STRING](crate::format::CXX14_HEX_STRING)" )] #![cfg_attr(feature = "format", doc = " - [CXX11_LITERAL](crate::format::CXX11_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [CXX11_STRING](crate::format::CXX11_STRING)")] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [CXX11_HEX_STRING](crate::format::CXX11_HEX_STRING)" )] #![cfg_attr(feature = "format", doc = " - [CXX03_LITERAL](crate::format::CXX03_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [CXX03_STRING](crate::format::CXX03_STRING)")] #![cfg_attr(feature = "format", doc = " - [CXX98_LITERAL](crate::format::CXX98_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [CXX98_STRING](crate::format::CXX98_STRING)")] #![cfg_attr(feature = "format", doc = " - [C_LITERAL](crate::format::C_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [C_STRING](crate::format::C_STRING)")] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [C_HEX_LITERAL](crate::format::C_HEX_LITERAL)" )] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [C_HEX_STRING](crate::format::C_HEX_STRING)" )] #![cfg_attr(feature = "format", doc = " - [C18_LITERAL](crate::format::C18_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [C18_STRING](crate::format::C18_STRING)")] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [C18_HEX_LITERAL](crate::format::C18_HEX_LITERAL)" )] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [C18_HEX_STRING](crate::format::C18_HEX_STRING)" )] #![cfg_attr(feature = "format", doc = " - [C11_LITERAL](crate::format::C11_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [C11_STRING](crate::format::C11_STRING)")] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [C11_HEX_LITERAL](crate::format::C11_HEX_LITERAL)" )] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [C11_HEX_STRING](crate::format::C11_HEX_STRING)" )] #![cfg_attr(feature = "format", doc = " - [C99_LITERAL](crate::format::C99_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [C99_STRING](crate::format::C99_STRING)")] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [C99_HEX_LITERAL](crate::format::C99_HEX_LITERAL)" )] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [C99_HEX_STRING](crate::format::C99_HEX_STRING)" )] #![cfg_attr(feature = "format", doc = " - [C90_LITERAL](crate::format::C90_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [C90_STRING](crate::format::C90_STRING)")] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [C90_HEX_STRING](crate::format::C90_HEX_STRING)" )] #![cfg_attr(feature = "format", doc = " - [C89_LITERAL](crate::format::C89_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [C89_STRING](crate::format::C89_STRING)")] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [C89_HEX_STRING](crate::format::C89_HEX_STRING)" )] #![cfg_attr(feature = "format", doc = " - [RUBY_LITERAL](crate::format::RUBY_LITERAL)")] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [RUBY_OCTAL_LITERAL](crate::format::RUBY_OCTAL_LITERAL)" )] #![cfg_attr(feature = "format", doc = " - [RUBY_STRING](crate::format::RUBY_STRING)")] #![cfg_attr(feature = "format", doc = " - [SWIFT_LITERAL](crate::format::SWIFT_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [SWIFT_STRING](crate::format::SWIFT_STRING)")] #![cfg_attr(feature = "format", doc = " - [GO_LITERAL](crate::format::GO_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [GO_STRING](crate::format::GO_STRING)")] #![cfg_attr(feature = "format", doc = " - [HASKELL_LITERAL](crate::format::HASKELL_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [HASKELL_STRING](crate::format::HASKELL_STRING)")] #![cfg_attr(feature = "format", doc = " - [JAVASCRIPT_LITERAL](crate::format::JAVASCRIPT_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [JAVASCRIPT_STRING](crate::format::JAVASCRIPT_STRING)")] #![cfg_attr(feature = "format", doc = " - [PERL_LITERAL](crate::format::PERL_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [PERL_STRING](crate::format::PERL_STRING)")] #![cfg_attr(feature = "format", doc = " - [PHP_LITERAL](crate::format::PHP_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [PHP_STRING](crate::format::PHP_STRING)")] #![cfg_attr(feature = "format", doc = " - [JAVA_LITERAL](crate::format::JAVA_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [JAVA_STRING](crate::format::JAVA_STRING)")] #![cfg_attr(feature = "format", doc = " - [R_LITERAL](crate::format::R_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [R_STRING](crate::format::R_STRING)")] #![cfg_attr(feature = "format", doc = " - [KOTLIN_LITERAL](crate::format::KOTLIN_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [KOTLIN_STRING](crate::format::KOTLIN_STRING)")] #![cfg_attr(feature = "format", doc = " - [JULIA_LITERAL](crate::format::JULIA_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [JULIA_STRING](crate::format::JULIA_STRING)")] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [JULIA_HEX_LITERAL](crate::format::JULIA_HEX_LITERAL)" )] #![cfg_attr( all(feature = "format", feature = "power-of-two"), doc = " - [JULIA_HEX_STRING](crate::format::JULIA_HEX_STRING)" )] #![cfg_attr(feature = "format", doc = " - [CSHARP_LITERAL](crate::format::CSHARP_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [CSHARP_STRING](crate::format::CSHARP_STRING)")] #![cfg_attr(feature = "format", doc = " - [CSHARP7_LITERAL](crate::format::CSHARP7_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [CSHARP7_STRING](crate::format::CSHARP7_STRING)")] #![cfg_attr(feature = "format", doc = " - [CSHARP6_LITERAL](crate::format::CSHARP6_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [CSHARP6_STRING](crate::format::CSHARP6_STRING)")] #![cfg_attr(feature = "format", doc = " - [CSHARP5_LITERAL](crate::format::CSHARP5_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [CSHARP5_STRING](crate::format::CSHARP5_STRING)")] #![cfg_attr(feature = "format", doc = " - [CSHARP4_LITERAL](crate::format::CSHARP4_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [CSHARP4_STRING](crate::format::CSHARP4_STRING)")] #![cfg_attr(feature = "format", doc = " - [CSHARP3_LITERAL](crate::format::CSHARP3_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [CSHARP3_STRING](crate::format::CSHARP3_STRING)")] #![cfg_attr(feature = "format", doc = " - [CSHARP2_LITERAL](crate::format::CSHARP2_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [CSHARP2_STRING](crate::format::CSHARP2_STRING)")] #![cfg_attr(feature = "format", doc = " - [CSHARP1_LITERAL](crate::format::CSHARP1_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [CSHARP1_STRING](crate::format::CSHARP1_STRING)")] #![cfg_attr(feature = "format", doc = " - [KAWA_LITERAL](crate::format::KAWA_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [KAWA_STRING](crate::format::KAWA_STRING)")] #![cfg_attr(feature = "format", doc = " - [GAMBITC_LITERAL](crate::format::GAMBITC_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [GAMBITC_STRING](crate::format::GAMBITC_STRING)")] #![cfg_attr(feature = "format", doc = " - [GUILE_LITERAL](crate::format::GUILE_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [GUILE_STRING](crate::format::GUILE_STRING)")] #![cfg_attr(feature = "format", doc = " - [CLOJURE_LITERAL](crate::format::CLOJURE_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [CLOJURE_STRING](crate::format::CLOJURE_STRING)")] #![cfg_attr(feature = "format", doc = " - [ERLANG_LITERAL](crate::format::ERLANG_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [ERLANG_STRING](crate::format::ERLANG_STRING)")] #![cfg_attr(feature = "format", doc = " - [ELM_LITERAL](crate::format::ELM_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [ELM_STRING](crate::format::ELM_STRING)")] #![cfg_attr(feature = "format", doc = " - [SCALA_LITERAL](crate::format::SCALA_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [SCALA_STRING](crate::format::SCALA_STRING)")] #![cfg_attr(feature = "format", doc = " - [ELIXIR_LITERAL](crate::format::ELIXIR_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [ELIXIR_STRING](crate::format::ELIXIR_STRING)")] #![cfg_attr(feature = "format", doc = " - [FORTRAN_LITERAL](crate::format::FORTRAN_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [FORTRAN_STRING](crate::format::FORTRAN_STRING)")] #![cfg_attr(feature = "format", doc = " - [D_LITERAL](crate::format::D_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [D_STRING](crate::format::D_STRING)")] #![cfg_attr( feature = "format", doc = " - [COFFEESCRIPT_LITERAL](crate::format::COFFEESCRIPT_LITERAL)" )] #![cfg_attr( feature = "format", doc = " - [COFFEESCRIPT_STRING](crate::format::COFFEESCRIPT_STRING)" )] #![cfg_attr(feature = "format", doc = " - [COBOL_LITERAL](crate::format::COBOL_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [COBOL_STRING](crate::format::COBOL_STRING)")] #![cfg_attr(feature = "format", doc = " - [FSHARP_LITERAL](crate::format::FSHARP_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [FSHARP_STRING](crate::format::FSHARP_STRING)")] #![cfg_attr(feature = "format", doc = " - [VB_LITERAL](crate::format::VB_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [VB_STRING](crate::format::VB_STRING)")] #![cfg_attr(feature = "format", doc = " - [OCAML_LITERAL](crate::format::OCAML_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [OCAML_STRING](crate::format::OCAML_STRING)")] #![cfg_attr(feature = "format", doc = " - [OBJECTIVEC_LITERAL](crate::format::OBJECTIVEC_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [OBJECTIVEC_STRING](crate::format::OBJECTIVEC_STRING)")] #![cfg_attr(feature = "format", doc = " - [REASONML_LITERAL](crate::format::REASONML_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [REASONML_STRING](crate::format::REASONML_STRING)")] #![cfg_attr(feature = "format", doc = " - [OCTAVE_LITERAL](crate::format::OCTAVE_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [OCTAVE_STRING](crate::format::OCTAVE_STRING)")] #![cfg_attr(feature = "format", doc = " - [MATLAB_LITERAL](crate::format::MATLAB_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [MATLAB_STRING](crate::format::MATLAB_STRING)")] #![cfg_attr(feature = "format", doc = " - [ZIG_LITERAL](crate::format::ZIG_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [ZIG_STRING](crate::format::ZIG_STRING)")] #![cfg_attr(feature = "format", doc = " - [SAGE_LITERAL](crate::format::SAGE_LITERAL)")] #![cfg_attr(feature = "format", doc = " - [SAGE_STRING](crate::format::SAGE_STRING)")] #![cfg_attr(feature = "format", doc = " - [JSON](crate::format::JSON)")] #![cfg_attr(feature = "format", doc = " - [TOML](crate::format::TOML)")] #![cfg_attr(feature = "format", doc = " - [YAML](crate::format::YAML)")] #![cfg_attr(feature = "format", doc = " - [XML](crate::format::XML)")] #![cfg_attr(feature = "format", doc = " - [SQLITE](crate::format::SQLITE)")] #![cfg_attr(feature = "format", doc = " - [POSTGRESQL](crate::format::POSTGRESQL)")] #![cfg_attr(feature = "format", doc = " - [MYSQL](crate::format::MYSQL)")] #![cfg_attr(feature = "format", doc = " - [MONGODB](crate::format::MONGODB)")] //! //! # Syntax Flags //! //! Bitflags to get and set syntax flags for the format packed struct. //! //! - [REQUIRED_INTEGER_DIGITS](crate::format::REQUIRED_INTEGER_DIGITS) //! - [REQUIRED_FRACTION_DIGITS](crate::format::REQUIRED_FRACTION_DIGITS) //! - [REQUIRED_EXPONENT_DIGITS](crate::format::REQUIRED_EXPONENT_DIGITS) //! - [REQUIRED_MANTISSA_DIGITS](crate::format::REQUIRED_MANTISSA_DIGITS) //! - [REQUIRED_DIGITS](crate::format::REQUIRED_DIGITS) //! - [NO_POSITIVE_MANTISSA_SIGN](crate::format::NO_POSITIVE_MANTISSA_SIGN) //! - [REQUIRED_MANTISSA_SIGN](crate::format::REQUIRED_MANTISSA_SIGN) //! - [NO_EXPONENT_NOTATION](crate::format::NO_EXPONENT_NOTATION) //! - [NO_POSITIVE_EXPONENT_SIGN](crate::format::NO_POSITIVE_EXPONENT_SIGN) //! - [REQUIRED_EXPONENT_SIGN](crate::format::REQUIRED_EXPONENT_SIGN) //! - [NO_EXPONENT_WITHOUT_FRACTION](crate::format::NO_EXPONENT_WITHOUT_FRACTION) //! - [NO_SPECIAL](crate::format::NO_SPECIAL) //! - [CASE_SENSITIVE_SPECIAL](crate::format::CASE_SENSITIVE_SPECIAL) //! - [NO_INTEGER_LEADING_ZEROS](crate::format::NO_INTEGER_LEADING_ZEROS) //! - [NO_FLOAT_LEADING_ZEROS](crate::format::NO_FLOAT_LEADING_ZEROS) //! - [REQUIRED_EXPONENT_NOTATION](crate::format::REQUIRED_EXPONENT_NOTATION) //! - [CASE_SENSITIVE_EXPONENT](crate::format::CASE_SENSITIVE_EXPONENT) //! - [CASE_SENSITIVE_BASE_PREFIX](crate::format::CASE_SENSITIVE_BASE_PREFIX) //! - [CASE_SENSITIVE_BASE_SUFFIX](crate::format::CASE_SENSITIVE_BASE_SUFFIX) //! //! # Digit Separator Flags //! //! Bitflags to get and set digit separators flags for the format //! packed struct. //! //! - [INTEGER_INTERNAL_DIGIT_SEPARATOR](crate::format::INTEGER_INTERNAL_DIGIT_SEPARATOR) //! - [FRACTION_INTERNAL_DIGIT_SEPARATOR](crate::format::FRACTION_INTERNAL_DIGIT_SEPARATOR) //! - [EXPONENT_INTERNAL_DIGIT_SEPARATOR](crate::format::EXPONENT_INTERNAL_DIGIT_SEPARATOR) //! - [INTEGER_LEADING_DIGIT_SEPARATOR](crate::format::INTEGER_LEADING_DIGIT_SEPARATOR) //! - [FRACTION_LEADING_DIGIT_SEPARATOR](crate::format::FRACTION_LEADING_DIGIT_SEPARATOR) //! - [EXPONENT_LEADING_DIGIT_SEPARATOR](crate::format::EXPONENT_LEADING_DIGIT_SEPARATOR) //! - [INTEGER_TRAILING_DIGIT_SEPARATOR](crate::format::INTEGER_TRAILING_DIGIT_SEPARATOR) //! - [FRACTION_TRAILING_DIGIT_SEPARATOR](crate::format::FRACTION_TRAILING_DIGIT_SEPARATOR) //! - [EXPONENT_TRAILING_DIGIT_SEPARATOR](crate::format::EXPONENT_TRAILING_DIGIT_SEPARATOR) //! - [INTEGER_CONSECUTIVE_DIGIT_SEPARATOR](crate::format::INTEGER_CONSECUTIVE_DIGIT_SEPARATOR) //! - [FRACTION_CONSECUTIVE_DIGIT_SEPARATOR](crate::format::FRACTION_CONSECUTIVE_DIGIT_SEPARATOR) //! - [EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR](crate::format::EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR) //! - [INTERNAL_DIGIT_SEPARATOR](crate::format::INTERNAL_DIGIT_SEPARATOR) //! - [LEADING_DIGIT_SEPARATOR](crate::format::LEADING_DIGIT_SEPARATOR) //! - [TRAILING_DIGIT_SEPARATOR](crate::format::TRAILING_DIGIT_SEPARATOR) //! - [CONSECUTIVE_DIGIT_SEPARATOR](crate::format::CONSECUTIVE_DIGIT_SEPARATOR) //! - [SPECIAL_DIGIT_SEPARATOR](crate::format::SPECIAL_DIGIT_SEPARATOR) //! //! # Character Shifts and Masks //! //! Bitmasks and bitshifts to get and set control characters for the format //! packed struct. //! //! - [DIGIT_SEPARATOR_SHIFT](crate::format::DIGIT_SEPARATOR_SHIFT) //! - [DIGIT_SEPARATOR](crate::format::DIGIT_SEPARATOR) //! - [BASE_PREFIX_SHIFT](crate::format::BASE_PREFIX_SHIFT) //! - [BASE_PREFIX](crate::format::BASE_PREFIX) //! - [BASE_SUFFIX_SHIFT](crate::format::BASE_SUFFIX_SHIFT) //! - [BASE_SUFFIX](crate::format::BASE_SUFFIX) //! - [MANTISSA_RADIX_SHIFT](crate::format::MANTISSA_RADIX_SHIFT) //! - [MANTISSA_RADIX](crate::format::MANTISSA_RADIX) //! - [RADIX_SHIFT](crate::format::RADIX_SHIFT) //! - [RADIX](crate::format::RADIX) //! - [EXPONENT_BASE_SHIFT](crate::format::EXPONENT_BASE_SHIFT) //! - [EXPONENT_BASE](crate::format::EXPONENT_BASE) //! - [EXPONENT_RADIX_SHIFT](crate::format::EXPONENT_RADIX_SHIFT) //! - [EXPONENT_RADIX](crate::format::EXPONENT_RADIX) //! //! # Character Functions //! //! Functions to get control characters from the format packed struct. //! //! - [digit_separator](crate::format::digit_separator) //! - [base_prefix](crate::format::base_prefix) //! - [base_suffix](crate::format::base_suffix) //! - [mantissa_radix](crate::format::mantissa_radix) //! - [exponent_base](crate::format::exponent_base) //! - [exponent_radix](crate::format::exponent_radix) //! - [radix_from_flags](crate::format::radix_from_flags) //! //! # Validators //! //! Functions to validate control characters for the format packed struct. //! //! - [is_valid_digit_separator](is_valid_digit_separator) //! - [is_valid_base_prefix](is_valid_base_prefix) //! - [is_valid_base_suffix](is_valid_base_suffix) //! - [is_valid_punctuation](is_valid_punctuation) //! - [is_valid_radix](is_valid_radix) #[cfg(feature = "format")] pub use crate::feature_format::*; pub use crate::format_builder::*; pub use crate::format_flags::*; #[cfg(not(feature = "format"))] pub use crate::not_feature_format::*; use crate::error::Error; use static_assertions::const_assert; /// Determine if the format packed struct is valid. #[inline] pub const fn format_is_valid() -> bool { NumberFormat:: {}.is_valid() } /// Get the error type from the format packed struct. /// /// An error type of `Error::Success` means the format is valid, any /// other error signifies an invalid format. #[inline] pub const fn format_error() -> Error { NumberFormat:: {}.error() } /// Standard number format. This is identical to the Rust string format. pub const STANDARD: u128 = NumberFormatBuilder::new().build(); const_assert!(NumberFormat::<{ STANDARD }> {}.is_valid()); lexical-util-0.8.5/src/format_builder.rs000064400000000000000000001144200072674642500164170ustar 00000000000000//! Builder for the number format. use crate::format_flags as flags; use core::{mem, num}; use static_assertions::const_assert; /// Type with the exact same size as a `u8`. pub type OptionU8 = Option; // Ensure the sizes are identical. const_assert!(mem::size_of::() == mem::size_of::()); /// Add single flag to SyntaxFormat. macro_rules! add_flag { ($format:ident, $bool:expr, $flag:ident) => { if $bool { $format |= flags::$flag; } }; } /// Add multiple flags to SyntaxFormat. macro_rules! add_flags { ($format:ident ; $($bool:expr, $flag:ident ;)*) => {{ $(add_flag!($format, $bool, $flag);)* }}; } /// Determine if a flag is set in the format. macro_rules! has_flag { ($format:ident, $flag:ident) => { $format & flags::$flag != 0 }; } /// Unwrap `Option` as a const fn. #[inline(always)] const fn unwrap_or_zero(option: OptionU8) -> u8 { match option { Some(x) => x.get(), None => 0, } } /// Build number format from specifications. /// /// Returns the format on calling build if it was able to compile the format, /// otherwise, returns None. /// /// # Fields /// /// * `digit_separator` - Character to separate digits. /// * `mantissa_radix` - Radix for mantissa digits. /// * `exponent_base` - Base for the exponent. /// * `exponent_radix` - Radix for the exponent digits. /// * `base_prefix` - Optional character for the base prefix. /// * `base_suffix` - Optional character for the base suffix. /// * `required_integer_digits` - If digits are required before the decimal point. /// * `required_fraction_digits` - If digits are required after the decimal point. /// * `required_exponent_digits` - If digits are required after the exponent character. /// * `required_mantissa_digits` - If at least 1 significant digit is required. /// * `no_positive_mantissa_sign` - If positive sign before the mantissa is not allowed. /// * `required_mantissa_sign` - If positive sign before the mantissa is required. /// * `no_exponent_notation` - If exponent notation is not allowed. /// * `no_positive_exponent_sign` - If positive sign before the exponent is not allowed. /// * `required_exponent_sign` - If sign before the exponent is required. /// * `no_exponent_without_fraction` - If exponent without fraction is not allowed. /// * `no_special` - If special (non-finite) values are not allowed. /// * `case_sensitive_special` - If special (non-finite) values are case-sensitive. /// * `no_integer_leading_zeros` - If leading zeros before an integer are not allowed. /// * `no_float_leading_zeros` - If leading zeros before a float are not allowed. /// * `required_exponent_notation` - If exponent notation is required. /// * `case_sensitive_exponent` - If exponent characters are case-sensitive. /// * `case_sensitive_base_prefix` - If base prefixes are case-sensitive. /// * `case_sensitive_base_suffix` - If base suffixes are case-sensitive. /// * `integer_internal_digit_separator` - If digit separators are allowed between integer digits. /// * `fraction_internal_digit_separator` - If digit separators are allowed between fraction digits. /// * `exponent_internal_digit_separator` - If digit separators are allowed between exponent digits. /// * `integer_leading_digit_separator` - If a digit separator is allowed before any integer digits. /// * `fraction_leading_digit_separator` - If a digit separator is allowed before any fraction digits. /// * `exponent_leading_digit_separator` - If a digit separator is allowed before any exponent digits. /// * `integer_trailing_digit_separator` - If a digit separator is allowed after any integer digits. /// * `fraction_trailing_digit_separator` - If a digit separator is allowed after any fraction digits. /// * `exponent_trailing_digit_separator` - If a digit separator is allowed after any exponent digits. /// * `integer_consecutive_digit_separator` - If multiple consecutive integer digit separators are allowed. /// * `fraction_consecutive_digit_separator` - If multiple consecutive fraction digit separators are allowed. /// * `special_digit_separator` - If any digit separators are allowed in special (non-finite) values. /// /// # Write Integer Fields /// /// No fields are used for writing integers. /// /// # Parse Integer Fields /// /// These fields are used for parsing integers: /// /// * `digit_separator` /// * `mantissa_radix` /// * `base_prefix` /// * `base_suffix` /// * `no_positive_mantissa_sign` /// * `required_mantissa_sign` /// * `no_integer_leading_zeros` /// * `integer_internal_digit_separator` /// * `integer_leading_digit_separator` /// * `integer_trailing_digit_separator` /// * `integer_consecutive_digit_separator` /// /// # Write Float Fields /// /// These fields are used for writing floats: /// /// * `mantissa_radix` /// * `exponent_base` /// * `exponent_radix` /// * `no_positive_mantissa_sign` /// * `required_mantissa_sign` /// * `no_exponent_notation` /// * `no_positive_exponent_sign` /// * `required_exponent_sign` /// * `required_exponent_notation` /// /// # Parse Float Fields /// /// These fields are used for parsing floats: /// /// * `digit_separator` /// * `mantissa_radix` /// * `exponent_base` /// * `exponent_radix` /// * `base_prefix` /// * `base_suffix` /// * `required_integer_digits` /// * `required_fraction_digits` /// * `required_exponent_digits` /// * `no_positive_mantissa_sign` /// * `required_mantissa_sign` /// * `no_exponent_notation` /// * `no_positive_exponent_sign` /// * `required_exponent_sign` /// * `no_exponent_without_fraction` /// * `no_special` /// * `case_sensitive_special` /// * `no_integer_leading_zeros` /// * `no_float_leading_zeros` /// * `required_exponent_notation` /// * `case_sensitive_exponent` /// * `case_sensitive_base_prefix` /// * `case_sensitive_base_suffix` /// * `integer_internal_digit_separator` /// * `fraction_internal_digit_separator` /// * `exponent_internal_digit_separator` /// * `integer_leading_digit_separator` /// * `fraction_leading_digit_separator` /// * `exponent_leading_digit_separator` /// * `integer_trailing_digit_separator` /// * `fraction_trailing_digit_separator` /// * `exponent_trailing_digit_separator` /// * `integer_consecutive_digit_separator` /// * `fraction_consecutive_digit_separator` /// * `special_digit_separator` pub struct NumberFormatBuilder { digit_separator: OptionU8, base_prefix: OptionU8, base_suffix: OptionU8, mantissa_radix: u8, exponent_base: OptionU8, exponent_radix: OptionU8, required_integer_digits: bool, required_fraction_digits: bool, required_exponent_digits: bool, required_mantissa_digits: bool, no_positive_mantissa_sign: bool, required_mantissa_sign: bool, no_exponent_notation: bool, no_positive_exponent_sign: bool, required_exponent_sign: bool, no_exponent_without_fraction: bool, no_special: bool, case_sensitive_special: bool, no_integer_leading_zeros: bool, no_float_leading_zeros: bool, required_exponent_notation: bool, case_sensitive_exponent: bool, case_sensitive_base_prefix: bool, case_sensitive_base_suffix: bool, integer_internal_digit_separator: bool, fraction_internal_digit_separator: bool, exponent_internal_digit_separator: bool, integer_leading_digit_separator: bool, fraction_leading_digit_separator: bool, exponent_leading_digit_separator: bool, integer_trailing_digit_separator: bool, fraction_trailing_digit_separator: bool, exponent_trailing_digit_separator: bool, integer_consecutive_digit_separator: bool, fraction_consecutive_digit_separator: bool, exponent_consecutive_digit_separator: bool, special_digit_separator: bool, } impl NumberFormatBuilder { // CONSTRUCTORS /// Create new NumberFormatBuilder with default arguments. #[inline(always)] pub const fn new() -> Self { Self { digit_separator: None, base_prefix: None, base_suffix: None, mantissa_radix: 10, exponent_base: None, exponent_radix: None, required_integer_digits: false, required_fraction_digits: false, required_exponent_digits: true, required_mantissa_digits: true, no_positive_mantissa_sign: false, required_mantissa_sign: false, no_exponent_notation: false, no_positive_exponent_sign: false, required_exponent_sign: false, no_exponent_without_fraction: false, no_special: false, case_sensitive_special: false, no_integer_leading_zeros: false, no_float_leading_zeros: false, required_exponent_notation: false, case_sensitive_exponent: false, case_sensitive_base_prefix: false, case_sensitive_base_suffix: false, integer_internal_digit_separator: false, fraction_internal_digit_separator: false, exponent_internal_digit_separator: false, integer_leading_digit_separator: false, fraction_leading_digit_separator: false, exponent_leading_digit_separator: false, integer_trailing_digit_separator: false, fraction_trailing_digit_separator: false, exponent_trailing_digit_separator: false, integer_consecutive_digit_separator: false, fraction_consecutive_digit_separator: false, exponent_consecutive_digit_separator: false, special_digit_separator: false, } } /// Create number format for standard, binary number. #[cfg(feature = "power-of-two")] pub const fn binary() -> u128 { Self::from_radix(2) } /// Create number format for standard, octal number. #[cfg(feature = "power-of-two")] pub const fn octal() -> u128 { Self::from_radix(8) } /// Create number format for standard, decimal number. pub const fn decimal() -> u128 { let mut builder = Self::new(); builder.mantissa_radix = 10; builder.exponent_base = num::NonZeroU8::new(10); builder.exponent_radix = num::NonZeroU8::new(10); builder.build() } /// Create number format for standard, hexadecimal number. #[cfg(feature = "power-of-two")] pub const fn hexadecimal() -> u128 { Self::from_radix(16) } /// Create number format from radix. #[cfg(feature = "power-of-two")] pub const fn from_radix(radix: u8) -> u128 { Self::new() .radix(radix) .exponent_base(num::NonZeroU8::new(radix)) .exponent_radix(num::NonZeroU8::new(radix)) .build() } // GETTERS /// Get the digit separator for the number format. #[inline(always)] pub const fn get_digit_separator(&self) -> OptionU8 { self.digit_separator } /// Get the radix for mantissa digits. #[inline(always)] pub const fn get_mantissa_radix(&self) -> u8 { self.mantissa_radix } /// Get the radix for the exponent. #[inline(always)] pub const fn get_exponent_base(&self) -> OptionU8 { self.exponent_base } /// Get the radix for exponent digits. #[inline(always)] pub const fn get_exponent_radix(&self) -> OptionU8 { self.exponent_radix } /// Get the optional character for the base prefix. #[inline(always)] pub const fn get_base_prefix(&self) -> OptionU8 { self.base_prefix } /// Get the optional character for the base suffix. #[inline(always)] pub const fn get_base_suffix(&self) -> OptionU8 { self.base_suffix } /// Get if digits are required before the decimal point. #[inline(always)] pub const fn get_required_integer_digits(&self) -> bool { self.required_integer_digits } /// Get if digits are required after the decimal point. #[inline(always)] pub const fn get_required_fraction_digits(&self) -> bool { self.required_fraction_digits } /// Get if digits are required after the exponent character. #[inline(always)] pub const fn get_required_exponent_digits(&self) -> bool { self.required_exponent_digits } /// Get if at least 1 significant digit is required. #[inline(always)] pub const fn get_required_mantissa_digits(&self) -> bool { self.required_mantissa_digits } /// Get if a positive sign before the mantissa is not allowed. #[inline(always)] pub const fn get_no_positive_mantissa_sign(&self) -> bool { self.no_positive_mantissa_sign } /// Get if a sign symbol before the mantissa is required. #[inline(always)] pub const fn get_required_mantissa_sign(&self) -> bool { self.required_mantissa_sign } /// Get if exponent notation is not allowed. #[inline(always)] pub const fn get_no_exponent_notation(&self) -> bool { self.no_exponent_notation } /// Get if a positive sign before the exponent is not allowed. #[inline(always)] pub const fn get_no_positive_exponent_sign(&self) -> bool { self.no_positive_exponent_sign } /// Get if a sign symbol before the exponent is required. #[inline(always)] pub const fn get_required_exponent_sign(&self) -> bool { self.required_exponent_sign } /// Get if an exponent without fraction is not allowed. #[inline(always)] pub const fn get_no_exponent_without_fraction(&self) -> bool { self.no_exponent_without_fraction } /// Get if special (non-finite) values are not allowed. #[inline(always)] pub const fn get_no_special(&self) -> bool { self.no_special } /// Get if special (non-finite) values are case-sensitive. #[inline(always)] pub const fn get_case_sensitive_special(&self) -> bool { self.case_sensitive_special } /// Get if leading zeros before an integer are not allowed. #[inline(always)] pub const fn get_no_integer_leading_zeros(&self) -> bool { self.no_integer_leading_zeros } /// Get if leading zeros before a float are not allowed. #[inline(always)] pub const fn get_no_float_leading_zeros(&self) -> bool { self.no_float_leading_zeros } /// Get if exponent notation is required. #[inline(always)] pub const fn get_required_exponent_notation(&self) -> bool { self.required_exponent_notation } /// Get if exponent characters are case-sensitive. #[inline(always)] pub const fn get_case_sensitive_exponent(&self) -> bool { self.case_sensitive_exponent } /// Get if base prefixes are case-sensitive. #[inline(always)] pub const fn get_case_sensitive_base_prefix(&self) -> bool { self.case_sensitive_base_prefix } /// Get if base suffixes are case-sensitive. #[inline(always)] pub const fn get_case_sensitive_base_suffix(&self) -> bool { self.case_sensitive_base_suffix } /// Get if digit separators are allowed between integer digits. #[inline(always)] pub const fn get_integer_internal_digit_separator(&self) -> bool { self.integer_internal_digit_separator } /// Get if digit separators are allowed between fraction digits. #[inline(always)] pub const fn get_fraction_internal_digit_separator(&self) -> bool { self.fraction_internal_digit_separator } /// Get if digit separators are allowed between exponent digits. #[inline(always)] pub const fn get_exponent_internal_digit_separator(&self) -> bool { self.exponent_internal_digit_separator } /// Get if a digit separator is allowed before any integer digits. #[inline(always)] pub const fn get_integer_leading_digit_separator(&self) -> bool { self.integer_leading_digit_separator } /// Get if a digit separator is allowed before any fraction digits. #[inline(always)] pub const fn get_fraction_leading_digit_separator(&self) -> bool { self.fraction_leading_digit_separator } /// Get if a digit separator is allowed before any exponent digits. #[inline(always)] pub const fn get_exponent_leading_digit_separator(&self) -> bool { self.exponent_leading_digit_separator } /// Get if a digit separator is allowed after any integer digits. #[inline(always)] pub const fn get_integer_trailing_digit_separator(&self) -> bool { self.integer_trailing_digit_separator } /// Get if a digit separator is allowed after any fraction digits. #[inline(always)] pub const fn get_fraction_trailing_digit_separator(&self) -> bool { self.fraction_trailing_digit_separator } /// Get if a digit separator is allowed after any exponent digits. #[inline(always)] pub const fn get_exponent_trailing_digit_separator(&self) -> bool { self.exponent_trailing_digit_separator } /// Get if multiple consecutive integer digit separators are allowed. #[inline(always)] pub const fn get_integer_consecutive_digit_separator(&self) -> bool { self.integer_consecutive_digit_separator } /// Get if multiple consecutive fraction digit separators are allowed. #[inline(always)] pub const fn get_fraction_consecutive_digit_separator(&self) -> bool { self.fraction_consecutive_digit_separator } /// Get if multiple consecutive exponent digit separators are allowed. #[inline(always)] pub const fn get_exponent_consecutive_digit_separator(&self) -> bool { self.exponent_consecutive_digit_separator } /// Get if any digit separators are allowed in special (non-finite) values. #[inline(always)] pub const fn get_special_digit_separator(&self) -> bool { self.special_digit_separator } // SETTERS /// Set the digit separator for the number format. #[inline(always)] #[cfg(feature = "format")] pub const fn digit_separator(mut self, character: OptionU8) -> Self { self.digit_separator = character; self } /// Alias for mantissa radix. #[inline(always)] #[cfg(feature = "power-of-two")] pub const fn radix(self, radix: u8) -> Self { self.mantissa_radix(radix) } /// Set the radix for mantissa digits. #[inline(always)] #[cfg(feature = "power-of-two")] pub const fn mantissa_radix(mut self, radix: u8) -> Self { self.mantissa_radix = radix; self } /// Set the radix for the exponent. #[inline(always)] #[cfg(feature = "power-of-two")] pub const fn exponent_base(mut self, base: OptionU8) -> Self { self.exponent_base = base; self } /// Set the radix for exponent digits. #[inline(always)] #[cfg(feature = "power-of-two")] pub const fn exponent_radix(mut self, radix: OptionU8) -> Self { self.exponent_radix = radix; self } /// Set the optional character for the base prefix. #[inline(always)] #[cfg(all(feature = "power-of-two", feature = "format"))] pub const fn base_prefix(mut self, base_prefix: OptionU8) -> Self { self.base_prefix = base_prefix; self } /// Set the optional character for the base suffix. #[inline(always)] #[cfg(all(feature = "power-of-two", feature = "format"))] pub const fn base_suffix(mut self, base_suffix: OptionU8) -> Self { self.base_suffix = base_suffix; self } /// Set if digits are required before the decimal point. #[inline(always)] #[cfg(feature = "format")] pub const fn required_integer_digits(mut self, flag: bool) -> Self { self.required_integer_digits = flag; self } /// Set if digits are required after the decimal point. #[inline(always)] #[cfg(feature = "format")] pub const fn required_fraction_digits(mut self, flag: bool) -> Self { self.required_fraction_digits = flag; self } /// Set if digits are required after the exponent character. #[inline(always)] #[cfg(feature = "format")] pub const fn required_exponent_digits(mut self, flag: bool) -> Self { self.required_exponent_digits = flag; self } /// Set if at least 1 significant digit is required. #[inline(always)] #[cfg(feature = "format")] pub const fn required_mantissa_digits(mut self, flag: bool) -> Self { self.required_mantissa_digits = flag; self } /// Set if digits are required for all float components. #[inline(always)] #[cfg(feature = "format")] pub const fn required_digits(mut self, flag: bool) -> Self { self = self.required_integer_digits(flag); self = self.required_fraction_digits(flag); self = self.required_exponent_digits(flag); self = self.required_mantissa_digits(flag); self } /// Set if a positive sign before the mantissa is not allowed. #[inline(always)] #[cfg(feature = "format")] pub const fn no_positive_mantissa_sign(mut self, flag: bool) -> Self { self.no_positive_mantissa_sign = flag; self } /// Set if a sign symbol before the mantissa is required. #[inline(always)] #[cfg(feature = "format")] pub const fn required_mantissa_sign(mut self, flag: bool) -> Self { self.required_mantissa_sign = flag; self } /// Set if exponent notation is not allowed. #[inline(always)] #[cfg(feature = "format")] pub const fn no_exponent_notation(mut self, flag: bool) -> Self { self.no_exponent_notation = flag; self } /// Set if a positive sign before the exponent is not allowed. #[inline(always)] #[cfg(feature = "format")] pub const fn no_positive_exponent_sign(mut self, flag: bool) -> Self { self.no_positive_exponent_sign = flag; self } /// Set if a sign symbol before the exponent is required. #[inline(always)] #[cfg(feature = "format")] pub const fn required_exponent_sign(mut self, flag: bool) -> Self { self.required_exponent_sign = flag; self } /// Set if an exponent without fraction is not allowed. #[inline(always)] #[cfg(feature = "format")] pub const fn no_exponent_without_fraction(mut self, flag: bool) -> Self { self.no_exponent_without_fraction = flag; self } /// Set if special (non-finite) values are not allowed. #[inline(always)] #[cfg(feature = "format")] pub const fn no_special(mut self, flag: bool) -> Self { self.no_special = flag; self } /// Set if special (non-finite) values are case-sensitive. #[inline(always)] #[cfg(feature = "format")] pub const fn case_sensitive_special(mut self, flag: bool) -> Self { self.case_sensitive_special = flag; self } /// Set if leading zeros before an integer are not allowed. #[inline(always)] #[cfg(feature = "format")] pub const fn no_integer_leading_zeros(mut self, flag: bool) -> Self { self.no_integer_leading_zeros = flag; self } /// Set if leading zeros before a float are not allowed. #[inline(always)] #[cfg(feature = "format")] pub const fn no_float_leading_zeros(mut self, flag: bool) -> Self { self.no_float_leading_zeros = flag; self } /// Set if exponent notation is required. #[inline(always)] #[cfg(feature = "format")] pub const fn required_exponent_notation(mut self, flag: bool) -> Self { self.required_exponent_notation = flag; self } /// Set if exponent characters are case-sensitive. #[inline(always)] #[cfg(feature = "format")] pub const fn case_sensitive_exponent(mut self, flag: bool) -> Self { self.case_sensitive_exponent = flag; self } /// Set if base prefixes are case-sensitive. #[inline(always)] #[cfg(all(feature = "power-of-two", feature = "format"))] pub const fn case_sensitive_base_prefix(mut self, flag: bool) -> Self { self.case_sensitive_base_prefix = flag; self } /// Set if base suffixes are case-sensitive. #[inline(always)] #[cfg(all(feature = "power-of-two", feature = "format"))] pub const fn case_sensitive_base_suffix(mut self, flag: bool) -> Self { self.case_sensitive_base_suffix = flag; self } /// Set if digit separators are allowed between integer digits. #[inline(always)] #[cfg(feature = "format")] pub const fn integer_internal_digit_separator(mut self, flag: bool) -> Self { self.integer_internal_digit_separator = flag; self } /// Set if digit separators are allowed between fraction digits. #[inline(always)] #[cfg(feature = "format")] pub const fn fraction_internal_digit_separator(mut self, flag: bool) -> Self { self.fraction_internal_digit_separator = flag; self } /// Set if digit separators are allowed between exponent digits. #[inline(always)] #[cfg(feature = "format")] pub const fn exponent_internal_digit_separator(mut self, flag: bool) -> Self { self.exponent_internal_digit_separator = flag; self } /// Set all internal digit separator flags. #[inline(always)] #[cfg(feature = "format")] pub const fn internal_digit_separator(mut self, flag: bool) -> Self { self = self.integer_internal_digit_separator(flag); self = self.fraction_internal_digit_separator(flag); self = self.exponent_internal_digit_separator(flag); self } /// Set if a digit separator is allowed before any integer digits. #[inline(always)] #[cfg(feature = "format")] pub const fn integer_leading_digit_separator(mut self, flag: bool) -> Self { self.integer_leading_digit_separator = flag; self } /// Set if a digit separator is allowed before any fraction digits. #[inline(always)] #[cfg(feature = "format")] pub const fn fraction_leading_digit_separator(mut self, flag: bool) -> Self { self.fraction_leading_digit_separator = flag; self } /// Set if a digit separator is allowed before any exponent digits. #[inline(always)] #[cfg(feature = "format")] pub const fn exponent_leading_digit_separator(mut self, flag: bool) -> Self { self.exponent_leading_digit_separator = flag; self } /// Set all leading digit separator flags. #[inline(always)] #[cfg(feature = "format")] pub const fn leading_digit_separator(mut self, flag: bool) -> Self { self = self.integer_leading_digit_separator(flag); self = self.fraction_leading_digit_separator(flag); self = self.exponent_leading_digit_separator(flag); self } /// Set if a digit separator is allowed after any integer digits. #[inline(always)] #[cfg(feature = "format")] pub const fn integer_trailing_digit_separator(mut self, flag: bool) -> Self { self.integer_trailing_digit_separator = flag; self } /// Set if a digit separator is allowed after any fraction digits. #[inline(always)] #[cfg(feature = "format")] pub const fn fraction_trailing_digit_separator(mut self, flag: bool) -> Self { self.fraction_trailing_digit_separator = flag; self } /// Set if a digit separator is allowed after any exponent digits. #[inline(always)] #[cfg(feature = "format")] pub const fn exponent_trailing_digit_separator(mut self, flag: bool) -> Self { self.exponent_trailing_digit_separator = flag; self } /// Set all trailing digit separator flags. #[inline(always)] #[cfg(feature = "format")] pub const fn trailing_digit_separator(mut self, flag: bool) -> Self { self = self.integer_trailing_digit_separator(flag); self = self.fraction_trailing_digit_separator(flag); self = self.exponent_trailing_digit_separator(flag); self } /// Set if multiple consecutive integer digit separators are allowed. #[inline(always)] #[cfg(feature = "format")] pub const fn integer_consecutive_digit_separator(mut self, flag: bool) -> Self { self.integer_consecutive_digit_separator = flag; self } /// Set if multiple consecutive fraction digit separators are allowed. #[inline(always)] #[cfg(feature = "format")] pub const fn fraction_consecutive_digit_separator(mut self, flag: bool) -> Self { self.fraction_consecutive_digit_separator = flag; self } /// Set if multiple consecutive exponent digit separators are allowed. #[inline(always)] #[cfg(feature = "format")] pub const fn exponent_consecutive_digit_separator(mut self, flag: bool) -> Self { self.exponent_consecutive_digit_separator = flag; self } /// Set all consecutive digit separator flags. #[inline(always)] #[cfg(feature = "format")] pub const fn consecutive_digit_separator(mut self, flag: bool) -> Self { self = self.integer_consecutive_digit_separator(flag); self = self.fraction_consecutive_digit_separator(flag); self = self.exponent_consecutive_digit_separator(flag); self } /// Set if any digit separators are allowed in special (non-finite) values. #[inline(always)] #[cfg(feature = "format")] pub const fn special_digit_separator(mut self, flag: bool) -> Self { self.special_digit_separator = flag; self } /// Set all digit separator flag masks. #[inline(always)] #[cfg(feature = "format")] pub const fn digit_separator_flags(mut self, flag: bool) -> Self { self = self.integer_digit_separator_flags(flag); self = self.fraction_digit_separator_flags(flag); self = self.exponent_digit_separator_flags(flag); self = self.special_digit_separator(flag); self } /// Set all integer digit separator flag masks. #[inline(always)] #[cfg(feature = "format")] pub const fn integer_digit_separator_flags(mut self, flag: bool) -> Self { self = self.integer_internal_digit_separator(flag); self = self.integer_leading_digit_separator(flag); self = self.integer_trailing_digit_separator(flag); self = self.integer_consecutive_digit_separator(flag); self } /// Set all fraction digit separator flag masks. #[inline(always)] #[cfg(feature = "format")] pub const fn fraction_digit_separator_flags(mut self, flag: bool) -> Self { self = self.fraction_internal_digit_separator(flag); self = self.fraction_leading_digit_separator(flag); self = self.fraction_trailing_digit_separator(flag); self = self.fraction_consecutive_digit_separator(flag); self } /// Set all exponent digit separator flag masks. #[inline(always)] #[cfg(feature = "format")] pub const fn exponent_digit_separator_flags(mut self, flag: bool) -> Self { self = self.exponent_internal_digit_separator(flag); self = self.exponent_leading_digit_separator(flag); self = self.exponent_trailing_digit_separator(flag); self = self.exponent_consecutive_digit_separator(flag); self } // BUILDER /// Create 128-bit, packed number format struct from builder options. /// /// NOTE: This function will never fail, due to issues with panicking /// (and therefore unwrapping Errors/Options) in const fns. It is /// therefore up to you to ensure the format is valid, called via the /// `is_valid` function on `NumberFormat`. #[inline] pub const fn build(&self) -> u128 { let mut format: u128 = 0; add_flags!( format ; self.required_integer_digits, REQUIRED_INTEGER_DIGITS ; self.required_fraction_digits, REQUIRED_FRACTION_DIGITS ; self.required_exponent_digits, REQUIRED_EXPONENT_DIGITS ; self.required_mantissa_digits, REQUIRED_MANTISSA_DIGITS ; self.no_positive_mantissa_sign, NO_POSITIVE_MANTISSA_SIGN ; self.required_mantissa_sign, REQUIRED_MANTISSA_SIGN ; self.no_exponent_notation, NO_EXPONENT_NOTATION ; self.no_positive_exponent_sign, NO_POSITIVE_EXPONENT_SIGN ; self.required_exponent_sign, REQUIRED_EXPONENT_SIGN ; self.no_exponent_without_fraction, NO_EXPONENT_WITHOUT_FRACTION ; self.no_special, NO_SPECIAL ; self.case_sensitive_special, CASE_SENSITIVE_SPECIAL ; self.no_integer_leading_zeros, NO_INTEGER_LEADING_ZEROS ; self.no_float_leading_zeros, NO_FLOAT_LEADING_ZEROS ; self.required_exponent_notation, REQUIRED_EXPONENT_NOTATION ; self.case_sensitive_exponent, CASE_SENSITIVE_EXPONENT ; self.case_sensitive_base_prefix, CASE_SENSITIVE_BASE_PREFIX ; self.case_sensitive_base_suffix, CASE_SENSITIVE_BASE_SUFFIX ; self.integer_internal_digit_separator, INTEGER_INTERNAL_DIGIT_SEPARATOR ; self.fraction_internal_digit_separator, FRACTION_INTERNAL_DIGIT_SEPARATOR ; self.exponent_internal_digit_separator, EXPONENT_INTERNAL_DIGIT_SEPARATOR ; self.integer_leading_digit_separator, INTEGER_LEADING_DIGIT_SEPARATOR ; self.fraction_leading_digit_separator, FRACTION_LEADING_DIGIT_SEPARATOR ; self.exponent_leading_digit_separator, EXPONENT_LEADING_DIGIT_SEPARATOR ; self.integer_trailing_digit_separator, INTEGER_TRAILING_DIGIT_SEPARATOR ; self.fraction_trailing_digit_separator, FRACTION_TRAILING_DIGIT_SEPARATOR ; self.exponent_trailing_digit_separator, EXPONENT_TRAILING_DIGIT_SEPARATOR ; self.integer_consecutive_digit_separator, INTEGER_CONSECUTIVE_DIGIT_SEPARATOR ; self.fraction_consecutive_digit_separator, FRACTION_CONSECUTIVE_DIGIT_SEPARATOR ; self.exponent_consecutive_digit_separator, EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR ; self.special_digit_separator, SPECIAL_DIGIT_SEPARATOR ; ); if format & flags::DIGIT_SEPARATOR_FLAG_MASK != 0 { format |= (unwrap_or_zero(self.digit_separator) as u128) << flags::DIGIT_SEPARATOR_SHIFT; } format |= (unwrap_or_zero(self.base_prefix) as u128) << flags::BASE_PREFIX_SHIFT; format |= (unwrap_or_zero(self.base_suffix) as u128) << flags::BASE_SUFFIX_SHIFT; format |= (self.mantissa_radix as u128) << flags::MANTISSA_RADIX_SHIFT; format |= (unwrap_or_zero(self.exponent_base) as u128) << flags::EXPONENT_BASE_SHIFT; format |= (unwrap_or_zero(self.exponent_radix) as u128) << flags::EXPONENT_RADIX_SHIFT; format } /// Re-create builder from format. #[inline] pub const fn rebuild(format: u128) -> Self { NumberFormatBuilder { digit_separator: num::NonZeroU8::new(flags::digit_separator(format)), base_prefix: num::NonZeroU8::new(flags::base_prefix(format)), base_suffix: num::NonZeroU8::new(flags::base_suffix(format)), mantissa_radix: flags::mantissa_radix(format) as u8, exponent_base: num::NonZeroU8::new(flags::exponent_base(format) as u8), exponent_radix: num::NonZeroU8::new(flags::exponent_radix(format) as u8), required_integer_digits: has_flag!(format, REQUIRED_INTEGER_DIGITS), required_fraction_digits: has_flag!(format, REQUIRED_FRACTION_DIGITS), required_exponent_digits: has_flag!(format, REQUIRED_EXPONENT_DIGITS), required_mantissa_digits: has_flag!(format, REQUIRED_MANTISSA_DIGITS), no_positive_mantissa_sign: has_flag!(format, NO_POSITIVE_MANTISSA_SIGN), required_mantissa_sign: has_flag!(format, REQUIRED_MANTISSA_SIGN), no_exponent_notation: has_flag!(format, NO_EXPONENT_NOTATION), no_positive_exponent_sign: has_flag!(format, NO_POSITIVE_EXPONENT_SIGN), required_exponent_sign: has_flag!(format, REQUIRED_EXPONENT_SIGN), no_exponent_without_fraction: has_flag!(format, NO_EXPONENT_WITHOUT_FRACTION), no_special: has_flag!(format, NO_SPECIAL), case_sensitive_special: has_flag!(format, CASE_SENSITIVE_SPECIAL), no_integer_leading_zeros: has_flag!(format, NO_INTEGER_LEADING_ZEROS), no_float_leading_zeros: has_flag!(format, NO_FLOAT_LEADING_ZEROS), required_exponent_notation: has_flag!(format, REQUIRED_EXPONENT_NOTATION), case_sensitive_exponent: has_flag!(format, CASE_SENSITIVE_EXPONENT), case_sensitive_base_prefix: has_flag!(format, CASE_SENSITIVE_BASE_PREFIX), case_sensitive_base_suffix: has_flag!(format, CASE_SENSITIVE_BASE_SUFFIX), integer_internal_digit_separator: has_flag!(format, INTEGER_INTERNAL_DIGIT_SEPARATOR), fraction_internal_digit_separator: has_flag!(format, FRACTION_INTERNAL_DIGIT_SEPARATOR), exponent_internal_digit_separator: has_flag!(format, EXPONENT_INTERNAL_DIGIT_SEPARATOR), integer_leading_digit_separator: has_flag!(format, INTEGER_LEADING_DIGIT_SEPARATOR), fraction_leading_digit_separator: has_flag!(format, FRACTION_LEADING_DIGIT_SEPARATOR), exponent_leading_digit_separator: has_flag!(format, EXPONENT_LEADING_DIGIT_SEPARATOR), integer_trailing_digit_separator: has_flag!(format, INTEGER_TRAILING_DIGIT_SEPARATOR), fraction_trailing_digit_separator: has_flag!(format, FRACTION_TRAILING_DIGIT_SEPARATOR), exponent_trailing_digit_separator: has_flag!(format, EXPONENT_TRAILING_DIGIT_SEPARATOR), integer_consecutive_digit_separator: has_flag!( format, INTEGER_CONSECUTIVE_DIGIT_SEPARATOR ), fraction_consecutive_digit_separator: has_flag!( format, FRACTION_CONSECUTIVE_DIGIT_SEPARATOR ), exponent_consecutive_digit_separator: has_flag!( format, EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR ), special_digit_separator: has_flag!(format, SPECIAL_DIGIT_SEPARATOR), } } } impl Default for NumberFormatBuilder { #[inline(always)] fn default() -> Self { Self::new() } } lexical-util-0.8.5/src/format_flags.rs000064400000000000000000000715020072674642500160700ustar 00000000000000//! Bitmask flags and masks for numeric formats. //! //! These bitflags and masks comprise a compressed struct as a 128-bit //! integer, allowing its use in const generics. This comprises two parts: //! flags designating which numerical components are valid in a string, //! and masks to designate the control characters. //! //! The flags are designated in the lower 64 bits that modify //! the syntax of strings that are parsed by lexical. //! //! Bits 8-32 are reserved for float component flags, such //! as for example if base prefixes or postfixes are case-sensitive, //! if leading zeros in a float are valid, etc. //! //! Bits 32-64 are reserved for digit separator flags. These //! define which locations within a float or integer digit separators //! are valid, for example, before any digits in the integer component, //! whether consecutive digit separators are allowed, and more. //! //! ```text //! 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! |I/R|F/R|E/R|M/R|+/M|R/M|e/e|+/E|R/E|e/F|S/S|S/C|N/I|N/F|R/e|e/C| //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! //! 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! |e/P|e/S| | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! //! 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! |I/I|F/I|E/I|I/L|F/L|E/L|I/T|F/T|E/T|I/C|F/C|E/C|S/D| | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! //! 48 49 50 51 52 53 54 55 56 57 58 59 60 62 62 63 64 //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! //! Where: //! Non-Digit Separator Flags: //! I/R = Required integer digits. //! F/R = Required fraction digits. //! E/R = Required exponent digits. //! M/R = Required mantissa digits. //! +/M = No mantissa positive sign. //! R/M = Required positive sign. //! e/e = No exponent notation. //! +/E = No exponent positive sign. //! R/E = Required exponent sign. //! e/F = No exponent without fraction. //! S/S = No special (non-finite) values. //! S/C = Case-sensitive special (non-finite) values. //! N/I = No integer leading zeros. //! N/F = No float leading zeros. //! R/e = Required exponent characters. //! e/C = Case-sensitive exponent character. //! e/P = Case-sensitive base prefix. //! e/S = Case-sensitive base suffix. //! //! Digit Separator Flags: //! I/I = Integer internal digit separator. //! F/I = Fraction internal digit separator. //! E/I = Exponent internal digit separator. //! I/L = Integer leading digit separator. //! F/L = Fraction leading digit separator. //! E/L = Exponent leading digit separator. //! I/T = Integer trailing digit separator. //! F/T = Fraction trailing digit separator. //! E/T = Exponent trailing digit separator. //! I/C = Integer consecutive digit separator. //! F/C = Fraction consecutive digit separator. //! E/C = Exponent consecutive digit separator. //! S/D = Special (non-finite) digit separator. //! ``` //! //! The upper 64-bits are designated for control characters and radixes, //! such as the digit separator and base prefix characters, radixes, //! and more. //! //! ```text //! 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! | Digit Separator | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! //! 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! | | Base Prefix | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! //! 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! | Base Suffix | | Mantissa Radix | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! //! 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! | Exponent Base | | Exponent Radix | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! ``` //! //! //! Note: //! ----- //! //! In order to limit the format specification and avoid parsing //! non-numerical data, all number formats require some significant //! digits. Examples of always invalid numbers include: //! - `` //! - `.` //! - `e` //! - `e7` //! //! Test Cases: //! ----------- //! //! The following test-cases are used to define whether a literal or //! a string float is valid in a given language, and these tests are //! used to denote features in pre-defined formats. Only a few //! of these flags may modify the parsing behavior of integers. //! Integer parsing is assumed to be derived from float parsing, //! so if consecutive digit separators are valid in the integer //! component of a float, they are also valid in an integer. //! //! ```text //! 0: '.3' // Non-required integer. //! 1: '3.' // Non-required fraction. //! 2: '3e' // Non-required exponent. //! 3. '+3.0' // Mantissa positive sign. //! 4: '3.0e7' // Exponent notation. //! 5: '3.0e+7' // Exponent positive sign. //! 6. '3e7' // Exponent notation without fraction. //! 7: 'NaN' // Special (non-finite) values. //! 8: 'NAN' // Case-sensitive special (non-finite) values. //! 9: '3_4.01' // Integer internal digit separator. //! A: '3.0_1' // Fraction internal digit separator. //! B: '3.0e7_1' // Exponent internal digit separator. //! C: '_3.01' // Integer leading digit separator. //! D: '3._01' // Fraction leading digit separator. //! E: '3.0e_71' // Exponent leading digit separator. //! F: '3_.01' // Integer trailing digit separator. //! G: '3.01_' // Fraction trailing digit separator. //! H: '3.0e71_' // Exponent trailing digit separator. //! I: '3__4.01' // Integer consecutive digit separator. //! J: '3.0__1' // Fraction consecutive digit separator. //! K: '3.0e7__1' // Exponent consecutive digit separator. //! L: 'In_f' // Special (non-finite) digit separator. //! M: '010' // No integer leading zeros. //! N: '010.0' // No float leading zeros. //! O: '1.0' // No required exponent notation. //! P: '3.0E7' // Case-insensitive exponent character. //! P: '0x3.0' // Case-insensitive base prefix. //! P: '3.0H' // Case-insensitive base postfix. //! ``` //! //! Currently Supported Programming and Data Languages: //! --------------------------------------------------- //! //! 1. Rust //! 2. Python //! 3. C++ (98, 03, 11, 14, 17) //! 4. C (89, 90, 99, 11, 18) //! 5. Ruby //! 6. Swift //! 7. Go //! 8. Haskell //! 9. Javascript //! 10. Perl //! 11. PHP //! 12. Java //! 13. R //! 14. Kotlin //! 15. Julia //! 16. C# (ISO-1, ISO-2, 3, 4, 5, 6, 7) //! 17. Kawa //! 18. Gambit-C //! 19. Guile //! 20. Clojure //! 21. Erlang //! 22. Elm //! 23. Scala //! 24. Elixir //! 25. FORTRAN //! 26. D //! 27. Coffeescript //! 28. Cobol //! 29. F# //! 30. Visual Basic //! 31. OCaml //! 32. Objective-C //! 33. ReasonML //! 34. Octave //! 35. Matlab //! 36. Zig //! 37. SageMath //! 38. JSON //! 39. TOML //! 40. XML //! 41. SQLite //! 42. PostgreSQL //! 43. MySQL //! 44. MongoDB #![cfg_attr(rustfmt, rustfmt::skip)] use static_assertions::const_assert; // ASSERTIONS // ---------- // Ensure all our bit flags are valid. macro_rules! check_subsequent_flags { ($x:ident, $y:ident) => { const_assert!($x << 1 == $y); }; } // Ensure all our bit masks don't overlap. macro_rules! check_subsequent_masks { ($x:ident, $y:ident) => { const_assert!($x & $y == 0); }; } // Check all our masks are in the range `[0, 255]` after shifting. macro_rules! check_mask_shifts { ($mask:ident, $shift:ident) => { const_assert!(0 < $mask >> $shift && 255 >= $mask >> $shift); }; } // Ensure all our bit masks don't overlap with existing flags. macro_rules! check_masks_and_flags { ($x:ident, $y:ident) => { const_assert!($x & $y == 0); }; } // NON-DIGIT SEPARATOR FLAGS & MASKS // --------------------------------- /// Digits are required before the decimal point. pub const REQUIRED_INTEGER_DIGITS: u128 = 1 << 0; /// Digits are required after the decimal point. /// This check will only occur if the decimal point is present. pub const REQUIRED_FRACTION_DIGITS: u128 = 1 << 1; /// Digits are required after the exponent character. /// This check will only occur if the exponent character is present. pub const REQUIRED_EXPONENT_DIGITS: u128 = 1 << 2; /// Mantissa digits are required (either before or after the decimal point). pub const REQUIRED_MANTISSA_DIGITS: u128 = 1 << 3; /// At least 1 digit in the number is required. pub const REQUIRED_DIGITS: u128 = REQUIRED_INTEGER_DIGITS | REQUIRED_FRACTION_DIGITS | REQUIRED_EXPONENT_DIGITS | REQUIRED_MANTISSA_DIGITS; /// Positive sign before the mantissa is not allowed. pub const NO_POSITIVE_MANTISSA_SIGN: u128 = 1 << 4; /// Positive sign before the mantissa is required. pub const REQUIRED_MANTISSA_SIGN: u128 = 1 << 5; /// Exponent notation is not allowed. pub const NO_EXPONENT_NOTATION: u128 = 1 << 6; /// Positive sign before the exponent is not allowed. pub const NO_POSITIVE_EXPONENT_SIGN: u128 = 1 << 7; /// Positive sign before the exponent is required. pub const REQUIRED_EXPONENT_SIGN: u128 = 1 << 8; /// Exponent without a fraction component is not allowed. /// /// This only checks if a decimal point precedes the exponent character. /// To require fraction digits or exponent digits with this check, /// please use the appropriate flags. pub const NO_EXPONENT_WITHOUT_FRACTION: u128 = 1 << 9; /// Special (non-finite) values are not allowed. pub const NO_SPECIAL: u128 = 1 << 10; /// Special (non-finite) values are case-sensitive. pub const CASE_SENSITIVE_SPECIAL: u128 = 1 << 11; /// Leading zeros before an integer value are not allowed. /// /// If the value is a literal, then this distinction applies /// when the value is treated like an integer literal, typically /// when there is no decimal point. If the value is parsed, /// then this distinction applies when the value as parsed /// as an integer. /// /// # Warning /// /// This also does not mean that the value parsed will be correct, /// for example, in languages like C, this will not auto- /// deduce that the radix is 8 with leading zeros, for an octal /// literal. pub const NO_INTEGER_LEADING_ZEROS: u128 = 1 << 12; /// Leading zeros before a float value are not allowed. /// /// If the value is a literal, then this distinction applies /// when the value is treated like an integer float, typically /// when there is a decimal point. If the value is parsed, /// then this distinction applies when the value as parsed /// as a float. /// /// # Warning /// /// This also does not mean that the value parsed will be correct, /// for example, in languages like C, this will not auto- /// deduce that the radix is 8 with leading zeros, for an octal /// literal. pub const NO_FLOAT_LEADING_ZEROS: u128 = 1 << 13; /// Exponent notation is required. /// /// Valid floats must contain an exponent notation character, and if /// applicable, a sign character and digits afterwards. pub const REQUIRED_EXPONENT_NOTATION: u128 = 1 << 14; /// Exponent characters are case-sensitive. pub const CASE_SENSITIVE_EXPONENT: u128 = 1 << 15; /// Base prefixes are case-sensitive. pub const CASE_SENSITIVE_BASE_PREFIX: u128 = 1 << 16; /// Base suffixes are case-sensitive. pub const CASE_SENSITIVE_BASE_SUFFIX: u128 = 1 << 17; // Non-digit separator flags. const_assert!(REQUIRED_INTEGER_DIGITS == 1); check_subsequent_flags!(REQUIRED_INTEGER_DIGITS, REQUIRED_FRACTION_DIGITS); check_subsequent_flags!(REQUIRED_FRACTION_DIGITS, REQUIRED_EXPONENT_DIGITS); check_subsequent_flags!(REQUIRED_EXPONENT_DIGITS, REQUIRED_MANTISSA_DIGITS); check_subsequent_flags!(REQUIRED_MANTISSA_DIGITS, NO_POSITIVE_MANTISSA_SIGN); check_subsequent_flags!(NO_POSITIVE_MANTISSA_SIGN, REQUIRED_MANTISSA_SIGN); check_subsequent_flags!(REQUIRED_MANTISSA_SIGN, NO_EXPONENT_NOTATION); check_subsequent_flags!(NO_EXPONENT_NOTATION, NO_POSITIVE_EXPONENT_SIGN); check_subsequent_flags!(NO_POSITIVE_EXPONENT_SIGN, REQUIRED_EXPONENT_SIGN); check_subsequent_flags!(REQUIRED_EXPONENT_SIGN, NO_EXPONENT_WITHOUT_FRACTION); check_subsequent_flags!(NO_EXPONENT_WITHOUT_FRACTION, NO_SPECIAL); check_subsequent_flags!(NO_SPECIAL, CASE_SENSITIVE_SPECIAL); check_subsequent_flags!(NO_SPECIAL, CASE_SENSITIVE_SPECIAL); check_subsequent_flags!(CASE_SENSITIVE_SPECIAL, NO_INTEGER_LEADING_ZEROS); check_subsequent_flags!(NO_INTEGER_LEADING_ZEROS, NO_FLOAT_LEADING_ZEROS); check_subsequent_flags!(NO_FLOAT_LEADING_ZEROS, REQUIRED_EXPONENT_NOTATION); check_subsequent_flags!(REQUIRED_EXPONENT_NOTATION, CASE_SENSITIVE_EXPONENT); check_subsequent_flags!(CASE_SENSITIVE_EXPONENT, CASE_SENSITIVE_BASE_PREFIX); check_subsequent_flags!(CASE_SENSITIVE_BASE_PREFIX, CASE_SENSITIVE_BASE_SUFFIX); // DIGIT SEPARATOR FLAGS & MASKS // ----------------------------- /// Digit separators are allowed between integer digits. pub const INTEGER_INTERNAL_DIGIT_SEPARATOR: u128 = 1 << 32; /// Digit separators are allowed between fraction digits. pub const FRACTION_INTERNAL_DIGIT_SEPARATOR: u128 = 1 << 33; /// Digit separators are allowed between exponent digits. pub const EXPONENT_INTERNAL_DIGIT_SEPARATOR: u128 = 1 << 34; /// A digit separator is allowed before any integer digits. pub const INTEGER_LEADING_DIGIT_SEPARATOR: u128 = 1 << 35; /// A digit separator is allowed before any fraction digits. pub const FRACTION_LEADING_DIGIT_SEPARATOR: u128 = 1 << 36; /// A digit separator is allowed before any exponent digits. pub const EXPONENT_LEADING_DIGIT_SEPARATOR: u128 = 1 << 37; /// A digit separator is allowed after any integer digits. pub const INTEGER_TRAILING_DIGIT_SEPARATOR: u128 = 1 << 38; /// A digit separator is allowed after any fraction digits. pub const FRACTION_TRAILING_DIGIT_SEPARATOR: u128 = 1 << 39; /// A digit separator is allowed after any exponent digits. pub const EXPONENT_TRAILING_DIGIT_SEPARATOR: u128 = 1 << 40; /// Multiple consecutive integer digit separators are allowed. pub const INTEGER_CONSECUTIVE_DIGIT_SEPARATOR: u128 = 1 << 41; /// Multiple consecutive fraction digit separators are allowed. pub const FRACTION_CONSECUTIVE_DIGIT_SEPARATOR: u128 = 1 << 42; /// Multiple consecutive exponent digit separators are allowed. pub const EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR: u128 = 1 << 43; /// Digit separators are allowed between digits. pub const INTERNAL_DIGIT_SEPARATOR: u128 = INTEGER_INTERNAL_DIGIT_SEPARATOR | FRACTION_INTERNAL_DIGIT_SEPARATOR | EXPONENT_INTERNAL_DIGIT_SEPARATOR; /// A digit separator is allowed before any digits. pub const LEADING_DIGIT_SEPARATOR: u128 = INTEGER_LEADING_DIGIT_SEPARATOR | FRACTION_LEADING_DIGIT_SEPARATOR | EXPONENT_LEADING_DIGIT_SEPARATOR; /// A digit separator is allowed after any digits. pub const TRAILING_DIGIT_SEPARATOR: u128 = INTEGER_TRAILING_DIGIT_SEPARATOR | FRACTION_TRAILING_DIGIT_SEPARATOR | EXPONENT_TRAILING_DIGIT_SEPARATOR; /// Multiple consecutive digit separators are allowed. pub const CONSECUTIVE_DIGIT_SEPARATOR: u128 = INTEGER_CONSECUTIVE_DIGIT_SEPARATOR | FRACTION_CONSECUTIVE_DIGIT_SEPARATOR | EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR; /// Any digit separators are allowed in special (non-finite) values. pub const SPECIAL_DIGIT_SEPARATOR: u128 = 1 << 44; // Digit separator flags. const_assert!(INTEGER_INTERNAL_DIGIT_SEPARATOR == 1 << 32); check_subsequent_flags!(INTEGER_INTERNAL_DIGIT_SEPARATOR, FRACTION_INTERNAL_DIGIT_SEPARATOR); check_subsequent_flags!(FRACTION_INTERNAL_DIGIT_SEPARATOR, EXPONENT_INTERNAL_DIGIT_SEPARATOR); check_subsequent_flags!(EXPONENT_INTERNAL_DIGIT_SEPARATOR, INTEGER_LEADING_DIGIT_SEPARATOR); check_subsequent_flags!(INTEGER_LEADING_DIGIT_SEPARATOR, FRACTION_LEADING_DIGIT_SEPARATOR); check_subsequent_flags!(FRACTION_LEADING_DIGIT_SEPARATOR, EXPONENT_LEADING_DIGIT_SEPARATOR); check_subsequent_flags!(EXPONENT_LEADING_DIGIT_SEPARATOR, INTEGER_TRAILING_DIGIT_SEPARATOR); check_subsequent_flags!(INTEGER_TRAILING_DIGIT_SEPARATOR, FRACTION_TRAILING_DIGIT_SEPARATOR); check_subsequent_flags!(FRACTION_TRAILING_DIGIT_SEPARATOR, EXPONENT_TRAILING_DIGIT_SEPARATOR); check_subsequent_flags!(EXPONENT_TRAILING_DIGIT_SEPARATOR, INTEGER_CONSECUTIVE_DIGIT_SEPARATOR); check_subsequent_flags!(INTEGER_CONSECUTIVE_DIGIT_SEPARATOR, FRACTION_CONSECUTIVE_DIGIT_SEPARATOR); check_subsequent_flags!(FRACTION_CONSECUTIVE_DIGIT_SEPARATOR, EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR); check_subsequent_flags!(EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR, SPECIAL_DIGIT_SEPARATOR); // CONTROL CHARACTER & RADIX MASKS // ------------------------------- /// Shift to convert to and from a digit separator as a `u8`. pub const DIGIT_SEPARATOR_SHIFT: i32 = 64; /// Mask to extract the digit separator character. pub const DIGIT_SEPARATOR: u128 = 0xFF << DIGIT_SEPARATOR_SHIFT; /// Shift to convert to and from a base prefix as a `u8`. pub const BASE_PREFIX_SHIFT: i32 = 88; /// Mask to extract the base prefix character. pub const BASE_PREFIX: u128 = 0xFF << BASE_PREFIX_SHIFT; /// Shift to convert to and from a base suffix as a `u8`. pub const BASE_SUFFIX_SHIFT: i32 = 96; /// Mask to extract the base suffix character. pub const BASE_SUFFIX: u128 = 0xFF << BASE_SUFFIX_SHIFT; /// Shift to convert to and from a mantissa radix as a `u32`. pub const MANTISSA_RADIX_SHIFT: i32 = 104; /// Mask to extract the mantissa radix: the radix for the significant digits. pub const MANTISSA_RADIX: u128 = 0xFF << MANTISSA_RADIX_SHIFT; /// Alias for MANTISSA_RADIX_SHIFT. pub const RADIX_SHIFT: i32 = MANTISSA_RADIX_SHIFT; /// Alias for MANTISSA_RADIX. pub const RADIX: u128 = MANTISSA_RADIX; /// Shift to convert to and from an exponent base as a `u32`. pub const EXPONENT_BASE_SHIFT: i32 = 112; /// Mask to extract the exponent base: the base the exponent is raised to. pub const EXPONENT_BASE: u128 = 0xFF << EXPONENT_BASE_SHIFT; /// Shift to convert to and from an exponent radix as a `u32`. pub const EXPONENT_RADIX_SHIFT: i32 = 120; /// Mask to extract the exponent radix: the radix for the exponent digits. pub const EXPONENT_RADIX: u128 = 0xFF << EXPONENT_RADIX_SHIFT; // Masks do not overlap. check_subsequent_masks!(DIGIT_SEPARATOR, BASE_PREFIX); check_subsequent_masks!(BASE_PREFIX, BASE_SUFFIX); check_subsequent_masks!(BASE_SUFFIX, MANTISSA_RADIX); check_subsequent_masks!(MANTISSA_RADIX, EXPONENT_BASE); check_subsequent_masks!(EXPONENT_BASE, EXPONENT_RADIX); // Check all our shifts shift the masks to a single byte. check_mask_shifts!(DIGIT_SEPARATOR, DIGIT_SEPARATOR_SHIFT); check_mask_shifts!(BASE_PREFIX, BASE_PREFIX_SHIFT); check_mask_shifts!(BASE_SUFFIX, BASE_SUFFIX_SHIFT); check_mask_shifts!(MANTISSA_RADIX, MANTISSA_RADIX_SHIFT); check_mask_shifts!(EXPONENT_BASE, EXPONENT_BASE_SHIFT); check_mask_shifts!(EXPONENT_RADIX, EXPONENT_RADIX_SHIFT); // Check masks don't overlap with neighboring flags. check_masks_and_flags!(DIGIT_SEPARATOR, SPECIAL_DIGIT_SEPARATOR); // HIDDEN MASKS // ------------ /// Mask to extract the flag bits. #[doc(hidden)] pub const FLAG_MASK: u128 = REQUIRED_DIGITS | NO_POSITIVE_MANTISSA_SIGN | REQUIRED_MANTISSA_SIGN | NO_EXPONENT_NOTATION | NO_POSITIVE_EXPONENT_SIGN | REQUIRED_EXPONENT_SIGN | NO_EXPONENT_WITHOUT_FRACTION | NO_SPECIAL | CASE_SENSITIVE_SPECIAL | NO_INTEGER_LEADING_ZEROS | NO_FLOAT_LEADING_ZEROS | REQUIRED_EXPONENT_NOTATION | CASE_SENSITIVE_EXPONENT | CASE_SENSITIVE_BASE_PREFIX | CASE_SENSITIVE_BASE_SUFFIX | INTERNAL_DIGIT_SEPARATOR | LEADING_DIGIT_SEPARATOR | TRAILING_DIGIT_SEPARATOR | CONSECUTIVE_DIGIT_SEPARATOR | SPECIAL_DIGIT_SEPARATOR; /// Mask to extract the flag bits controlling interface parsing. /// /// This mask controls all the flags handled by the interface, /// omitting those that are handled prior. This limits the /// number of match paths required to determine the correct /// interface. #[doc(hidden)] pub const INTERFACE_FLAG_MASK: u128 = REQUIRED_DIGITS | NO_EXPONENT_NOTATION | NO_POSITIVE_EXPONENT_SIGN | REQUIRED_EXPONENT_SIGN | NO_EXPONENT_WITHOUT_FRACTION | NO_FLOAT_LEADING_ZEROS | REQUIRED_EXPONENT_NOTATION | INTERNAL_DIGIT_SEPARATOR | LEADING_DIGIT_SEPARATOR | TRAILING_DIGIT_SEPARATOR | CONSECUTIVE_DIGIT_SEPARATOR; /// Mask to extract digit separator flags. #[doc(hidden)] pub const DIGIT_SEPARATOR_FLAG_MASK: u128 = INTERNAL_DIGIT_SEPARATOR | LEADING_DIGIT_SEPARATOR | TRAILING_DIGIT_SEPARATOR | CONSECUTIVE_DIGIT_SEPARATOR | SPECIAL_DIGIT_SEPARATOR; /// Mask to extract exponent flags. #[doc(hidden)] pub const EXPONENT_FLAG_MASK: u128 = REQUIRED_EXPONENT_DIGITS | NO_EXPONENT_NOTATION | NO_POSITIVE_EXPONENT_SIGN | REQUIRED_EXPONENT_SIGN | NO_EXPONENT_WITHOUT_FRACTION | REQUIRED_EXPONENT_NOTATION | EXPONENT_INTERNAL_DIGIT_SEPARATOR | EXPONENT_LEADING_DIGIT_SEPARATOR | EXPONENT_TRAILING_DIGIT_SEPARATOR | EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR; /// Mask to extract integer digit separator flags. #[doc(hidden)] pub const INTEGER_DIGIT_SEPARATOR_FLAG_MASK: u128 = INTEGER_INTERNAL_DIGIT_SEPARATOR | INTEGER_LEADING_DIGIT_SEPARATOR | INTEGER_TRAILING_DIGIT_SEPARATOR | INTEGER_CONSECUTIVE_DIGIT_SEPARATOR; /// Mask to extract fraction digit separator flags. #[doc(hidden)] pub const FRACTION_DIGIT_SEPARATOR_FLAG_MASK: u128 = FRACTION_INTERNAL_DIGIT_SEPARATOR | FRACTION_LEADING_DIGIT_SEPARATOR | FRACTION_TRAILING_DIGIT_SEPARATOR | FRACTION_CONSECUTIVE_DIGIT_SEPARATOR; /// Mask to extract exponent digit separator flags. #[doc(hidden)] pub const EXPONENT_DIGIT_SEPARATOR_FLAG_MASK: u128 = EXPONENT_INTERNAL_DIGIT_SEPARATOR | EXPONENT_LEADING_DIGIT_SEPARATOR | EXPONENT_TRAILING_DIGIT_SEPARATOR | EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR; // EXTRACTORS // ---------- /// Extract the digit separator from the format packed struct. #[inline] pub const fn digit_separator(format: u128) -> u8 { ((format & DIGIT_SEPARATOR) >> DIGIT_SEPARATOR_SHIFT) as u8 } /// Extract the base prefix character from the format packed struct. #[inline] pub const fn base_prefix(format: u128) -> u8 { ((format & BASE_PREFIX) >> BASE_PREFIX_SHIFT) as u8 } /// Extract the base suffix character from the format packed struct. #[inline] pub const fn base_suffix(format: u128) -> u8 { ((format & BASE_SUFFIX) >> BASE_SUFFIX_SHIFT) as u8 } /// Extract the mantissa radix from the format packed struct. #[inline] pub const fn mantissa_radix(format: u128) -> u32 { ((format & MANTISSA_RADIX) >> MANTISSA_RADIX_SHIFT) as u32 } /// Extract the exponent base from the format packed struct. /// If not provided, defaults to `mantissa_radix`. #[inline] pub const fn exponent_base(format: u128) -> u32 { let radix = ((format & EXPONENT_BASE) >> EXPONENT_BASE_SHIFT) as u32; if radix == 0 { mantissa_radix(format) } else { radix } } /// Extract the exponent radix from the format packed struct. /// If not provided, defaults to `mantissa_radix`. #[inline] pub const fn exponent_radix(format: u128) -> u32 { let radix = ((format & EXPONENT_RADIX) >> EXPONENT_RADIX_SHIFT) as u32; if radix == 0 { mantissa_radix(format) } else { radix } } /// Extract a generic radix from the format and bitflags. #[inline] pub const fn radix_from_flags(format: u128, mask: u128, shift: i32) -> u32 { let radix = ((format & mask) >> shift) as u32; if radix == 0 { mantissa_radix(format) } else { radix } } // VALIDATORS // ---------- /// Determine if the provided exponent flags are valid. #[inline] pub const fn is_valid_exponent_flags(format: u128) -> bool { // Both cannot be set. format & NO_EXPONENT_NOTATION == 0 || format & REQUIRED_EXPONENT_NOTATION == 0 } /// Determine if an optional control character is valid. #[inline] const fn is_valid_optional_control_radix(radix: u32, value: u8) -> bool { // Validate the character isn't a digit or sign character, and is valid ASCII. use crate::ascii::is_valid_ascii; use crate::digit::char_is_digit_const; !char_is_digit_const(value, radix) && value != b'+' && value != b'-' && (is_valid_ascii(value) || value == 0) } /// Determine if an optional control character is valid. #[inline] const fn is_valid_optional_control(format: u128, value: u8) -> bool { // Need to get the larger of the two radix values, since these // will be the characters that define the valid digits. // const fn doesn't support max as of 1.55 nightly. let mradix = mantissa_radix(format); let eradix = exponent_radix(format); let radix = if mradix > eradix { mradix } else { eradix }; is_valid_optional_control_radix(radix, value) } /// Determine if an control character is valid. #[inline] const fn is_valid_control(format: u128, value: u8) -> bool { value != 0 && is_valid_optional_control(format, value) } /// Determine if the digit separator is valid. /// Digit separators must not be valid digits or sign characters. #[inline] pub const fn is_valid_digit_separator(format: u128) -> bool { let value = digit_separator(format); if cfg!(feature = "format") { is_valid_optional_control(format, value) } else { value == 0 } } /// Determine if the base prefix character is valid. #[inline] pub const fn is_valid_base_prefix(format: u128) -> bool { let value = base_prefix(format); if cfg!(feature = "format") { is_valid_optional_control(format, value) } else { value == 0 } } /// Determine if the base suffix character is valid. #[inline] pub const fn is_valid_base_suffix(format: u128) -> bool { let value = base_suffix(format); if cfg!(feature = "format") { is_valid_optional_control(format, value) } else { value == 0 } } /// Determine if all of the "punctuation" characters are valid. #[inline] #[allow(clippy::if_same_then_else)] pub const fn is_valid_punctuation(format: u128) -> bool { // All the checks against optional characters with mandatory are fine: // if they're not 0, then they can't overlap, and mandatory can't be 0. if cfg!(not(feature = "format")) && digit_separator(format) != 0 { // Digit separator set when not allowed. false } else { let separator = digit_separator(format); let prefix = base_prefix(format); let suffix = base_suffix(format); // Check all are optional, or enough are not present. match (separator, prefix, suffix) { (0, 0, 0) => true, (_, 0, 0) => true, (0, _, 0) => true, (0, 0, _) => true, // Can't have more than 1 0, check they're all different. (x, y, z) => x != y && x != z && y != z, } } } /// Determine if all of the "punctuation" characters for the options API are valid. #[inline] #[allow(clippy::if_same_then_else, clippy::needless_bool)] pub const fn is_valid_options_punctuation(format: u128, exponent: u8, decimal_point: u8) -> bool { // All the checks against optional characters with mandatory are fine: // if they're not 0, then they can't overlap, and mandatory can't be 0. if !is_valid_control(format, decimal_point) || !is_valid_control(format, exponent) { // Must be in the valid range. false } else if decimal_point == exponent { // Can't have overlapping characters. false } else if cfg!(feature = "format") && digit_separator(format) == decimal_point { false } else if cfg!(feature = "format") && digit_separator(format) == exponent { false } else if cfg!(feature = "format") && base_prefix(format) == decimal_point { false } else if cfg!(feature = "format") && base_prefix(format) == exponent { false } else if cfg!(feature = "format") && base_suffix(format) == decimal_point { false } else if cfg!(feature = "format") && base_suffix(format) == exponent { false } else { true } } /// Determine if the radix is valid. pub const fn is_valid_radix(radix: u32) -> bool { if cfg!(feature = "radix") { radix >= 2 && radix <= 36 } else if cfg!(feature = "power-of-two") { matches!(radix, 2 | 4 | 8 | 10 | 16 | 32) } else { radix == 10 } } lexical-util-0.8.5/src/iterator.rs000064400000000000000000000107540072674642500152570ustar 00000000000000//! Specialized iterator traits. //! //! The traits are iterable, and provide optimizations for contiguous //! iterators, while still working for non-contiguous data. #![cfg(feature = "parse")] // Re-export our digit iterators. #[cfg(not(feature = "format"))] pub use crate::noskip::{AsBytes, Bytes}; #[cfg(feature = "format")] pub use crate::skip::{AsBytes, Bytes}; /// Iterator over a contiguous block of bytes. /// /// This allows us to convert to-and-from-slices, raw pointers, and /// peek/query the data from either end cheaply. /// /// A default implementation is provided for slice iterators. /// This trait **should never** return `null` from `as_ptr`, or be /// implemented for non-contiguous data. pub trait BytesIter<'a>: Iterator { /// Determine if each yielded value is adjacent in memory. const IS_CONTIGUOUS: bool; /// Get a ptr to the current start of the iterator. fn as_ptr(&self) -> *const u8; /// Get a slice to the current start of the iterator. fn as_slice(&self) -> &'a [u8]; /// Get the total number of elements in the underlying slice. fn length(&self) -> usize; /// Get the current index of the iterator in the slice. fn cursor(&self) -> usize; /// Set the current index of the iterator in the slice. /// /// # Safety /// /// Safe if `index <= self.length()`. unsafe fn set_cursor(&mut self, index: usize); /// Get the current number of values returned by the iterator. fn current_count(&self) -> usize; /// Get if the iterator cannot return any more elements. /// /// This may advance the internal iterator state, but not /// modify the next returned value. #[allow(clippy::wrong_self_convention)] fn is_consumed(&mut self) -> bool; /// Get if the buffer underlying the iterator is empty. /// /// This might not be the same thing as `is_consumed`: `is_consumed` /// checks if any more elements may be returned, which may require /// peeking the next value. Consumed merely checks if the /// iterator has an empty slice. It is effectively a cheaper, /// but weaker variant of `is_consumed()`. fn is_done(&self) -> bool; /// Determine if the iterator is contiguous. #[inline] fn is_contiguous(&self) -> bool { Self::IS_CONTIGUOUS } /// Peek the next value of the iterator, without checking bounds. /// /// # Safety /// /// Safe as long as there is at least a single valid value left in /// the iterator. Note that the behavior of this may lead to out-of-bounds /// access (for contiguous iterators) or panics (for non-contiguous /// iterators). unsafe fn peek_unchecked(&mut self) -> Self::Item; /// Peek the next value of the iterator, without consuming it. fn peek(&mut self) -> Option; /// Check if the next element is a given value. #[inline] fn peek_is(&mut self, value: u8) -> bool { if let Some(&c) = self.peek() { c == value } else { false } } /// Check if the next element is a given value without case sensitivity. #[inline] fn case_insensitive_peek_is(&mut self, value: u8) -> bool { if let Some(&c) = self.peek() { c.to_ascii_lowercase() == value.to_ascii_lowercase() } else { false } } /// Skip zeros from the start of the iterator #[inline] fn skip_zeros(&mut self) -> usize { let start = self.cursor(); while let Some(&b'0') = self.peek() { self.next(); } self.cursor() - start } /// Read a value of a difference type from the iterator. /// This advances the internal state of the iterator. /// /// # Safety /// /// Safe as long as the number of the buffer is contains as least as /// many bytes as the size of V. unsafe fn read_unchecked(&self) -> V; /// Try to read a value of a different type from the iterator. /// This advances the internal state of the iterator. fn read(&self) -> Option; /// Advance the internal slice by `N` elements. /// /// # Safety /// /// As long as the iterator is at least `N` elements, this /// is safe. unsafe fn step_by_unchecked(&mut self, count: usize); /// Advance the internal slice by 1 element. /// /// # Safety /// /// Safe as long as the iterator is not empty. #[inline] unsafe fn step_unchecked(&mut self) { unsafe { self.step_by_unchecked(1) }; } } lexical-util-0.8.5/src/lib.rs000064400000000000000000000043130072674642500141660ustar 00000000000000//! Shared utilities for lexical conversion routines. //! //! These are not meant to be used publicly for any numeric //! conversion routines, but provide optimized math routines, //! format packed struct definitions, and custom iterators //! for all workspaces. //! //! # Features //! //! * `std` - Use the standard library. //! * `power-of-two` - Add support for parsing power-of-two integer strings. //! * `radix` - Add support for strings of any radix. //! * `write-integers` - Add support for writing integers. //! * `write-floats` - Add support for writing floats. //! * `parse-integers` - Add support for parsing integers. //! * `parse-floats` - Add support for parsing floats. //! * `compact` - Reduce code size at the cost of performance. //! //! # Note //! //! None of this is considered a public API: any of the implementation //! details may change release-to-release without major or minor version //! changes. Use internal implementation details at your own risk. //! //! lexical-util mainly exists as an implementation detail for //! lexical-core, although its API is stable. If you would like to use //! a high-level API that writes to and parses from `String` and `&str`, //! respectively, please look at [lexical](https://crates.io/crates/lexical) //! instead. If you would like an API that supports multiple numeric //! conversions, please look at [lexical-core](https://crates.io/crates/lexical-core) //! instead. //! //! # Version Support //! //! The minimum, standard, required version is 1.51.0, for const generic //! support. Older versions of lexical support older Rust versions. // We want to have the same safety guarantees as Rust core, // so we allow unused unsafe to clearly document safety guarantees. #![allow(unused_unsafe)] #![cfg_attr(feature = "lint", warn(unsafe_op_in_unsafe_fn))] #![cfg_attr(not(feature = "std"), no_std)] pub mod algorithm; pub mod ascii; pub mod assert; pub mod bf16; pub mod constants; pub mod digit; pub mod div128; pub mod error; pub mod extended_float; pub mod f16; pub mod format; pub mod iterator; pub mod mul; pub mod num; pub mod options; pub mod result; pub mod step; mod api; mod feature_format; mod format_builder; mod format_flags; mod noskip; mod not_feature_format; mod skip; lexical-util-0.8.5/src/mul.rs000064400000000000000000000031000072674642500142060ustar 00000000000000//! Fast multiplication routines. use crate::num::{as_cast, UnsignedInteger}; /// Multiply two unsigned, integral values, and return the hi and lo product. /// /// The `full` type is the full type size, while the `half` type is the type /// with exactly half the bits. #[inline(always)] pub fn mul(x: Full, y: Full) -> (Full, Full) where Full: UnsignedInteger, Half: UnsignedInteger, { // Extract high-and-low masks. let x1 = x >> Half::BITS as i32; let x0 = x & as_cast(Half::MAX); let y1 = y >> Half::BITS as i32; let y0 = y & as_cast(Half::MAX); let w0 = x0 * y0; let tmp = (x1 * y0) + (w0 >> Half::BITS as i32); let w1 = tmp & as_cast(Half::MAX); let w2 = tmp >> Half::BITS as i32; let w1 = w1 + x0 * y1; let hi = (x1 * y1) + w2 + (w1 >> Half::BITS as i32); let lo = x.wrapping_mul(y); (hi, lo) } /// Multiply two unsigned, integral values, and return the hi product. /// /// The `full` type is the full type size, while the `half` type is the type /// with exactly half the bits. #[inline(always)] pub fn mulhi(x: Full, y: Full) -> Full where Full: UnsignedInteger, Half: UnsignedInteger, { // Extract high-and-low masks. let x1 = x >> Half::BITS as i32; let x0 = x & as_cast(Half::MAX); let y1 = y >> Half::BITS as i32; let y0 = y & as_cast(Half::MAX); let w0 = x0 * y0; let m = (x0 * y1) + (w0 >> Half::BITS as i32); let w1 = m & as_cast(Half::MAX); let w2 = m >> Half::BITS as i32; let w3 = (x1 * y0 + w1) >> Half::BITS as i32; x1 * y1 + w2 + w3 } lexical-util-0.8.5/src/noskip.rs000064400000000000000000000211310072674642500147200ustar 00000000000000//! An iterator over a slice. //! //! This iterator has both the length of the original slice, as //! well as the current position of the iterator in the buffer. #![cfg(all(feature = "parse", not(feature = "format")))] use crate::iterator::BytesIter; use core::{mem, ptr}; // AS DIGITS // --------- /// Trait to simplify creation of a `Bytes` object. pub trait AsBytes<'a> { /// Create `Bytes` from object. fn bytes(&'a self) -> Bytes<'a, __>; } impl<'a> AsBytes<'a> for [u8] { #[inline] fn bytes(&'a self) -> Bytes<'a, __> { Bytes::new(self) } } // DIGITS // ------ /// Slice iterator that stores the original length of the slice. #[derive(Clone)] pub struct Bytes<'a, const __: u128> { /// The raw slice for the iterator. slc: &'a [u8], /// Current index of the iterator in the slice. index: usize, } impl<'a, const __: u128> Bytes<'a, __> { /// If each yielded value is adjacent in memory. pub const IS_CONTIGUOUS: bool = true; /// Create new byte object. #[inline] pub const fn new(slc: &'a [u8]) -> Self { Self { slc, index: 0, } } /// Get a ptr to the current start of the iterator. #[inline] pub fn as_ptr(&self) -> *const u8 { self.as_slice().as_ptr() } /// Get a slice to the current start of the iterator. #[inline] pub fn as_slice(&self) -> &'a [u8] { debug_assert!(self.index <= self.length()); // SAFETY: safe since index must be in range. unsafe { self.slc.get_unchecked(self.index..) } } /// Get the total number of elements in the underlying slice. #[inline] pub fn length(&self) -> usize { self.slc.len() } /// Get the current index of the iterator in the slice. #[inline] pub fn cursor(&self) -> usize { self.index } /// Set the current index of the iterator in the slice. /// /// # Safety /// /// Safe if `index <= self.length()`. #[inline] pub unsafe fn set_cursor(&mut self, index: usize) { debug_assert!(index <= self.length()); self.index = index } /// Get the current number of values returned by the iterator. #[inline] pub fn current_count(&self) -> usize { self.index } /// Get if the buffer underlying the iterator is empty. /// Same as `is_consumed`. #[inline] pub fn is_done(&self) -> bool { self.index >= self.slc.len() } /// Read a value of a difference type from the iterator. /// This advances the internal state of the iterator. /// /// # Safety /// /// Safe as long as the number of the buffer is contains as least as /// many bytes as the size of V. #[inline] #[allow(clippy::assertions_on_constants)] pub unsafe fn read_unchecked(&self) -> V { debug_assert!(Self::IS_CONTIGUOUS); debug_assert!(self.as_slice().len() >= mem::size_of::()); let slc = self.as_slice(); // SAFETY: safe as long as the slice has at least count elements. unsafe { ptr::read_unaligned::(slc.as_ptr() as *const _) } } /// Try to read a value of a different type from the iterator. /// This advances the internal state of the iterator. #[inline] pub fn read(&self) -> Option { if Self::IS_CONTIGUOUS && self.as_slice().len() >= mem::size_of::() { // SAFETY: safe since we've guaranteed the buffer is greater than // the number of elements read. unsafe { Some(self.read_unchecked()) } } else { None } } /// Check if the next element is a given value. #[inline] pub fn first_is(&mut self, value: u8) -> bool { if let Some(&c) = self.slc.get(self.index) { c == value } else { false } } /// Check if the next element is a given value without case sensitivity. #[inline] pub fn case_insensitive_first_is(&mut self, value: u8) -> bool { if let Some(&c) = self.slc.get(self.index) { c.to_ascii_lowercase() == value.to_ascii_lowercase() } else { false } } /// Get iterator over integer digits. #[inline] pub fn integer_iter<'b>(&'b mut self) -> BytesIterator<'a, 'b, __> { BytesIterator { byte: self, } } /// Get iterator over fraction digits. #[inline] pub fn fraction_iter<'b>(&'b mut self) -> BytesIterator<'a, 'b, __> { BytesIterator { byte: self, } } /// Get iterator over exponent digits. #[inline] pub fn exponent_iter<'b>(&'b mut self) -> BytesIterator<'a, 'b, __> { BytesIterator { byte: self, } } /// Get iterator over special floating point values. #[inline] pub fn special_iter<'b>(&'b mut self) -> BytesIterator<'a, 'b, __> { BytesIterator { byte: self, } } /// Advance the byte by `N` elements. /// /// # Safety /// /// As long as the iterator is at least `N` elements, this /// is safe. #[inline] #[allow(clippy::assertions_on_constants)] pub unsafe fn step_by_unchecked(&mut self, count: usize) { debug_assert!(Self::IS_CONTIGUOUS); debug_assert!(self.as_slice().len() >= count); self.index += count; } /// Advance the byte by 1 element. /// /// # Safety /// /// Safe as long as the iterator is not empty. #[inline] #[allow(clippy::assertions_on_constants)] pub unsafe fn step_unchecked(&mut self) { debug_assert!(Self::IS_CONTIGUOUS); debug_assert!(!self.as_slice().is_empty()); self.index += 1; } } // DIGITS ITERATOR // --------------- /// Slice iterator that stores the original length of the slice. pub struct BytesIterator<'a: 'b, 'b, const __: u128> { /// The internal byte object for the noskip iterator. byte: &'b mut Bytes<'a, __>, } impl<'a: 'b, 'b, const __: u128> BytesIter<'a> for BytesIterator<'a, 'b, __> { const IS_CONTIGUOUS: bool = Bytes::<'a, __>::IS_CONTIGUOUS; #[inline] fn as_ptr(&self) -> *const u8 { self.byte.as_ptr() } #[inline] fn as_slice(&self) -> &'a [u8] { self.byte.as_slice() } #[inline] fn length(&self) -> usize { self.byte.length() } #[inline] fn cursor(&self) -> usize { self.byte.cursor() } #[inline] unsafe fn set_cursor(&mut self, index: usize) { debug_assert!(index <= self.length()); // SAFETY: safe if `index <= self.length()`. unsafe { self.byte.set_cursor(index) }; } #[inline] fn current_count(&self) -> usize { self.byte.current_count() } #[inline] fn is_consumed(&mut self) -> bool { Self::is_done(self) } #[inline] fn is_done(&self) -> bool { self.byte.is_done() } #[inline] unsafe fn peek_unchecked(&mut self) -> ::Item { // SAFETY: safe if `self.cursor() < self.length()`. unsafe { self.byte.slc.get_unchecked(self.byte.index) } } #[inline] fn peek(&mut self) -> Option<::Item> { if self.byte.index < self.byte.slc.len() { // SAFETY: the slice cannot be empty, so this is safe Some(unsafe { self.peek_unchecked() }) } else { None } } #[inline] unsafe fn read_unchecked(&self) -> V { debug_assert!(self.as_slice().len() >= mem::size_of::()); // SAFETY: safe as long as the slice has at least count elements. unsafe { self.byte.read_unchecked() } } #[inline] fn read(&self) -> Option { self.byte.read() } #[inline] unsafe fn step_by_unchecked(&mut self, count: usize) { debug_assert!(self.as_slice().len() >= count); // SAFETY: safe as long as `slc.len() >= count`. unsafe { self.byte.step_by_unchecked(count) } } #[inline] unsafe fn step_unchecked(&mut self) { debug_assert!(!self.as_slice().is_empty()); // SAFETY: safe as long as `slc.len() >= 1`. unsafe { self.byte.step_unchecked() } } } impl<'a: 'b, 'b, const __: u128> Iterator for BytesIterator<'a, 'b, __> { type Item = &'a u8; #[inline] fn next(&mut self) -> Option { let value = self.byte.slc.get(self.byte.index)?; self.byte.index += 1; Some(value) } } impl<'a: 'b, 'b, const __: u128> ExactSizeIterator for BytesIterator<'a, 'b, __> { #[inline] fn len(&self) -> usize { self.length() - self.cursor() } } lexical-util-0.8.5/src/not_feature_format.rs000064400000000000000000000451060072674642500173100ustar 00000000000000//! Bare bones implementation of the format packed struct without feature `format`. //! //! See `feature_format` for detailed documentation. #![cfg(not(feature = "format"))] use crate::error::Error; use crate::format_builder::NumberFormatBuilder; use crate::format_flags as flags; /// Wrapper for the 128-bit packed struct. /// /// The following values are explicitly set, and therefore not configurable: /// 1. required_integer_digits /// 2. required_fraction_digits /// 3. required_exponent_digits /// 4. required_mantissa_digits /// 5. required_digits /// 6. no_positive_mantissa_sign /// 7. required_mantissa_sign /// 8. no_exponent_notation /// 9. no_positive_exponent_sign /// 10. required_exponent_sign /// 11. no_exponent_without_fraction /// 12. no_special /// 13. case_sensitive_special /// 14. no_integer_leading_zeros /// 15. no_float_leading_zeros /// 16. required_exponent_notation /// 17. case_sensitive_exponent /// 18. case_sensitive_base_prefix /// 19. case_sensitive_base_suffix /// 20. integer_internal_digit_separator /// 21. fraction_internal_digit_separator /// 22. exponent_internal_digit_separator /// 23. internal_digit_separator /// 24. integer_leading_digit_separator /// 25. fraction_leading_digit_separator /// 26. exponent_leading_digit_separator /// 27. leading_digit_separator /// 28. integer_trailing_digit_separator /// 29. fraction_trailing_digit_separator /// 30. exponent_trailing_digit_separator /// 31. trailing_digit_separator /// 32. integer_consecutive_digit_separator /// 33. fraction_consecutive_digit_separator /// 34. exponent_consecutive_digit_separator /// 35. consecutive_digit_separator /// 36. special_digit_separator /// 37. digit_separator /// 38. base_prefix /// 39. base_suffix /// 40. exponent_base /// 41. exponent_radix /// /// See `NumberFormatBuilder` for the `FORMAT` fields /// for the packed struct. #[doc(hidden)] pub struct NumberFormat; impl NumberFormat { // CONSTRUCTORS /// Create new instance (for methods and validation). pub const fn new() -> Self { Self {} } // VALIDATION /// Determine if the number format is valid. pub const fn is_valid(&self) -> bool { self.error().is_success() } /// Get the error type from the format. pub const fn error(&self) -> Error { let valid_flags = flags::REQUIRED_EXPONENT_DIGITS | flags::REQUIRED_MANTISSA_DIGITS; if !flags::is_valid_radix(self.mantissa_radix()) { Error::InvalidMantissaRadix } else if !flags::is_valid_radix(self.exponent_base()) { Error::InvalidExponentBase } else if !flags::is_valid_radix(self.exponent_radix()) { Error::InvalidExponentRadix } else if !flags::is_valid_digit_separator(FORMAT) { Error::InvalidDigitSeparator } else if !flags::is_valid_base_prefix(FORMAT) { Error::InvalidBasePrefix } else if !flags::is_valid_base_suffix(FORMAT) { Error::InvalidBaseSuffix } else if !flags::is_valid_punctuation(FORMAT) { Error::InvalidPunctuation } else if self.flags() != valid_flags { Error::InvalidFlags } else { Error::Success } } // NON-DIGIT SEPARATOR FLAGS & MASKS /// If digits are required before the decimal point. pub const REQUIRED_INTEGER_DIGITS: bool = false; /// Get if digits are required before the decimal point. #[inline(always)] pub const fn required_integer_digits(&self) -> bool { Self::REQUIRED_INTEGER_DIGITS } /// If digits are required after the decimal point. pub const REQUIRED_FRACTION_DIGITS: bool = false; /// Get if digits are required after the decimal point. #[inline(always)] pub const fn required_fraction_digits(&self) -> bool { Self::REQUIRED_FRACTION_DIGITS } /// If digits are required after the exponent character. pub const REQUIRED_EXPONENT_DIGITS: bool = true; /// Get if digits are required after the exponent character. #[inline(always)] pub const fn required_exponent_digits(&self) -> bool { Self::REQUIRED_EXPONENT_DIGITS } /// If significant digits are required. pub const REQUIRED_MANTISSA_DIGITS: bool = true; /// Get if significant digits are required. #[inline(always)] pub const fn required_mantissa_digits(&self) -> bool { Self::REQUIRED_MANTISSA_DIGITS } /// If at least 1 digit in the number is required. pub const REQUIRED_DIGITS: bool = true; /// Get if at least 1 digit in the number is required. #[inline(always)] pub const fn required_digits(&self) -> bool { Self::REQUIRED_DIGITS } /// If a positive sign before the mantissa is not allowed. pub const NO_POSITIVE_MANTISSA_SIGN: bool = false; /// Get if a positive sign before the mantissa is not allowed. #[inline(always)] pub const fn no_positive_mantissa_sign(&self) -> bool { Self::NO_POSITIVE_MANTISSA_SIGN } /// If a sign symbol before the mantissa is required. pub const REQUIRED_MANTISSA_SIGN: bool = false; /// Get if a sign symbol before the mantissa is required. #[inline(always)] pub const fn required_mantissa_sign(&self) -> bool { Self::REQUIRED_MANTISSA_SIGN } /// If exponent notation is not allowed. pub const NO_EXPONENT_NOTATION: bool = false; /// Get if exponent notation is not allowed. #[inline(always)] pub const fn no_exponent_notation(&self) -> bool { Self::NO_EXPONENT_NOTATION } /// If a positive sign before the exponent is not allowed. pub const NO_POSITIVE_EXPONENT_SIGN: bool = false; /// Get if a positive sign before the exponent is not allowed. #[inline(always)] pub const fn no_positive_exponent_sign(&self) -> bool { Self::NO_POSITIVE_EXPONENT_SIGN } /// If a sign symbol before the exponent is required. pub const REQUIRED_EXPONENT_SIGN: bool = false; /// Get if a sign symbol before the exponent is required. #[inline(always)] pub const fn required_exponent_sign(&self) -> bool { Self::REQUIRED_EXPONENT_SIGN } /// If an exponent without fraction is not allowed. pub const NO_EXPONENT_WITHOUT_FRACTION: bool = false; /// Get if an exponent without fraction is not allowed. #[inline(always)] pub const fn no_exponent_without_fraction(&self) -> bool { Self::NO_EXPONENT_WITHOUT_FRACTION } /// If special (non-finite) values are not allowed. pub const NO_SPECIAL: bool = false; /// Get if special (non-finite) values are not allowed. #[inline(always)] pub const fn no_special(&self) -> bool { Self::NO_SPECIAL } /// If special (non-finite) values are case-sensitive. pub const CASE_SENSITIVE_SPECIAL: bool = false; /// Get if special (non-finite) values are case-sensitive. #[inline(always)] pub const fn case_sensitive_special(&self) -> bool { Self::CASE_SENSITIVE_SPECIAL } /// If leading zeros before an integer are not allowed. pub const NO_INTEGER_LEADING_ZEROS: bool = false; /// Get if leading zeros before an integer are not allowed. #[inline(always)] pub const fn no_integer_leading_zeros(&self) -> bool { Self::NO_INTEGER_LEADING_ZEROS } /// If leading zeros before a float are not allowed. pub const NO_FLOAT_LEADING_ZEROS: bool = false; /// Get if leading zeros before a float are not allowed. #[inline(always)] pub const fn no_float_leading_zeros(&self) -> bool { Self::NO_FLOAT_LEADING_ZEROS } /// If exponent notation is required. pub const REQUIRED_EXPONENT_NOTATION: bool = false; /// Get if exponent notation is required. #[inline(always)] pub const fn required_exponent_notation(&self) -> bool { Self::REQUIRED_EXPONENT_NOTATION } /// If exponent characters are case-sensitive. pub const CASE_SENSITIVE_EXPONENT: bool = false; /// Get if exponent characters are case-sensitive. #[inline(always)] pub const fn case_sensitive_exponent(&self) -> bool { Self::CASE_SENSITIVE_EXPONENT } /// If base prefixes are case-sensitive. pub const CASE_SENSITIVE_BASE_PREFIX: bool = false; /// Get if base prefixes are case-sensitive. #[inline(always)] pub const fn case_sensitive_base_prefix(&self) -> bool { Self::CASE_SENSITIVE_BASE_PREFIX } /// If base suffixes are case-sensitive. pub const CASE_SENSITIVE_BASE_SUFFIX: bool = false; /// Get if base suffixes are case-sensitive. #[inline(always)] pub const fn case_sensitive_base_suffix(&self) -> bool { Self::CASE_SENSITIVE_BASE_SUFFIX } // DIGIT SEPARATOR FLAGS & MASKS // If digit separators are allowed between integer digits. pub const INTEGER_INTERNAL_DIGIT_SEPARATOR: bool = false; /// Get if digit separators are allowed between integer digits. #[inline(always)] pub const fn integer_internal_digit_separator(&self) -> bool { Self::INTEGER_INTERNAL_DIGIT_SEPARATOR } /// If digit separators are allowed between fraction digits. pub const FRACTION_INTERNAL_DIGIT_SEPARATOR: bool = false; /// Get if digit separators are allowed between fraction digits. #[inline(always)] pub const fn fraction_internal_digit_separator(&self) -> bool { Self::FRACTION_INTERNAL_DIGIT_SEPARATOR } /// If digit separators are allowed between exponent digits. pub const EXPONENT_INTERNAL_DIGIT_SEPARATOR: bool = false; /// Get if digit separators are allowed between exponent digits. #[inline(always)] pub const fn exponent_internal_digit_separator(&self) -> bool { Self::EXPONENT_INTERNAL_DIGIT_SEPARATOR } /// If digit separators are allowed between digits. pub const INTERNAL_DIGIT_SEPARATOR: bool = false; /// Get if digit separators are allowed between digits. #[inline(always)] pub const fn internal_digit_separator(&self) -> bool { Self::INTERNAL_DIGIT_SEPARATOR } /// If a digit separator is allowed before any integer digits. pub const INTEGER_LEADING_DIGIT_SEPARATOR: bool = false; /// Get if a digit separator is allowed before any integer digits. #[inline(always)] pub const fn integer_leading_digit_separator(&self) -> bool { Self::INTEGER_LEADING_DIGIT_SEPARATOR } /// If a digit separator is allowed before any integer digits. pub const FRACTION_LEADING_DIGIT_SEPARATOR: bool = false; /// Get if a digit separator is allowed before any fraction digits. #[inline(always)] pub const fn fraction_leading_digit_separator(&self) -> bool { Self::FRACTION_LEADING_DIGIT_SEPARATOR } /// If a digit separator is allowed before any exponent digits. pub const EXPONENT_LEADING_DIGIT_SEPARATOR: bool = false; /// Get if a digit separator is allowed before any exponent digits. #[inline(always)] pub const fn exponent_leading_digit_separator(&self) -> bool { Self::EXPONENT_LEADING_DIGIT_SEPARATOR } /// If a digit separator is allowed before any digits. pub const LEADING_DIGIT_SEPARATOR: bool = false; /// Get if a digit separator is allowed before any digits. #[inline(always)] pub const fn leading_digit_separator(&self) -> bool { Self::LEADING_DIGIT_SEPARATOR } /// If a digit separator is allowed after any integer digits. pub const INTEGER_TRAILING_DIGIT_SEPARATOR: bool = false; /// Get if a digit separator is allowed after any integer digits. #[inline(always)] pub const fn integer_trailing_digit_separator(&self) -> bool { Self::INTEGER_TRAILING_DIGIT_SEPARATOR } /// If a digit separator is allowed after any fraction digits. pub const FRACTION_TRAILING_DIGIT_SEPARATOR: bool = false; /// Get if a digit separator is allowed after any fraction digits. #[inline(always)] pub const fn fraction_trailing_digit_separator(&self) -> bool { Self::FRACTION_TRAILING_DIGIT_SEPARATOR } /// If a digit separator is allowed after any exponent digits. pub const EXPONENT_TRAILING_DIGIT_SEPARATOR: bool = false; /// Get if a digit separator is allowed after any exponent digits. #[inline(always)] pub const fn exponent_trailing_digit_separator(&self) -> bool { Self::EXPONENT_TRAILING_DIGIT_SEPARATOR } /// If a digit separator is allowed after any digits. pub const TRAILING_DIGIT_SEPARATOR: bool = false; /// Get if a digit separator is allowed after any digits. #[inline(always)] pub const fn trailing_digit_separator(&self) -> bool { Self::TRAILING_DIGIT_SEPARATOR } /// If multiple consecutive integer digit separators are allowed. pub const INTEGER_CONSECUTIVE_DIGIT_SEPARATOR: bool = false; /// Get if multiple consecutive integer digit separators are allowed. #[inline(always)] pub const fn integer_consecutive_digit_separator(&self) -> bool { Self::INTEGER_CONSECUTIVE_DIGIT_SEPARATOR } /// If multiple consecutive fraction digit separators are allowed. pub const FRACTION_CONSECUTIVE_DIGIT_SEPARATOR: bool = false; /// Get if multiple consecutive fraction digit separators are allowed. #[inline(always)] pub const fn fraction_consecutive_digit_separator(&self) -> bool { Self::FRACTION_CONSECUTIVE_DIGIT_SEPARATOR } /// If multiple consecutive exponent digit separators are allowed. pub const EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR: bool = false; /// Get if multiple consecutive exponent digit separators are allowed. #[inline(always)] pub const fn exponent_consecutive_digit_separator(&self) -> bool { Self::EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR } /// If multiple consecutive digit separators are allowed. pub const CONSECUTIVE_DIGIT_SEPARATOR: bool = false; /// Get if multiple consecutive digit separators are allowed. #[inline(always)] pub const fn consecutive_digit_separator(&self) -> bool { Self::CONSECUTIVE_DIGIT_SEPARATOR } /// If any digit separators are allowed in special (non-finite) values. pub const SPECIAL_DIGIT_SEPARATOR: bool = false; /// Get if any digit separators are allowed in special (non-finite) values. #[inline(always)] pub const fn special_digit_separator(&self) -> bool { Self::SPECIAL_DIGIT_SEPARATOR } // CHARACTERS /// The digit separator character in the packed struct. pub const DIGIT_SEPARATOR: u8 = 0; /// Get the digit separator character. /// /// If the digit separator is 0, digit separators are not allowed. #[inline(always)] pub const fn digit_separator(&self) -> u8 { Self::DIGIT_SEPARATOR } /// The base prefix character in the packed struct. pub const BASE_PREFIX: u8 = 0; /// Get the character for the base prefix. /// /// If the base prefix is 0, base prefixes are not allowed. /// The number will have then have the format `0$base_prefix...`. /// For example, a hex base prefix would be `0x`. Base prefixes are /// always optional. #[inline(always)] pub const fn base_prefix(&self) -> u8 { Self::BASE_PREFIX } /// The base suffix character in the packed struct. pub const BASE_SUFFIX: u8 = 0; /// Character for the base suffix. /// /// If not provided, base suffixes are not allowed. /// The number will have then have the format `...$base_suffix`. /// For example, a hex base prefix would be `0x`. Base prefixes are /// always optional. #[inline(always)] pub const fn base_suffix(&self) -> u8 { Self::BASE_SUFFIX } // RADIX /// The radix for the significant digits in the packed struct. pub const MANTISSA_RADIX: u32 = flags::mantissa_radix(FORMAT); /// Get the radix for the mantissa digits. #[inline(always)] pub const fn mantissa_radix(&self) -> u32 { Self::MANTISSA_RADIX } /// The radix for the significant digits in the packed struct. /// Alias for `MANTISSA_RADIX`. pub const RADIX: u32 = Self::MANTISSA_RADIX; /// Get the radix for the significant digits. #[inline(always)] pub const fn radix(&self) -> u32 { Self::RADIX } /// The base for the exponent. pub const EXPONENT_BASE: u32 = flags::exponent_base(FORMAT); /// Get the base for the exponent. /// /// IE, a base of 2 means we have `mantissa * 2^exponent`. /// If not provided, it defaults to `radix`. #[inline(always)] pub const fn exponent_base(&self) -> u32 { Self::EXPONENT_BASE } /// The radix for the exponent digits. pub const EXPONENT_RADIX: u32 = flags::exponent_radix(FORMAT); /// Get the radix for the exponent digits. #[inline(always)] pub const fn exponent_radix(&self) -> u32 { Self::EXPONENT_RADIX } // FLAGS /// Get the flags from the number format. #[inline(always)] pub const fn flags(&self) -> u128 { FORMAT & flags::FLAG_MASK } /// Get the interface flags from the number format. #[inline(always)] pub const fn interface_flags(&self) -> u128 { FORMAT & flags::INTERFACE_FLAG_MASK } /// Get the digit separator flags from the number format. #[inline(always)] pub const fn digit_separator_flags(&self) -> u128 { FORMAT & flags::DIGIT_SEPARATOR_FLAG_MASK } /// Get the exponent flags from the number format. #[inline(always)] pub const fn exponent_flags(&self) -> u128 { FORMAT & flags::EXPONENT_FLAG_MASK } /// Get the integer digit separator flags from the number format. #[inline(always)] pub const fn integer_digit_separator_flags(&self) -> u128 { FORMAT & flags::INTEGER_DIGIT_SEPARATOR_FLAG_MASK } /// Get the fraction digit separator flags from the number format. #[inline(always)] pub const fn fraction_digit_separator_flags(&self) -> u128 { FORMAT & flags::FRACTION_DIGIT_SEPARATOR_FLAG_MASK } /// Get the exponent digit separator flags from the number format. #[inline(always)] pub const fn exponent_digit_separator_flags(&self) -> u128 { FORMAT & flags::EXPONENT_DIGIT_SEPARATOR_FLAG_MASK } // BUILDER /// Get the number format builder from the format. #[inline] pub const fn builder() -> NumberFormatBuilder { NumberFormatBuilder::new() } /// Get the number format builder from the format. #[inline] pub const fn rebuild() -> NumberFormatBuilder { NumberFormatBuilder::rebuild(FORMAT) } } lexical-util-0.8.5/src/num.rs000064400000000000000000001107010072674642500142160ustar 00000000000000//! Utilities for Rust numbers. //! //! These traits define useful properties, methods, associated //! types, and trait bounds, and conversions for working with //! numbers in generic code. #[cfg(feature = "f16")] use crate::bf16::bf16; #[cfg(feature = "f16")] use crate::f16::f16; use core::{fmt, mem, ops}; // AS PRIMITIVE // ------------ /// Type that can be converted to primitive with `as`. pub trait AsPrimitive: Copy + PartialEq + PartialOrd + Send + Sync + Sized { fn as_u8(self) -> u8; fn as_u16(self) -> u16; fn as_u32(self) -> u32; fn as_u64(self) -> u64; fn as_u128(self) -> u128; fn as_usize(self) -> usize; fn as_i8(self) -> i8; fn as_i16(self) -> i16; fn as_i32(self) -> i32; fn as_i64(self) -> i64; fn as_i128(self) -> i128; fn as_isize(self) -> isize; fn as_f32(self) -> f32; fn as_f64(self) -> f64; fn from_u32(value: u32) -> Self; #[cfg(feature = "f16")] fn as_f16(self) -> f16; #[cfg(feature = "f16")] fn as_bf16(self) -> bf16; } macro_rules! as_primitive { ($($t:ty)*) => ($( impl AsPrimitive for $t { #[inline(always)] fn as_u8(self) -> u8 { self as _ } #[inline(always)] fn as_u16(self) -> u16 { self as _ } #[inline(always)] fn as_u32(self) -> u32 { self as _ } #[inline(always)] fn as_u64(self) -> u64 { self as _ } #[inline(always)] fn as_u128(self) -> u128 { self as _ } #[inline(always)] fn as_usize(self) -> usize { self as _ } #[inline(always)] fn as_i8(self) -> i8 { self as _ } #[inline(always)] fn as_i16(self) -> i16 { self as _ } #[inline(always)] fn as_i32(self) -> i32 { self as _ } #[inline(always)] fn as_i64(self) -> i64 { self as _ } #[inline(always)] fn as_i128(self) -> i128 { self as _ } #[inline(always)] fn as_isize(self) -> isize { self as _ } #[inline(always)] fn as_f32(self) -> f32 { self as _ } #[inline(always)] fn as_f64(self) -> f64 { self as _ } #[inline(always)] fn from_u32(value: u32) -> Self { value as _ } #[cfg(feature = "f16")] #[inline(always)] fn as_f16(self) -> f16 { f16::from_f32(self as f32) } #[cfg(feature = "f16")] #[inline(always)] fn as_bf16(self) -> bf16 { bf16::from_f32(self as f32) } } )*) } as_primitive! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize f32 f64 } #[cfg(feature = "f16")] macro_rules! half_as_primitive { ($($t:ty)*) => ($( impl AsPrimitive for $t { #[inline(always)] fn as_u8(self) -> u8 { self.as_f32() as _ } #[inline(always)] fn as_u16(self) -> u16 { self.as_f32() as _ } #[inline(always)] fn as_u32(self) -> u32 { self.as_f32() as _ } #[inline(always)] fn as_u64(self) -> u64 { self.as_f32() as _ } #[inline(always)] fn as_u128(self) -> u128 { self.as_f32() as _ } #[inline(always)] fn as_usize(self) -> usize { self.as_f32() as _ } #[inline(always)] fn as_i8(self) -> i8 { self.as_f32() as _ } #[inline(always)] fn as_i16(self) -> i16 { self.as_f32() as _ } #[inline(always)] fn as_i32(self) -> i32 { self.as_f32() as _ } #[inline(always)] fn as_i64(self) -> i64 { self.as_f32() as _ } #[inline(always)] fn as_i128(self) -> i128 { self.as_f32() as _ } #[inline(always)] fn as_isize(self) -> isize { self.as_f32() as _ } #[inline(always)] fn as_f32(self) -> f32 { self.as_f32() as _ } #[inline(always)] fn as_f64(self) -> f64 { self.as_f32() as _ } #[inline(always)] fn from_u32(value: u32) -> Self { Self::from_f32(value as _) } #[inline(always)] fn as_f16(self) -> f16 { f16::from_f32(self.as_f32()) } #[inline(always)] fn as_bf16(self) -> bf16 { bf16::from_f32(self.as_f32()) } } )*) } #[cfg(feature = "f16")] half_as_primitive! { f16 bf16 } // AS CAST // ------- /// An interface for casting between machine scalars. pub trait AsCast: AsPrimitive { /// Creates a number from another value that can be converted into /// a primitive via the `AsPrimitive` trait. fn as_cast(n: N) -> Self; } /// Allows the high-level conversion of generic types as if `as` was used. #[inline] pub fn as_cast(t: T) -> U { U::as_cast(t) } macro_rules! as_cast { ($($t:ty, $meth:ident ; )*) => ($( impl AsCast for $t { #[inline] fn as_cast(n: N) -> $t { n.$meth() as _ } } )*); } as_cast!( u8, as_u8 ; u16, as_u16 ; u32, as_u32 ; u64, as_u64 ; u128, as_u128 ; usize, as_usize ; i8, as_i8 ; i16, as_i16 ; i32, as_i32 ; i64, as_i64 ; i128, as_i128 ; isize, as_isize ; f32, as_f32 ; f64, as_f64 ; ); #[cfg(feature = "f16")] as_cast!( f16, as_f16 ; bf16, as_bf16 ; ); // PRIMITIVE // --------- /// Primitive type trait (which all have static lifetimes). pub trait Primitive: 'static + fmt::Debug + fmt::Display + AsCast {} macro_rules! primitive { ($($t:ty)*) => ($( impl Primitive for $t {} )*) } primitive! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize f32 f64 } #[cfg(feature = "f16")] primitive! { f16 bf16 } // NUMBER // ------ /// Numerical type trait. pub trait Number: Default + Primitive + // Operations ops::Add + ops::AddAssign + ops::Div + ops::DivAssign + ops::Mul + ops::MulAssign + ops::Rem + ops::RemAssign + ops::Sub + ops::SubAssign { /// If the number is a signed type. const IS_SIGNED: bool; } macro_rules! number_impl { ($($t:tt $is_signed:literal ; )*) => ($( impl Number for $t { const IS_SIGNED: bool = $is_signed; } )*) } number_impl! { u8 false ; u16 false ; u32 false ; u64 false ; u128 false ; usize false ; i8 true ; i16 true ; i32 true ; i64 true ; i128 true ; isize true ; f32 true ; f64 true ; // f128 true } #[cfg(feature = "f16")] number_impl! { f16 true ; bf16 true ; } // INTEGER // ------- /// Defines a trait that supports integral operations. pub trait Integer: // Basic Number + Eq + Ord + // Operations ops::BitAnd + ops::BitAndAssign + ops::BitOr + ops::BitOrAssign + ops::BitXor + ops::BitXorAssign + ops::Not + ops::Shl + ops::Shl + ops::ShlAssign + ops::Shr + ops::ShrAssign + { // CONSTANTS const ZERO: Self; const ONE: Self; const TWO: Self; const MAX: Self; const MIN: Self; const BITS: usize; // FUNCTIONS (INHERITED) fn leading_zeros(self) -> u32; fn trailing_zeros(self) -> u32; fn pow(self, exp: u32) -> Self; fn checked_add(self, i: Self) -> Option; fn checked_sub(self, i: Self) -> Option; fn checked_mul(self, i: Self) -> Option; fn overflowing_add(self, i: Self) -> (Self, bool); fn overflowing_mul(self, i: Self) -> (Self, bool); fn wrapping_add(self, i: Self) -> Self; fn wrapping_sub(self, i: Self) -> Self; fn wrapping_mul(self, i: Self) -> Self; fn wrapping_neg(self) -> Self; fn saturating_add(self, i: Self) -> Self; fn saturating_sub(self, i: Self) -> Self; fn saturating_mul(self, i: Self) -> Self; /// Get the fast ceiling of the quotient from integer division. /// Not safe, since the remainder can easily overflow. #[inline] fn ceil_divmod(self, y: Self) -> (Self, i32) { let q = self / y; let r = self % y; match r == Self::ZERO { true => (q, i32::as_cast(r)), false => (q + Self::ONE, i32::as_cast(r) - i32::as_cast(y)) } } /// Get the fast ceiling of the quotient from integer division. /// Not safe, since the remainder can easily overflow. #[inline] fn ceil_div(self, y: Self) -> Self { self.ceil_divmod(y).0 } /// Get the fast ceiling modulus from integer division. /// Not safe, since the remainder can easily overflow. #[inline] fn ceil_mod(self, y: Self) -> i32 { self.ceil_divmod(y).1 } // PROPERTIES /// Get the number of bits in a value. #[inline] fn bit_length(self) -> u32 { Self::BITS as u32 - self.leading_zeros() } /// Returns true if the least-significant bit is odd. #[inline] fn is_odd(self) -> bool { self & Self::ONE == Self::ONE } /// Returns true if the least-significant bit is even. #[inline] fn is_even(self) -> bool { !self.is_odd() } } macro_rules! integer_impl { ($($t:tt)*) => ($( impl Integer for $t { const ZERO: $t = 0; const ONE: $t = 1; const TWO: $t = 2; const MAX: $t = $t::max_value(); const MIN: $t = $t::min_value(); // DEPRECATE: when we drop support for <= 1.53.0, change to `<$t>::BITS` const BITS: usize = mem::size_of::<$t>() * 8; #[inline] fn leading_zeros(self) -> u32 { $t::leading_zeros(self) } #[inline] fn trailing_zeros(self) -> u32 { $t::trailing_zeros(self) } #[inline] fn checked_add(self, i: Self) -> Option { $t::checked_add(self, i) } #[inline] fn checked_sub(self, i: Self) -> Option { $t::checked_sub(self, i) } #[inline] fn checked_mul(self, i: Self) -> Option { $t::checked_mul(self, i) } #[inline] fn overflowing_add(self, i: Self) -> (Self, bool) { $t::overflowing_add(self, i) } #[inline] fn overflowing_mul(self, i: Self) -> (Self, bool) { $t::overflowing_mul(self, i) } #[inline] fn wrapping_add(self, i: Self) -> Self { $t::wrapping_add(self, i) } #[inline] fn wrapping_sub(self, i: Self) -> Self { $t::wrapping_sub(self, i) } #[inline] fn wrapping_mul(self, i: Self) -> Self { $t::wrapping_mul(self, i) } #[inline] fn wrapping_neg(self) -> Self { $t::wrapping_neg(self) } #[inline] fn pow(self, exp: u32) -> Self { Self::pow(self, exp) } #[inline] fn saturating_add(self, i: Self) -> Self { $t::saturating_add(self, i) } #[inline] fn saturating_sub(self, i: Self) -> Self { $t::saturating_sub(self, i) } #[inline] fn saturating_mul(self, i: Self) -> Self { $t::saturating_mul(self, i) } } )*) } integer_impl! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } // SIGNED INTEGER // -------------- /// Defines a trait that supports signed integral operations. pub trait SignedInteger: Integer + ops::Neg {} macro_rules! signed_integer_impl { ($($t:tt)*) => ($( impl SignedInteger for $t {} )*) } signed_integer_impl! { i8 i16 i32 i64 i128 isize } // UNSIGNED INTEGER // ---------------- /// Defines a trait that supports unsigned integral operations. pub trait UnsignedInteger: Integer {} macro_rules! unsigned_integer_impl { ($($t:ty)*) => ($( impl UnsignedInteger for $t {} )*) } unsigned_integer_impl! { u8 u16 u32 u64 u128 usize } // FLOAT // ----- /// Float information for native float types. #[cfg(feature = "floats")] pub trait Float: Number + ops::Neg { /// Unsigned type of the same size. type Unsigned: UnsignedInteger; // CONSTANTS const ZERO: Self; const ONE: Self; const TWO: Self; const MAX: Self; const MIN: Self; const INFINITY: Self; const NEG_INFINITY: Self; const NAN: Self; const BITS: usize; /// Bitmask for the sign bit. const SIGN_MASK: Self::Unsigned; /// Bitmask for the exponent, including the hidden bit. const EXPONENT_MASK: Self::Unsigned; /// Bitmask for the hidden bit in exponent, which is an implicit 1 in the fraction. const HIDDEN_BIT_MASK: Self::Unsigned; /// Bitmask for the mantissa (fraction), excluding the hidden bit. const MANTISSA_MASK: Self::Unsigned; /// Mask to determine if a full-carry occurred (1 in bit above hidden bit). const CARRY_MASK: Self::Unsigned; // PROPERTIES // The following constants can be calculated as follows: // - `INFINITY_BITS`: EXPONENT_MASK // - `NEGATIVE_INFINITY_BITS`: INFINITY_BITS | SIGN_MASK // - `EXPONENT_BIAS`: `2^(EXPONENT_SIZE-1) - 1 + MANTISSA_SIZE` // - `DENORMAL_EXPONENT`: `1 - EXPONENT_BIAS` // - `MAX_EXPONENT`: `2^EXPONENT_SIZE - 1 - EXPONENT_BIAS` /// Positive infinity as bits. const INFINITY_BITS: Self::Unsigned; /// Positive infinity as bits. const NEGATIVE_INFINITY_BITS: Self::Unsigned; /// Size of the exponent. const EXPONENT_SIZE: i32; /// Size of the significand (mantissa) without hidden bit. const MANTISSA_SIZE: i32; /// Bias of the exponent. const EXPONENT_BIAS: i32; /// Exponent portion of a denormal float. const DENORMAL_EXPONENT: i32; /// Maximum exponent value in float. const MAX_EXPONENT: i32; // FUNCTIONS (INHERITED) // Re-export the to and from bits methods. fn to_bits(self) -> Self::Unsigned; fn from_bits(u: Self::Unsigned) -> Self; fn ln(self) -> Self; fn floor(self) -> Self; fn is_sign_positive(self) -> bool; fn is_sign_negative(self) -> bool; /// Returns true if the float is a denormal. #[inline] fn is_denormal(self) -> bool { self.to_bits() & Self::EXPONENT_MASK == Self::Unsigned::ZERO } /// Returns true if the float is a NaN or Infinite. #[inline] fn is_special(self) -> bool { self.to_bits() & Self::EXPONENT_MASK == Self::EXPONENT_MASK } /// Returns true if the float is NaN. #[inline] fn is_nan(self) -> bool { self.is_special() && (self.to_bits() & Self::MANTISSA_MASK) != Self::Unsigned::ZERO } /// Returns true if the float is infinite. #[inline] fn is_inf(self) -> bool { self.is_special() && (self.to_bits() & Self::MANTISSA_MASK) == Self::Unsigned::ZERO } /// Returns true if the float's least-significant mantissa bit is odd. #[inline] fn is_odd(self) -> bool { self.to_bits().is_odd() } /// Returns true if the float's least-significant mantissa bit is even. #[inline] fn is_even(self) -> bool { !self.is_odd() } /// Get exponent component from the float. #[inline] fn exponent(self) -> i32 { if self.is_denormal() { return Self::DENORMAL_EXPONENT; } let bits = self.to_bits(); let biased_e = i32::as_cast((bits & Self::EXPONENT_MASK) >> Self::MANTISSA_SIZE).as_i32(); biased_e - Self::EXPONENT_BIAS } /// Get mantissa (significand) component from float. #[inline] fn mantissa(self) -> Self::Unsigned { let bits = self.to_bits(); let s = bits & Self::MANTISSA_MASK; if !self.is_denormal() { s + Self::HIDDEN_BIT_MASK } else { s } } /// Get next greater float. #[inline] fn next(self) -> Self { let bits = self.to_bits(); if self.is_sign_negative() && self == Self::ZERO { // -0.0 Self::ZERO } else if bits == Self::INFINITY_BITS { Self::from_bits(Self::INFINITY_BITS) } else if self.is_sign_negative() { Self::from_bits(bits.saturating_sub(Self::Unsigned::ONE)) } else { Self::from_bits(bits.saturating_add(Self::Unsigned::ONE)) } } /// Get next greater float for a positive float. /// Value must be >= 0.0 and < INFINITY. #[inline] fn next_positive(self) -> Self { debug_assert!(self.is_sign_positive() && !self.is_inf()); Self::from_bits(self.to_bits() + Self::Unsigned::ONE) } /// Get previous greater float, such that `self.prev().next() == self`. #[inline] fn prev(self) -> Self { let bits = self.to_bits(); if self.is_sign_positive() && self == Self::ZERO { // +0.0 -Self::ZERO } else if bits == Self::NEGATIVE_INFINITY_BITS { Self::from_bits(Self::NEGATIVE_INFINITY_BITS) } else if self.is_sign_negative() { Self::from_bits(bits.saturating_add(Self::Unsigned::ONE)) } else { Self::from_bits(bits.saturating_sub(Self::Unsigned::ONE)) } } /// Get previous greater float for a positive float. /// Value must be > 0.0. #[inline] fn prev_positive(self) -> Self { debug_assert!(self.is_sign_positive() && self != Self::ZERO); Self::from_bits(self.to_bits() - Self::Unsigned::ONE) } /// Round a positive number to even. #[inline] fn round_positive_even(self) -> Self { if self.mantissa().is_odd() { self.next_positive() } else { self } } /// Get the max of two finite numbers. #[inline] fn max_finite(self, f: Self) -> Self { debug_assert!(!self.is_special() && !f.is_special(), "max_finite self={} f={}", self, f); if self < f { f } else { self } } /// Get the min of two finite numbers. #[inline] fn min_finite(self, f: Self) -> Self { debug_assert!(!self.is_special() && !f.is_special(), "min_finite self={} f={}", self, f); if self < f { self } else { f } } } /// Define the float literals. #[cfg(feature = "floats")] macro_rules! float_literals { ($float:ty) => { const ZERO: $float = 0.0; const ONE: $float = 1.0; const TWO: $float = 2.0; const MAX: $float = <$float>::MAX; const MIN: $float = <$float>::MIN; const INFINITY: $float = <$float>::INFINITY; const NEG_INFINITY: $float = <$float>::NEG_INFINITY; const NAN: $float = <$float>::NAN; const BITS: usize = mem::size_of::<$float>() * 8; }; } /// Define the float masks. #[cfg(feature = "floats")] macro_rules! float_masks { ( float => $float:ty,sign_mask => $sign:literal,exponent_mask => $exponent:literal,hidden_bit_mask => $hidden:literal,mantissa_mask => $mantissa:literal, ) => { const SIGN_MASK: <$float>::Unsigned = $sign; const EXPONENT_MASK: <$float>::Unsigned = $exponent; const HIDDEN_BIT_MASK: <$float>::Unsigned = $hidden; const MANTISSA_MASK: <$float>::Unsigned = $mantissa; // The carry mask is always 1 bit above the hidden bit. const CARRY_MASK: <$float>::Unsigned = $hidden << 1; // Infinity is always every exponent bit set. const INFINITY_BITS: <$float>::Unsigned = $exponent; // Negative infinity is just infinity + sign. const NEGATIVE_INFINITY_BITS: <$float>::Unsigned = $exponent | $sign; }; } // Due to missing specifics or types for the following float types, // `Float` is not yet fully implemented for: // - f128 #[cfg(feature = "f16")] macro_rules! float_one { ($f:ident) => { (($f::EXPONENT_BIAS - $f::MANTISSA_SIZE) as u16) << $f::MANTISSA_SIZE }; } #[cfg(feature = "f16")] macro_rules! float_two { ($f:ident) => { (($f::EXPONENT_BIAS - $f::MANTISSA_SIZE + 1) as u16) << $f::MANTISSA_SIZE }; } #[cfg(feature = "f16")] macro_rules! float_max { ($f:ident) => { ($f::EXPONENT_MASK ^ $f::HIDDEN_BIT_MASK) | $f::MANTISSA_MASK }; } #[cfg(feature = "f16")] macro_rules! float_min { ($f:ident) => { $f::MAX.to_bits() | $f::SIGN_MASK }; } #[cfg(feature = "f16")] macro_rules! float_nan { ($f:ident) => { $f::EXPONENT_MASK | ($f::HIDDEN_BIT_MASK >> 1) }; } #[cfg(feature = "f16")] impl Float for f16 { type Unsigned = u16; const ZERO: Self = Self::from_bits(0); const ONE: Self = Self::from_bits(float_one!(Self)); const TWO: Self = Self::from_bits(float_two!(Self)); const MAX: Self = Self::from_bits(float_max!(Self)); const MIN: Self = Self::from_bits(float_min!(Self)); const INFINITY: Self = Self::from_bits(Self::INFINITY_BITS); const NEG_INFINITY: Self = Self::from_bits(Self::NEGATIVE_INFINITY_BITS); const NAN: Self = Self::from_bits(float_nan!(Self)); const BITS: usize = mem::size_of::() * 8; float_masks!( float => Self, sign_mask => 0x8000, exponent_mask => 0x7C00, hidden_bit_mask => 0x0400, mantissa_mask => 0x03FF, ); const EXPONENT_SIZE: i32 = 5; const MANTISSA_SIZE: i32 = 10; const EXPONENT_BIAS: i32 = 15 + Self::MANTISSA_SIZE; const DENORMAL_EXPONENT: i32 = 1 - Self::EXPONENT_BIAS; const MAX_EXPONENT: i32 = 0x1F - Self::EXPONENT_BIAS; #[inline] fn to_bits(self) -> u16 { f16::to_bits(self) } #[inline] fn from_bits(u: u16) -> f16 { f16::from_bits(u) } #[inline] fn ln(self) -> f16 { f16::from_f32(self.as_f32().ln()) } #[inline] fn floor(self) -> f16 { f16::from_f32(self.as_f32().floor()) } #[inline] fn is_sign_positive(self) -> bool { self.to_bits() & Self::SIGN_MASK == 0 } #[inline] fn is_sign_negative(self) -> bool { !self.is_sign_positive() } } #[cfg(feature = "f16")] impl Float for bf16 { type Unsigned = u16; const ZERO: Self = Self::from_bits(0); const ONE: Self = Self::from_bits(float_one!(Self)); const TWO: Self = Self::from_bits(float_two!(Self)); const MAX: Self = Self::from_bits(float_max!(Self)); const MIN: Self = Self::from_bits(float_min!(Self)); const INFINITY: Self = Self::from_bits(Self::INFINITY_BITS); const NEG_INFINITY: Self = Self::from_bits(Self::NEGATIVE_INFINITY_BITS); const NAN: Self = Self::from_bits(float_nan!(Self)); const BITS: usize = mem::size_of::() * 8; float_masks!( float => Self, sign_mask => 0x8000, exponent_mask => 0x7F80, hidden_bit_mask => 0x0080, mantissa_mask => 0x007F, ); const EXPONENT_SIZE: i32 = 8; const MANTISSA_SIZE: i32 = 7; const EXPONENT_BIAS: i32 = 127 + Self::MANTISSA_SIZE; const DENORMAL_EXPONENT: i32 = 1 - Self::EXPONENT_BIAS; const MAX_EXPONENT: i32 = 0xFF - Self::EXPONENT_BIAS; #[inline] fn to_bits(self) -> u16 { bf16::to_bits(self) } #[inline] fn from_bits(u: u16) -> bf16 { bf16::from_bits(u) } #[inline] fn ln(self) -> bf16 { bf16::from_f32(self.as_f32().ln()) } #[inline] fn floor(self) -> bf16 { bf16::from_f32(self.as_f32().floor()) } #[inline] fn is_sign_positive(self) -> bool { self.to_bits() & Self::SIGN_MASK == 0 } #[inline] fn is_sign_negative(self) -> bool { !self.is_sign_positive() } } #[cfg(feature = "floats")] impl Float for f32 { type Unsigned = u32; float_literals!(f32); float_masks!( float => Self, sign_mask => 0x80000000, exponent_mask => 0x7F800000, hidden_bit_mask => 0x00800000, mantissa_mask => 0x007FFFFF, ); const EXPONENT_SIZE: i32 = 8; const MANTISSA_SIZE: i32 = 23; const EXPONENT_BIAS: i32 = 127 + Self::MANTISSA_SIZE; const DENORMAL_EXPONENT: i32 = 1 - Self::EXPONENT_BIAS; const MAX_EXPONENT: i32 = 0xFF - Self::EXPONENT_BIAS; #[inline] fn to_bits(self) -> u32 { f32::to_bits(self) } #[inline] fn from_bits(u: u32) -> f32 { f32::from_bits(u) } #[inline] fn ln(self) -> f32 { #[cfg(feature = "std")] return f32::ln(self); #[cfg(not(feature = "std"))] return logf(self); } #[inline] fn floor(self) -> f32 { #[cfg(feature = "std")] return f32::floor(self); #[cfg(not(feature = "std"))] return floorf(self); } #[inline] fn is_sign_positive(self) -> bool { f32::is_sign_positive(self) } #[inline] fn is_sign_negative(self) -> bool { f32::is_sign_negative(self) } } #[cfg(feature = "floats")] impl Float for f64 { type Unsigned = u64; float_literals!(f64); float_masks!( float => Self, sign_mask => 0x8000000000000000, exponent_mask => 0x7FF0000000000000, hidden_bit_mask => 0x0010000000000000, mantissa_mask => 0x000FFFFFFFFFFFFF, ); const EXPONENT_SIZE: i32 = 11; const MANTISSA_SIZE: i32 = 52; const EXPONENT_BIAS: i32 = 1023 + Self::MANTISSA_SIZE; const DENORMAL_EXPONENT: i32 = 1 - Self::EXPONENT_BIAS; const MAX_EXPONENT: i32 = 0x7FF - Self::EXPONENT_BIAS; #[inline] fn to_bits(self) -> u64 { f64::to_bits(self) } #[inline] fn from_bits(u: u64) -> f64 { f64::from_bits(u) } #[inline] fn ln(self) -> f64 { #[cfg(feature = "std")] return f64::ln(self); #[cfg(not(feature = "std"))] return logd(self); } #[inline] fn floor(self) -> f64 { #[cfg(feature = "std")] return f64::floor(self); #[cfg(not(feature = "std"))] return floord(self); } #[inline] fn is_sign_positive(self) -> bool { f64::is_sign_positive(self) } #[inline] fn is_sign_negative(self) -> bool { f64::is_sign_negative(self) } } // #[cfg(feature = "f128")] // impl Float for f128 { // type Unsigned = u128; // float_literals!(f128); // float_masks!( // float => Self, // sign_mask => 0x80000000000000000000000000000000, // exponent_mask => 0x7FFF0000000000000000000000000000, // hidden_bit_mask => 0x00010000000000000000000000000000, // mantissa_mask => 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF, // ); // const EXPONENT_SIZE: i32 = 15; // const MANTISSA_SIZE: i32 = 112; // const EXPONENT_BIAS: i32 = 16383 + Self::MANTISSA_SIZE; // const DENORMAL_EXPONENT: i32 = 1 - Self::EXPONENT_BIAS; // const MAX_EXPONENT: i32 = 0x7FFF - Self::EXPONENT_BIAS; // } // FLOAT HELPERS // ------------- // These are adapted from libm, a port of musl libc's libm to Rust. // libm can be found online [here](https://github.com/rust-lang/libm), // and is similarly licensed under an Apache2.0/MIT license /// # Safety /// /// Safe as long as `e` is properly initialized. #[cfg(all(not(feature = "std"), feature = "floats"))] macro_rules! volatile { ($e:expr) => { // SAFETY: safe as long as `$e` has been properly initialized. unsafe { core::ptr::read_volatile(&$e); } }; } /// Floor (f64) /// /// Finds the nearest integer less than or equal to `x`. #[cfg(all(not(feature = "std"), feature = "floats"))] fn floord(x: f64) -> f64 { const TOINT: f64 = 1. / f64::EPSILON; let ui = x.to_bits(); let e = ((ui >> 52) & 0x7ff) as i32; if (e >= 0x3ff + 52) || (x == 0.) { return x; } /* y = int(x) - x, where int(x) is an integer neighbor of x */ let y = if (ui >> 63) != 0 { x - TOINT + TOINT - x } else { x + TOINT - TOINT - x }; /* special case because of non-nearest rounding modes */ if e < 0x3ff { volatile!(y); return if (ui >> 63) != 0 { -1. } else { 0. }; } if y > 0. { x + y - 1. } else { x + y } } /// Floor (f32) /// /// Finds the nearest integer less than or equal to `x`. #[cfg(all(not(feature = "std"), feature = "floats"))] fn floorf(x: f32) -> f32 { let mut ui = x.to_bits(); let e = (((ui >> 23) as i32) & 0xff) - 0x7f; if e >= 23 { return x; } if e >= 0 { let m: u32 = 0x007fffff >> e; if (ui & m) == 0 { return x; } volatile!(x + f32::from_bits(0x7b800000)); if ui >> 31 != 0 { ui += m; } ui &= !m; } else { volatile!(x + f32::from_bits(0x7b800000)); if ui >> 31 == 0 { ui = 0; } else if ui << 1 != 0 { return -1.0; } } f32::from_bits(ui) } /* origin: FreeBSD /usr/src/lib/msun/src/e_log.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* log(x) * Return the logarithm of x * * Method : * 1. Argument Reduction: find k and f such that * x = 2^k * (1+f), * where sqrt(2)/2 < 1+f < sqrt(2) . * * 2. Approximation of log(1+f). * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) * = 2s + 2/3 s**3 + 2/5 s**5 + ....., * = 2s + s*R * We use a special Remez algorithm on [0,0.1716] to generate * a polynomial of degree 14 to approximate R The maximum error * of this polynomial approximation is bounded by 2**-58.45. In * other words, * 2 4 6 8 10 12 14 * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s * (the values of Lg1 to Lg7 are listed in the program) * and * | 2 14 | -58.45 * | Lg1*s +...+Lg7*s - R(z) | <= 2 * | | * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. * In order to guarantee error in log below 1ulp, we compute log * by * log(1+f) = f - s*(f - R) (if f is not too large) * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) * * 3. Finally, log(x) = k*ln2 + log(1+f). * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) * Here ln2 is split into two floating point number: * ln2_hi + ln2_lo, * where n*ln2_hi is always exact for |n| < 2000. * * Special cases: * log(x) is NaN with signal if x < 0 (including -INF) ; * log(+INF) is +INF; log(0) is -INF with signal; * log(NaN) is that NaN with no signal. * * Accuracy: * according to an error analysis, the error is always less than * 1 ulp (unit in the last place). * * Constants: * The hexadecimal values are the intended ones for the following * constants. The decimal values may be used, provided that the * compiler will convert from decimal to binary accurately enough * to produce the hexadecimal values shown. */ #[allow(clippy::eq_op, clippy::excessive_precision)] #[cfg(all(not(feature = "std"), feature = "floats"))] fn logd(mut x: f64) -> f64 { const LN2_HI: f64 = 6.93147180369123816490e-01; /* 3fe62e42 fee00000 */ const LN2_LO: f64 = 1.90821492927058770002e-10; /* 3dea39ef 35793c76 */ const LG1: f64 = 6.666666666666735130e-01; /* 3FE55555 55555593 */ const LG2: f64 = 3.999999999940941908e-01; /* 3FD99999 9997FA04 */ const LG3: f64 = 2.857142874366239149e-01; /* 3FD24924 94229359 */ const LG4: f64 = 2.222219843214978396e-01; /* 3FCC71C5 1D8E78AF */ const LG5: f64 = 1.818357216161805012e-01; /* 3FC74664 96CB03DE */ const LG6: f64 = 1.531383769920937332e-01; /* 3FC39A09 D078C69F */ const LG7: f64 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ let x1p54 = f64::from_bits(0x4350000000000000); // 0x1p54 === 2 ^ 54 let mut ui = x.to_bits(); let mut hx: u32 = (ui >> 32) as u32; let mut k: i32 = 0; if (hx < 0x00100000) || ((hx >> 31) != 0) { /* x < 2**-126 */ if ui << 1 == 0 { return -1. / (x * x); /* log(+-0)=-inf */ } if hx >> 31 != 0 { return (x - x) / 0.0; /* log(-#) = NaN */ } /* subnormal number, scale x up */ k -= 54; x *= x1p54; ui = x.to_bits(); hx = (ui >> 32) as u32; } else if hx >= 0x7ff00000 { return x; } else if hx == 0x3ff00000 && ui << 32 == 0 { return 0.; } /* reduce x into [sqrt(2)/2, sqrt(2)] */ hx += 0x3ff00000 - 0x3fe6a09e; k += ((hx >> 20) as i32) - 0x3ff; hx = (hx & 0x000fffff) + 0x3fe6a09e; ui = ((hx as u64) << 32) | (ui & 0xffffffff); x = f64::from_bits(ui); let f: f64 = x - 1.0; let hfsq: f64 = 0.5 * f * f; let s: f64 = f / (2.0 + f); let z: f64 = s * s; let w: f64 = z * z; let t1: f64 = w * (LG2 + w * (LG4 + w * LG6)); let t2: f64 = z * (LG1 + w * (LG3 + w * (LG5 + w * LG7))); let r: f64 = t2 + t1; let dk: f64 = k as f64; s * (hfsq + r) + dk * LN2_LO - hfsq + f + dk * LN2_HI } /* origin: FreeBSD /usr/src/lib/msun/src/e_logf.c */ /* * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #[allow(clippy::eq_op, clippy::excessive_precision)] #[cfg(all(not(feature = "std"), feature = "floats"))] fn logf(mut x: f32) -> f32 { const LN2_HI: f32 = 6.9313812256e-01; /* 0x3f317180 */ const LN2_LO: f32 = 9.0580006145e-06; /* 0x3717f7d1 */ /* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ const LG1: f32 = 0.66666662693; /* 0xaaaaaa.0p-24*/ const LG2: f32 = 0.40000972152; /* 0xccce13.0p-25 */ const LG3: f32 = 0.28498786688; /* 0x91e9ee.0p-25 */ const LG4: f32 = 0.24279078841; /* 0xf89e26.0p-26 */ let x1p25 = f32::from_bits(0x4c000000); // 0x1p25f === 2 ^ 25 let mut ix = x.to_bits(); let mut k = 0i32; if (ix < 0x00800000) || ((ix >> 31) != 0) { /* x < 2**-126 */ if ix << 1 == 0 { return -1. / (x * x); /* log(+-0)=-inf */ } if (ix >> 31) != 0 { return (x - x) / 0.; /* log(-#) = NaN */ } /* subnormal number, scale up x */ k -= 25; x *= x1p25; ix = x.to_bits(); } else if ix >= 0x7f800000 { return x; } else if ix == 0x3f800000 { return 0.; } /* reduce x into [sqrt(2)/2, sqrt(2)] */ ix += 0x3f800000 - 0x3f3504f3; k += ((ix >> 23) as i32) - 0x7f; ix = (ix & 0x007fffff) + 0x3f3504f3; x = f32::from_bits(ix); let f = x - 1.; let s = f / (2. + f); let z = s * s; let w = z * z; let t1 = w * (LG2 + w * LG4); let t2 = z * (LG1 + w * LG3); let r = t2 + t1; let hfsq = 0.5 * f * f; let dk = k as f32; s * (hfsq + r) + dk * LN2_LO - hfsq + f + dk * LN2_HI } lexical-util-0.8.5/src/options.rs000064400000000000000000000105430072674642500151150ustar 00000000000000//! Shared traits for the options API. #[cfg(feature = "write")] use crate::constants::FormattedSize; // TRAITS // ------ /// Shared trait for all writer options. #[cfg(feature = "write")] pub trait WriteOptions: Default { /// Determine if the options are valid. fn is_valid(&self) -> bool; /// Get an upper bound on the buffer size. fn buffer_size(&self) -> usize; } /// Shared trait for all parser options. #[cfg(feature = "parse")] pub trait ParseOptions: Default { /// Determine if the options are valid. fn is_valid(&self) -> bool; } // PRE-DEFINED CONSTANTS // --------------------- // The following constants have the following signifiers: // ${X}_LITERAL - Applies to all literal values for that language. // ${X}_STRING - Applies to all string values for that language. // ${X} - Applies to all values for that language. // ${X}_(NAN|INF|INFINITY) - Applies to only a single special value. // IF it's not defined, all values are the default. macro_rules! literal { ($name:ident, $value:ident) => { pub const $name: Option<&[u8]> = $value; }; ($name:ident, $value:literal) => { pub const $name: Option<&[u8]> = Some($value); }; } literal!(RUST_LITERAL, None); // RUST_STRING literal!(PYTHON_LITERAL, None); // PYTHON_STRING literal!(CXX_LITERAL_NAN, b"NAN"); literal!(CXX_LITERAL_INF, b"INFINITY"); literal!(CXX_LITERAL_INFINITY, b"INFINITY"); // CXX_STRING literal!(C_LITERAL_NAN, b"NAN"); literal!(C_LITERAL_INF, b"INFINITY"); literal!(C_LITERAL_INFINITY, b"INFINITY"); // C_STRING literal!(RUBY, None); literal!(SWIFT_LITERAL, None); // SWIFT_STRING literal!(GO_LITERAL, None); // GO_STRING literal!(HASKELL_LITERAL, None); literal!(HASKELL_STRING_INF, b"Infinity"); literal!(HASKELL_STRING_INFINITY, b"Infinity"); literal!(JAVASCRIPT_INF, b"Infinity"); literal!(JAVASCRIPT_INFINITY, b"Infinity"); literal!(PERL_LITERAL, None); // PERL_STRING literal!(PHP_LITERAL_NAN, b"NAN"); literal!(PHP_LITERAL_INF, b"INF"); literal!(PHP_LITERAL_INFINITY, b"INF"); // PHP_STRING literal!(JAVA_LITERAL, None); literal!(JAVA_STRING_INF, b"Infinity"); literal!(JAVA_STRING_INFINITY, b"Infinity"); literal!(R_LITERAL_INF, b"Inf"); literal!(R_LITERAL_INFINITY, b"Inf"); // R_STRING literal!(KOTLIN_LITERAL, None); literal!(KOTLIN_STRING_INF, b"Infinity"); literal!(KOTLIN_STRING_INFINITY, b"Infinity"); literal!(JULIA_LITERAL_INF, b"Inf"); literal!(JULIA_LITERAL_INFINITY, b"Inf"); // JULIA_STRING literal!(CSHARP_LITERAL, None); literal!(CSHARP_STRING_INF, b"Infinity"); literal!(CSHARP_STRING_INFINITY, b"Infinity"); literal!(KAWA, None); literal!(GAMBITC, None); literal!(GUILE, None); literal!(CLOJURE_LITERAL, None); literal!(CLOJURE_STRING_INF, b"Infinity"); literal!(CLOJURE_STRING_INFINITY, b"Infinity"); literal!(ERLANG_LITERAL_NAN, b"nan"); literal!(ERLANG_STRING, None); literal!(ELM_LITERAL, None); literal!(ELM_STRING_NAN, None); literal!(ELM_STRING_INF, b"Infinity"); literal!(ELM_STRING_INFINITY, b"Infinity"); literal!(SCALA_LITERAL, None); literal!(SCALA_STRING_INF, b"Infinity"); literal!(SCALA_STRING_INFINITY, b"Infinity"); literal!(ELIXIR, None); literal!(FORTRAN_LITERAL, None); // FORTRAN_STRING literal!(D_LITERAL, None); // D_STRING literal!(COFFEESCRIPT_INF, b"Infinity"); literal!(COFFEESCRIPT_INFINITY, b"Infinity"); literal!(COBOL, None); literal!(FSHARP_LITERAL_NAN, b"nan"); literal!(FSHARP_LITERAL_INF, b"infinity"); literal!(FSHARP_LITERAL_INFINITY, b"infinity"); // FSHARP_STRING literal!(VB_LITERAL, None); literal!(VB_STRING_INF, None); literal!(VB_STRING_INFINITY, None); literal!(OCAML_LITERAL_NAN, b"nan"); literal!(OCAML_LITERAL_INF, b"infinity"); literal!(OCAML_LITERAL_INFINITY, b"infinity"); // OCAML_STRING literal!(OBJECTIVEC, None); literal!(REASONML_LITERAL_NAN, b"nan"); literal!(REASONML_LITERAL_INF, b"infinity"); literal!(REASONML_LITERAL_INFINITY, b"infinity"); // REASONML_STRING literal!(MATLAB_LITERAL_INF, b"inf"); literal!(MATLAB_LITERAL_INFINITY, b"Inf"); // MATLAB_STRING literal!(ZIG_LITERAL, None); // ZIG_STRING literal!(SAGE_LITERAL_INF, b"infinity"); literal!(SAGE_LITERAL_INFINITY, b"Infinity"); // SAGE_STRING literal!(JSON, None); literal!(TOML, None); literal!(YAML, None); literal!(XML_INF, None); literal!(XML_INFINITY, None); literal!(SQLITE, None); literal!(POSTGRESQL, None); literal!(MYSQL, None); literal!(MONGODB_INF, b"Infinity"); literal!(MONGODB_INFINITY, b"Infinity"); lexical-util-0.8.5/src/result.rs000064400000000000000000000003010072674642500147270ustar 00000000000000//! Result type for numeric parsing functions. use crate::error; use core::result; /// A specialized Result type for lexical operations. pub type Result = result::Result; lexical-util-0.8.5/src/skip.rs000064400000000000000000000636730072674642500144040ustar 00000000000000//! An iterator that skips values equal to a provided value. //! //! Iterators over a contiguous slice, returning all values //! except for those matching the provided skip value. //! //! # Complexity //! //! Although superficially quite simple, the level of complexity //! introduced by digit separators can be quite complex, due //! the number of permutations during parsing. //! //! We can consume any combinations of of \[0,3\] items from the following set: //! - \[l\]eading digit separators, where digit separators occur before digits. //! - \[i\]nternal digit separators, where digit separators occur between digits. //! - \[t\]railing digit separators, where digit separators occur after digits. //! //! In addition to those combinations, we can also have: //! - \[c\]onsecutive digit separators, which allows two digit separators to be adjacent. //! //! # Shorthand //! //! We will use the term consumer to denote a function that consumes digits, //! splitting an input buffer at an index, where the leading section contains //! valid input digits, and the trailing section contains invalid characters. //! Due to the number of combinations for consumers, we use the following //! shorthand to denote consumers: //! - `no`, does not use a digit separator. //! - `l`, consumes leading digit separators. //! - `i`, consumes internal digit separators. //! - `t`, consumes trailing digit separators. //! - `c`, consumes consecutive digit separators. //! //! The `next`/`iter` algorithms are therefore named `next_x`, where `x` //! represents the shorthand name of the consumer, in sorted order. //! For example, `next_ilt` means that consumer can skip internal, //! leading, and trailing digit separators, but not consecutive ones. #![cfg(all(feature = "format", feature = "parse"))] use crate::digit::char_is_digit_const; use crate::format::NumberFormat; use crate::format_flags as flags; use crate::iterator::BytesIter; use core::{mem, ptr}; // PEEK // ---- /// Determine if the digit separator is internal. /// /// Preconditions: Assumes `slc[index]` is a digit separator. /// The compiler optimizes this pretty well: it's almost as efficient as /// optimized assembly without bounds checking. macro_rules! is_i { ($self:ident) => { !is_l!($self) && !is_t!($self) }; } /// Determine if the digit separator is leading. /// /// Preconditions: Assumes `slc[index]` is a digit separator. /// The compiler optimizes this pretty well: it's almost as efficient as /// optimized assembly without bounds checking. macro_rules! is_l { ($self:ident) => {{ // Consume any digit separators before the current one. let mut index = $self.byte.index; while index > 0 && $self.byte.slc.get(index - 1).map_or(false, |&x| $self.is_digit_separator(x)) { index -= 1; } // True if there are no items before the digit separator, or character // before the digit separators is not a digit. index == 0 || !$self.byte.slc.get(index - 1).map_or(false, |&x| $self.is_digit(x)) }}; } /// Determine if the digit separator is trailing. /// /// Preconditions: Assumes `slc[index]` is a digit separator. /// The compiler optimizes this pretty well: it's almost as efficient as /// optimized assembly without bounds checking. macro_rules! is_t { ($self:ident) => {{ // Consume any digit separators after the current one. let mut index = $self.byte.index; while index < $self.byte.slc.len() && $self.byte.slc.get(index + 1).map_or(false, |&x| $self.is_digit_separator(x)) { index += 1; } index == $self.byte.slc.len() || !$self.byte.slc.get(index + 1).map_or(false, |&x| $self.is_digit(x)) }}; } /// Determine if the digit separator is leading or internal. /// /// Preconditions: Assumes `slc[index]` is a digit separator. macro_rules! is_il { ($self:ident) => { is_l!($self) || !is_t!($self) }; } /// Determine if the digit separator is internal or trailing. /// /// Preconditions: Assumes `slc[index]` is a digit separator. macro_rules! is_it { ($self:ident) => { is_t!($self) || !is_l!($self) }; } /// Determine if the digit separator is leading or trailing. /// /// Preconditions: Assumes `slc[index]` is a digit separator. macro_rules! is_lt { ($self:ident) => { is_l!($self) || is_t!($self) }; } /// Determine if the digit separator is internal, leading, or trailing. macro_rules! is_ilt { ($self:ident) => { true }; } /// Consumes 1 or more digit separators. /// Peeks the next token that's not a digit separator. macro_rules! peek_1 { ($self:ident, $is_skip:ident) => {{ // This will consume consecutive digit separators. let value = $self.byte.slc.get($self.byte.index)?; let is_digit_separator = $self.is_digit_separator(*value); if is_digit_separator && $is_skip!($self) { // Have a skippable digit separator: keep incrementing until we find // a non-digit separator character. Don't need any complex checks // here, since we've already done them above. let mut index = $self.byte.index + 1; while index < $self.length() && $self.byte.slc.get(index).map_or(false, |&x| $self.is_digit_separator(x)) { index += 1; } $self.byte.index = index; $self.byte.slc.get($self.byte.index) } else { // Have 1 of 2 conditions: // 1. A non-digit separator character. // 2. A digit separator that is not valid in the context. Some(value) } }}; } /// Consumes 1 or more digit separators. /// Peeks the next token that's not a digit separator. macro_rules! peek_n { ($self:ident, $is_skip:ident) => {{ // This will consume consecutive digit separators. let value = $self.byte.slc.get($self.byte.index)?; let is_digit_separator = $self.is_digit_separator(*value); if is_digit_separator && $is_skip!($self) { // Have a skippable digit separator: keep incrementing until we find // a non-digit separator character. Don't need any complex checks // here, since we've already done them above. let mut index = $self.byte.index + 1; while index < $self.byte.slc.len() && $self.byte.slc.get(index).map_or(false, |&x| $self.is_digit_separator(x)) { index += 1; } $self.byte.index = index; $self.byte.slc.get($self.byte.index) } else { // Have 1 of 2 conditions: // 1. A non-digit separator character. // 2. A digit separator that is not valid in the context. Some(value) } }}; } /// Consumes no digit separators and peeks the next value. macro_rules! peek_noskip { ($self:ident) => { $self.byte.slc.get($self.byte.index) }; } /// Consumes at most 1 leading digit separator and peeks the next value. macro_rules! peek_l { ($self:ident) => { peek_1!($self, is_l) }; } /// Consumes at most 1 internal digit separator and peeks the next value. macro_rules! peek_i { ($self:ident) => { peek_1!($self, is_i) }; } /// Consumes at most 1 trailing digit separator and peeks the next value. macro_rules! peek_t { ($self:ident) => { peek_1!($self, is_t) }; } /// Consumes at most 1 internal/leading digit separator and peeks the next value. macro_rules! peek_il { ($self:ident) => { peek_1!($self, is_il) }; } /// Consumes at most 1 internal/trailing digit separator and peeks the next value. macro_rules! peek_it { ($self:ident) => { peek_1!($self, is_it) }; } /// Consumes at most 1 leading/trailing digit separator and peeks the next value. macro_rules! peek_lt { ($self:ident) => { peek_1!($self, is_lt) }; } /// Consumes at most 1 digit separator and peeks the next value. macro_rules! peek_ilt { ($self:ident) => { peek_1!($self, is_ilt) }; } /// Consumes 1 or more leading digit separators and peeks the next value. macro_rules! peek_lc { ($self:ident) => { peek_n!($self, is_l) }; } /// Consumes 1 or more internal digit separators and peeks the next value. macro_rules! peek_ic { ($self:ident) => { peek_n!($self, is_i) }; } /// Consumes 1 or more trailing digit separators and peeks the next value. macro_rules! peek_tc { ($self:ident) => { peek_n!($self, is_t) }; } /// Consumes 1 or more internal/leading digit separators and peeks the next value. macro_rules! peek_ilc { ($self:ident) => { peek_n!($self, is_il) }; } /// Consumes 1 or more internal/trailing digit separators and peeks the next value. macro_rules! peek_itc { ($self:ident) => { peek_n!($self, is_it) }; } /// Consumes 1 or more leading/trailing digit separators and peeks the next value. macro_rules! peek_ltc { ($self:ident) => { peek_n!($self, is_lt) }; } /// Consumes 1 or more digit separators and peeks the next value. macro_rules! peek_iltc { ($self:ident) => {{ loop { let value = $self.byte.slc.get($self.byte.index)?; if !$self.is_digit_separator(*value) { return Some(value); } $self.byte.index += 1; } }}; } // AS DIGITS // --------- /// Trait to simplify creation of a `Bytes` object. pub trait AsBytes<'a> { /// Create `Bytes` from object. fn bytes(&'a self) -> Bytes<'a, FORMAT>; } impl<'a> AsBytes<'a> for [u8] { #[inline] fn bytes(&'a self) -> Bytes<'a, FORMAT> { Bytes::new(self) } } // DIGITS // ------ /// Slice iterator that skips characters matching a given value. /// /// This wraps an iterator over a contiguous block of memory, /// and only returns values that are not equal to skip. /// /// The format allows us to dictate the actual behavior of /// the iterator: in what contexts does it skip digit separators. /// /// `FORMAT` is required to tell us what the digit separator is, and where /// the digit separators are allowed, as well tell us the radix. /// The radix is required to allow us to differentiate digit from /// non-digit characters (see [DigitSeparators](/docs/DigitSeparators.md) /// for a detailed explanation on why). #[derive(Clone)] pub struct Bytes<'a, const FORMAT: u128> { /// The raw slice for the iterator. slc: &'a [u8], /// Current index of the iterator in the slice. index: usize, /// The current count of values returned by the iterator. /// This is only used if the iterator is not contiguous. count: usize, } impl<'a, const FORMAT: u128> Bytes<'a, FORMAT> { /// If each yielded value is adjacent in memory. pub const IS_CONTIGUOUS: bool = NumberFormat::<{ FORMAT }>::DIGIT_SEPARATOR == 0; /// Create new byte object. #[inline] pub fn new(slc: &'a [u8]) -> Self { Self { slc, index: 0, count: 0, } } /// Get a ptr to the current start of the iterator. #[inline] pub fn as_ptr(&self) -> *const u8 { self.as_slice().as_ptr() } /// Get a slice to the current start of the iterator. #[inline] pub fn as_slice(&self) -> &'a [u8] { // SAFETY: safe since index must be in range unsafe { self.slc.get_unchecked(self.index..) } } /// Get the total number of elements in the underlying slice. #[inline] pub fn length(&self) -> usize { self.slc.len() } /// Get the current index of the iterator in the slice. #[inline] pub fn cursor(&self) -> usize { self.index } /// Set the current index of the iterator in the slice. /// /// # Safety /// /// Safe if `index <= self.length()`. #[inline] pub unsafe fn set_cursor(&mut self, index: usize) { debug_assert!(index <= self.length()); self.index = index } /// Get the current number of values returned by the iterator. #[inline] pub fn current_count(&self) -> usize { // If the buffer is contiguous, then we don't need to track the // number of values: the current index is enough. if Self::IS_CONTIGUOUS { self.index } else { self.count } } /// Get if the buffer underlying the iterator is empty. /// /// This might not be the same thing as `is_consumed`: `is_consumed` /// checks if any more elements may be returned, which may require /// peeking the next value. Consumed merely checks if the /// iterator has an empty slice. It is effectively a cheaper, /// but weaker variant of `is_consumed()`. #[inline] pub fn is_done(&self) -> bool { self.index >= self.slc.len() } // Determine if the abstraction is contiguous. #[inline] pub fn is_contiguous(&self) -> bool { Self::IS_CONTIGUOUS } /// Read a value of a difference type from the iterator. /// This advances the internal state of the iterator. /// /// # Safety /// /// Safe as long as the number of the buffer is contains as least as /// many bytes as the size of V. #[inline] pub unsafe fn read_unchecked(&self) -> V { debug_assert!(Self::IS_CONTIGUOUS); debug_assert!(self.as_slice().len() >= mem::size_of::()); let slc = self.as_slice(); // SAFETY: safe as long as the slice has at least count elements. unsafe { ptr::read_unaligned::(slc.as_ptr() as *const _) } } /// Try to read a value of a different type from the iterator. /// This advances the internal state of the iterator. #[inline] pub fn read(&self) -> Option { if Self::IS_CONTIGUOUS && self.as_slice().len() >= mem::size_of::() { // SAFETY: safe since we've guaranteed the buffer is greater than // the number of elements read. unsafe { Some(self.read_unchecked()) } } else { None } } /// Check if the next element is a given value. #[inline] pub fn first_is(&mut self, value: u8) -> bool { // Don't assert not a digit separator, since this can occur when // a different component does not allow digit separators there. if let Some(&c) = self.slc.get(self.index) { c == value } else { false } } /// Check if the next element is a given value without case sensitivity. #[inline] pub fn case_insensitive_first_is(&mut self, value: u8) -> bool { // Don't assert not a digit separator, since this can occur when // a different component does not allow digit separators there. if let Some(&c) = self.slc.get(self.index) { c.to_ascii_lowercase() == value.to_ascii_lowercase() } else { false } } /// Get iterator over integer digits. #[inline] pub fn integer_iter<'b>(&'b mut self) -> IntegerBytesIterator<'a, 'b, FORMAT> { IntegerBytesIterator { byte: self, } } /// Get iterator over fraction digits. #[inline] pub fn fraction_iter<'b>(&'b mut self) -> FractionBytesIterator<'a, 'b, FORMAT> { FractionBytesIterator { byte: self, } } /// Get iterator over exponent digits. #[inline] pub fn exponent_iter<'b>(&'b mut self) -> ExponentBytesIterator<'a, 'b, FORMAT> { ExponentBytesIterator { byte: self, } } /// Get iterator over special floating point values. #[inline] pub fn special_iter<'b>(&'b mut self) -> SpecialBytesIterator<'a, 'b, FORMAT> { SpecialBytesIterator { byte: self, } } /// Advance the byte by `N` elements. /// /// # Safety /// /// As long as the iterator is at least `N` elements, this /// is safe. #[inline] pub unsafe fn step_by_unchecked(&mut self, count: usize) { if Self::IS_CONTIGUOUS { // Contiguous, can skip most of these checks. debug_assert!(self.as_slice().len() >= count); } else { // Since this isn't contiguous, it only works // if the value is in the range `[0, 1]`. // We also need to make sure the **current** value // isn't a digit separator. let format = NumberFormat::<{ FORMAT }> {}; debug_assert!(self.as_slice().len() >= count); debug_assert!(count == 0 || count == 1); debug_assert!( count == 0 || self.slc.get(self.index) != Some(&format.digit_separator()) ); } self.index += count; if !Self::IS_CONTIGUOUS { // Only increment the count if it's not contiguous, otherwise, // this is an unnecessary performance penalty. self.count += count; } } /// Advance the byte by 1 element. /// /// # Safety /// /// Safe as long as the iterator is not empty. #[inline] pub unsafe fn step_unchecked(&mut self) { debug_assert!(!self.as_slice().is_empty()); // SAFETY: safe if `self.index < self.length()`. unsafe { self.step_by_unchecked(1) }; } } // ITERATOR HELPERS // ---------------- /// Create skip iterator definition. macro_rules! skip_iterator { ($iterator:ident, $doc:literal) => { #[doc = $doc] pub struct $iterator<'a: 'b, 'b, const FORMAT: u128> { /// The internal byte object for the skip iterator. byte: &'b mut Bytes<'a, FORMAT>, } }; } macro_rules! is_digit_separator { ($format:ident) => { /// Determine if the character is a digit separator. pub const fn is_digit_separator(&self, value: u8) -> bool { let format = NumberFormat::<{ $format }> {}; let digit_separator = format.digit_separator(); if digit_separator == 0 { // Check at compile time if we have an invalid digit separator. // b'\x00', or the NUL character, is this invalid value. false } else { value == digit_separator } } }; } /// Create impl block for skip iterator. macro_rules! skip_iterator_impl { ($iterator:ident, $radix_cb:ident) => { impl<'a: 'b, 'b, const FORMAT: u128> $iterator<'a, 'b, FORMAT> { is_digit_separator!(FORMAT); /// Determine if the character is a digit. pub const fn is_digit(&self, value: u8) -> bool { let format = NumberFormat::<{ FORMAT }> {}; char_is_digit_const(value, format.$radix_cb()) } } }; } /// Create impl Iterator block for skip iterator. macro_rules! skip_iterator_iterator_impl { ($iterator:ident) => { impl<'a: 'b, 'b, const FORMAT: u128> Iterator for $iterator<'a, 'b, FORMAT> { type Item = &'a u8; #[inline] fn next(&mut self) -> Option { // Peek will handle everything properly internally. let value = self.peek()?; // Increment the index so we know not to re-fetch it. self.byte.index += 1; if !Self::IS_CONTIGUOUS { // Only increment the count if it's not contiguous, otherwise, // this is an unnecessary performance penalty. self.byte.count += 1; } Some(value) } } }; } /// Create base methods for the ByteIter block of a skip iterator. macro_rules! skip_iterator_byteiter_base { ($format:ident, $mask:ident) => { // It's contiguous if we don't skip over any values. // IE, the digit separator flags for the iterator over // the digits doesn't skip any values. const IS_CONTIGUOUS: bool = $format & flags::$mask == 0; #[inline] fn as_ptr(&self) -> *const u8 { self.byte.as_ptr() } #[inline] fn as_slice(&self) -> &'a [u8] { self.byte.as_slice() } #[inline] fn length(&self) -> usize { self.byte.length() } #[inline] fn cursor(&self) -> usize { self.byte.cursor() } #[inline] unsafe fn set_cursor(&mut self, index: usize) { debug_assert!(index <= self.length()); // SAFETY: safe if `index <= self.length()`. unsafe { self.byte.set_cursor(index) }; } #[inline] fn current_count(&self) -> usize { self.byte.current_count() } #[inline] fn is_consumed(&mut self) -> bool { self.peek().is_none() } #[inline] fn is_done(&self) -> bool { self.byte.is_done() } #[inline] fn is_contiguous(&self) -> bool { Self::IS_CONTIGUOUS } #[inline] unsafe fn peek_unchecked(&mut self) -> ::Item { self.peek().unwrap() } #[inline] unsafe fn read_unchecked(&self) -> V { debug_assert!(self.as_slice().len() >= mem::size_of::()); // SAFETY: safe as long as the slice has at least count elements. unsafe { self.byte.read_unchecked() } } #[inline] fn read(&self) -> Option { self.byte.read() } #[inline] unsafe fn step_by_unchecked(&mut self, count: usize) { debug_assert!(self.as_slice().len() >= count); // SAFETY: safe as long as `slc.len() >= count`. unsafe { self.byte.step_by_unchecked(count) } } }; } /// Create impl ByteIter block for skip iterator. macro_rules! skip_iterator_byteiter_impl { ($iterator:ident, $mask:ident, $i:ident, $l:ident, $t:ident, $c:ident) => { impl<'a: 'b, 'b, const FORMAT: u128> BytesIter<'a> for $iterator<'a, 'b, FORMAT> { skip_iterator_byteiter_base!(FORMAT, $mask); /// Peek the next value of the iterator, without consuming it. #[inline] fn peek(&mut self) -> Option<::Item> { let format = NumberFormat::<{ FORMAT }> {}; const IL: u128 = flags::$i | flags::$l; const IT: u128 = flags::$i | flags::$t; const LT: u128 = flags::$l | flags::$t; const ILT: u128 = flags::$i | flags::$l | flags::$t; const IC: u128 = flags::$i | flags::$c; const LC: u128 = flags::$l | flags::$c; const TC: u128 = flags::$t | flags::$c; const ILC: u128 = IL | flags::$c; const ITC: u128 = IT | flags::$c; const LTC: u128 = LT | flags::$c; const ILTC: u128 = ILT | flags::$c; match format.digit_separator_flags() & flags::$mask { 0 => peek_noskip!(self), flags::$i => peek_i!(self), flags::$l => peek_l!(self), flags::$t => peek_t!(self), IL => peek_il!(self), IT => peek_it!(self), LT => peek_lt!(self), ILT => peek_ilt!(self), IC => peek_ic!(self), LC => peek_lc!(self), TC => peek_tc!(self), ILC => peek_ilc!(self), ITC => peek_itc!(self), LTC => peek_ltc!(self), ILTC => peek_iltc!(self), _ => unreachable!(), } } } }; } // INTEGER DIGITS ITERATOR // ----------------------- skip_iterator!(IntegerBytesIterator, "Iterator that skips over digit separators in the integer."); skip_iterator_impl!(IntegerBytesIterator, mantissa_radix); skip_iterator_iterator_impl!(IntegerBytesIterator); skip_iterator_byteiter_impl!( IntegerBytesIterator, INTEGER_DIGIT_SEPARATOR_FLAG_MASK, INTEGER_INTERNAL_DIGIT_SEPARATOR, INTEGER_LEADING_DIGIT_SEPARATOR, INTEGER_TRAILING_DIGIT_SEPARATOR, INTEGER_CONSECUTIVE_DIGIT_SEPARATOR ); // FRACTION DIGITS ITERATOR // ------------------------ skip_iterator!(FractionBytesIterator, "Iterator that skips over digit separators in the fraction."); skip_iterator_impl!(FractionBytesIterator, mantissa_radix); skip_iterator_iterator_impl!(FractionBytesIterator); skip_iterator_byteiter_impl!( FractionBytesIterator, FRACTION_DIGIT_SEPARATOR_FLAG_MASK, FRACTION_INTERNAL_DIGIT_SEPARATOR, FRACTION_LEADING_DIGIT_SEPARATOR, FRACTION_TRAILING_DIGIT_SEPARATOR, FRACTION_CONSECUTIVE_DIGIT_SEPARATOR ); // EXPONENT DIGITS ITERATOR // ------------------------ skip_iterator!(ExponentBytesIterator, "Iterator that skips over digit separators in the exponent."); skip_iterator_impl!(ExponentBytesIterator, exponent_radix); skip_iterator_iterator_impl!(ExponentBytesIterator); skip_iterator_byteiter_impl!( ExponentBytesIterator, EXPONENT_DIGIT_SEPARATOR_FLAG_MASK, EXPONENT_INTERNAL_DIGIT_SEPARATOR, EXPONENT_LEADING_DIGIT_SEPARATOR, EXPONENT_TRAILING_DIGIT_SEPARATOR, EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR ); // SPECIAL DIGITS ITERATOR // ----------------------- skip_iterator!( SpecialBytesIterator, "Iterator that skips over digit separators in special floats." ); skip_iterator_iterator_impl!(SpecialBytesIterator); impl<'a: 'b, 'b, const FORMAT: u128> SpecialBytesIterator<'a, 'b, FORMAT> { is_digit_separator!(FORMAT); } impl<'a: 'b, 'b, const FORMAT: u128> BytesIter<'a> for SpecialBytesIterator<'a, 'b, FORMAT> { skip_iterator_byteiter_base!(FORMAT, SPECIAL_DIGIT_SEPARATOR); /// Peek the next value of the iterator, without consuming it. #[inline] fn peek(&mut self) -> Option<::Item> { let format = NumberFormat::<{ FORMAT }> {}; if format.special_digit_separator() { peek_iltc!(self) } else { peek_noskip!(self) } } } lexical-util-0.8.5/src/step.rs000064400000000000000000001061330072674642500143760ustar 00000000000000//! The maximum digits that can be held in a u64 for a given radix without overflow. //! //! This is useful for 128-bit division and operations, since it can //! reduces the number of inefficient, non-native operations. //! //! # Generation //! //! See [`etc/step.py`] for the script to generate the divisors and the //! constants, and the division algorithm. //! //! [`etc/step.py`]: https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-util/etc/step.py #![cfg(any(feature = "parse", feature = "write"))] // NOTE: // Fallback radixes use 1 for the value to avoid infinite loops, // but allowing them in `const fn`. /// Calculate the maximum number of digits that can always be processed /// without overflowing for a given type. For example, 19 digits can /// always be processed for a decimal string for `u64` without overflowing. #[inline(always)] pub const fn min_step(radix: u32, bits: usize, is_signed: bool) -> usize { if cfg!(feature = "radix") { match radix { 2 => min_step_2(bits, is_signed), 3 => min_step_3(bits, is_signed), 4 => min_step_4(bits, is_signed), 5 => min_step_5(bits, is_signed), 6 => min_step_6(bits, is_signed), 7 => min_step_7(bits, is_signed), 8 => min_step_8(bits, is_signed), 9 => min_step_9(bits, is_signed), 10 => min_step_10(bits, is_signed), 11 => min_step_11(bits, is_signed), 12 => min_step_12(bits, is_signed), 13 => min_step_13(bits, is_signed), 14 => min_step_14(bits, is_signed), 15 => min_step_15(bits, is_signed), 16 => min_step_16(bits, is_signed), 17 => min_step_17(bits, is_signed), 18 => min_step_18(bits, is_signed), 19 => min_step_19(bits, is_signed), 20 => min_step_20(bits, is_signed), 21 => min_step_21(bits, is_signed), 22 => min_step_22(bits, is_signed), 23 => min_step_23(bits, is_signed), 24 => min_step_24(bits, is_signed), 25 => min_step_25(bits, is_signed), 26 => min_step_26(bits, is_signed), 27 => min_step_27(bits, is_signed), 28 => min_step_28(bits, is_signed), 29 => min_step_29(bits, is_signed), 30 => min_step_30(bits, is_signed), 31 => min_step_31(bits, is_signed), 32 => min_step_32(bits, is_signed), 33 => min_step_33(bits, is_signed), 34 => min_step_34(bits, is_signed), 35 => min_step_35(bits, is_signed), 36 => min_step_36(bits, is_signed), _ => 1, } } else if cfg!(feature = "power-of-two") { match radix { 2 => min_step_2(bits, is_signed), 4 => min_step_4(bits, is_signed), 8 => min_step_8(bits, is_signed), 10 => min_step_10(bits, is_signed), 16 => min_step_16(bits, is_signed), 32 => min_step_32(bits, is_signed), _ => 1, } } else { min_step_10(bits, is_signed) } } /// Calculate the maximum number of digits that can be processed /// without always overflowing for a given type. For example, 20 digits can /// be processed for a decimal string for `u64` without overflowing, but /// it may overflow. #[inline(always)] pub const fn max_step(radix: u32, bits: usize, is_signed: bool) -> usize { if cfg!(feature = "radix") { match radix { 2 => max_step_2(bits, is_signed), 3 => max_step_3(bits, is_signed), 4 => max_step_4(bits, is_signed), 5 => max_step_5(bits, is_signed), 6 => max_step_6(bits, is_signed), 7 => max_step_7(bits, is_signed), 8 => max_step_8(bits, is_signed), 9 => max_step_9(bits, is_signed), 10 => max_step_10(bits, is_signed), 11 => max_step_11(bits, is_signed), 12 => max_step_12(bits, is_signed), 13 => max_step_13(bits, is_signed), 14 => max_step_14(bits, is_signed), 15 => max_step_15(bits, is_signed), 16 => max_step_16(bits, is_signed), 17 => max_step_17(bits, is_signed), 18 => max_step_18(bits, is_signed), 19 => max_step_19(bits, is_signed), 20 => max_step_20(bits, is_signed), 21 => max_step_21(bits, is_signed), 22 => max_step_22(bits, is_signed), 23 => max_step_23(bits, is_signed), 24 => max_step_24(bits, is_signed), 25 => max_step_25(bits, is_signed), 26 => max_step_26(bits, is_signed), 27 => max_step_27(bits, is_signed), 28 => max_step_28(bits, is_signed), 29 => max_step_29(bits, is_signed), 30 => max_step_30(bits, is_signed), 31 => max_step_31(bits, is_signed), 32 => max_step_32(bits, is_signed), 33 => max_step_33(bits, is_signed), 34 => max_step_34(bits, is_signed), 35 => max_step_35(bits, is_signed), 36 => max_step_36(bits, is_signed), _ => 1, } } else if cfg!(feature = "power-of-two") { match radix { 2 => max_step_2(bits, is_signed), 4 => max_step_4(bits, is_signed), 8 => max_step_8(bits, is_signed), 10 => max_step_10(bits, is_signed), 16 => max_step_16(bits, is_signed), 32 => max_step_32(bits, is_signed), _ => 1, } } else { max_step_10(bits, is_signed) } } /// Calculate the number of digits that can be processed without overflowing a u64. /// Helper function since this is used for 128-bit division. #[inline(always)] pub const fn u64_step(radix: u32) -> usize { min_step(radix, 64, false) } // AUTO-GENERATED // These functions were auto-generated by `etc/step.py`. // Do not edit them unless there is a good reason to. // Preferably, edit the source code to generate the constants. // // NOTE: For the fallthrough value for types (in case of adding short // or wider type support in the future), use 1 so it doesn't infinitely // recurse. Under normal circumstances, this will never be called. #[inline] const fn max_step_2(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 7, 8 if !is_signed => 8, 16 if is_signed => 15, 16 if !is_signed => 16, 32 if is_signed => 31, 32 if !is_signed => 32, 64 if is_signed => 63, 64 if !is_signed => 64, 128 if is_signed => 127, 128 if !is_signed => 128, _ => 1, } } #[inline] const fn min_step_2(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 7, 8 if !is_signed => 8, 16 if is_signed => 15, 16 if !is_signed => 16, 32 if is_signed => 31, 32 if !is_signed => 32, 64 if is_signed => 63, 64 if !is_signed => 64, 128 if is_signed => 127, 128 if !is_signed => 128, _ => 1, } } #[inline] const fn max_step_3(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 5, 8 if !is_signed => 6, 16 if is_signed => 10, 16 if !is_signed => 11, 32 if is_signed => 20, 32 if !is_signed => 21, 64 if is_signed => 40, 64 if !is_signed => 41, 128 if is_signed => 81, 128 if !is_signed => 81, _ => 1, } } #[inline] const fn min_step_3(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 4, 8 if !is_signed => 5, 16 if is_signed => 9, 16 if !is_signed => 10, 32 if is_signed => 19, 32 if !is_signed => 20, 64 if is_signed => 39, 64 if !is_signed => 40, 128 if is_signed => 80, 128 if !is_signed => 80, _ => 1, } } #[inline] const fn max_step_4(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 4, 8 if !is_signed => 4, 16 if is_signed => 8, 16 if !is_signed => 8, 32 if is_signed => 16, 32 if !is_signed => 16, 64 if is_signed => 32, 64 if !is_signed => 32, 128 if is_signed => 64, 128 if !is_signed => 64, _ => 1, } } #[inline] const fn min_step_4(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 3, 8 if !is_signed => 4, 16 if is_signed => 7, 16 if !is_signed => 8, 32 if is_signed => 15, 32 if !is_signed => 16, 64 if is_signed => 31, 64 if !is_signed => 32, 128 if is_signed => 63, 128 if !is_signed => 64, _ => 1, } } #[inline] const fn max_step_5(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 4, 8 if !is_signed => 4, 16 if is_signed => 7, 16 if !is_signed => 7, 32 if is_signed => 14, 32 if !is_signed => 14, 64 if is_signed => 28, 64 if !is_signed => 28, 128 if is_signed => 55, 128 if !is_signed => 56, _ => 1, } } #[inline] const fn min_step_5(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 3, 8 if !is_signed => 3, 16 if is_signed => 6, 16 if !is_signed => 6, 32 if is_signed => 13, 32 if !is_signed => 13, 64 if is_signed => 27, 64 if !is_signed => 27, 128 if is_signed => 54, 128 if !is_signed => 55, _ => 1, } } #[inline] const fn max_step_6(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 3, 8 if !is_signed => 4, 16 if is_signed => 6, 16 if !is_signed => 7, 32 if is_signed => 12, 32 if !is_signed => 13, 64 if is_signed => 25, 64 if !is_signed => 25, 128 if is_signed => 50, 128 if !is_signed => 50, _ => 1, } } #[inline] const fn min_step_6(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 3, 16 if is_signed => 5, 16 if !is_signed => 6, 32 if is_signed => 11, 32 if !is_signed => 12, 64 if is_signed => 24, 64 if !is_signed => 24, 128 if is_signed => 49, 128 if !is_signed => 49, _ => 1, } } #[inline] const fn max_step_7(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 3, 8 if !is_signed => 3, 16 if is_signed => 6, 16 if !is_signed => 6, 32 if is_signed => 12, 32 if !is_signed => 12, 64 if is_signed => 23, 64 if !is_signed => 23, 128 if is_signed => 46, 128 if !is_signed => 46, _ => 1, } } #[inline] const fn min_step_7(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 5, 16 if !is_signed => 5, 32 if is_signed => 11, 32 if !is_signed => 11, 64 if is_signed => 22, 64 if !is_signed => 22, 128 if is_signed => 45, 128 if !is_signed => 45, _ => 1, } } #[inline] const fn max_step_8(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 3, 8 if !is_signed => 3, 16 if is_signed => 5, 16 if !is_signed => 6, 32 if is_signed => 11, 32 if !is_signed => 11, 64 if is_signed => 21, 64 if !is_signed => 22, 128 if is_signed => 43, 128 if !is_signed => 43, _ => 1, } } #[inline] const fn min_step_8(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 5, 16 if !is_signed => 5, 32 if is_signed => 10, 32 if !is_signed => 10, 64 if is_signed => 21, 64 if !is_signed => 21, 128 if is_signed => 42, 128 if !is_signed => 42, _ => 1, } } #[inline] const fn max_step_9(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 3, 8 if !is_signed => 3, 16 if is_signed => 5, 16 if !is_signed => 6, 32 if is_signed => 10, 32 if !is_signed => 11, 64 if is_signed => 20, 64 if !is_signed => 21, 128 if is_signed => 41, 128 if !is_signed => 41, _ => 1, } } #[inline] const fn min_step_9(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 5, 32 if is_signed => 9, 32 if !is_signed => 10, 64 if is_signed => 19, 64 if !is_signed => 20, 128 if is_signed => 40, 128 if !is_signed => 40, _ => 1, } } #[inline] const fn max_step_10(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 3, 8 if !is_signed => 3, 16 if is_signed => 5, 16 if !is_signed => 5, 32 if is_signed => 10, 32 if !is_signed => 10, 64 if is_signed => 19, 64 if !is_signed => 20, 128 if is_signed => 39, 128 if !is_signed => 39, _ => 1, } } #[inline] const fn min_step_10(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 9, 32 if !is_signed => 9, 64 if is_signed => 18, 64 if !is_signed => 19, 128 if is_signed => 38, 128 if !is_signed => 38, _ => 1, } } #[inline] const fn max_step_11(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 3, 8 if !is_signed => 3, 16 if is_signed => 5, 16 if !is_signed => 5, 32 if is_signed => 9, 32 if !is_signed => 10, 64 if is_signed => 19, 64 if !is_signed => 19, 128 if is_signed => 37, 128 if !is_signed => 38, _ => 1, } } #[inline] const fn min_step_11(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 8, 32 if !is_signed => 9, 64 if is_signed => 18, 64 if !is_signed => 18, 128 if is_signed => 36, 128 if !is_signed => 37, _ => 1, } } #[inline] const fn max_step_12(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 3, 16 if is_signed => 5, 16 if !is_signed => 5, 32 if is_signed => 9, 32 if !is_signed => 9, 64 if is_signed => 18, 64 if !is_signed => 18, 128 if is_signed => 36, 128 if !is_signed => 36, _ => 1, } } #[inline] const fn min_step_12(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 8, 32 if !is_signed => 8, 64 if is_signed => 17, 64 if !is_signed => 17, 128 if is_signed => 35, 128 if !is_signed => 35, _ => 1, } } #[inline] const fn max_step_13(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 3, 16 if is_signed => 5, 16 if !is_signed => 5, 32 if is_signed => 9, 32 if !is_signed => 9, 64 if is_signed => 18, 64 if !is_signed => 18, 128 if is_signed => 35, 128 if !is_signed => 35, _ => 1, } } #[inline] const fn min_step_13(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 8, 32 if !is_signed => 8, 64 if is_signed => 17, 64 if !is_signed => 17, 128 if is_signed => 34, 128 if !is_signed => 34, _ => 1, } } #[inline] const fn max_step_14(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 3, 16 if is_signed => 4, 16 if !is_signed => 5, 32 if is_signed => 9, 32 if !is_signed => 9, 64 if is_signed => 17, 64 if !is_signed => 17, 128 if is_signed => 34, 128 if !is_signed => 34, _ => 1, } } #[inline] const fn min_step_14(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 2, 16 if is_signed => 3, 16 if !is_signed => 4, 32 if is_signed => 8, 32 if !is_signed => 8, 64 if is_signed => 16, 64 if !is_signed => 16, 128 if is_signed => 33, 128 if !is_signed => 33, _ => 1, } } #[inline] const fn max_step_15(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 3, 16 if is_signed => 4, 16 if !is_signed => 5, 32 if is_signed => 8, 32 if !is_signed => 9, 64 if is_signed => 17, 64 if !is_signed => 17, 128 if is_signed => 33, 128 if !is_signed => 33, _ => 1, } } #[inline] const fn min_step_15(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 2, 16 if is_signed => 3, 16 if !is_signed => 4, 32 if is_signed => 7, 32 if !is_signed => 8, 64 if is_signed => 16, 64 if !is_signed => 16, 128 if is_signed => 32, 128 if !is_signed => 32, _ => 1, } } #[inline] const fn max_step_16(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 8, 32 if !is_signed => 8, 64 if is_signed => 16, 64 if !is_signed => 16, 128 if is_signed => 32, 128 if !is_signed => 32, _ => 1, } } #[inline] const fn min_step_16(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 2, 16 if is_signed => 3, 16 if !is_signed => 4, 32 if is_signed => 7, 32 if !is_signed => 8, 64 if is_signed => 15, 64 if !is_signed => 16, 128 if is_signed => 31, 128 if !is_signed => 32, _ => 1, } } #[inline] const fn max_step_17(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 8, 32 if !is_signed => 8, 64 if is_signed => 16, 64 if !is_signed => 16, 128 if is_signed => 32, 128 if !is_signed => 32, _ => 1, } } #[inline] const fn min_step_17(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 3, 16 if !is_signed => 3, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 15, 64 if !is_signed => 15, 128 if is_signed => 31, 128 if !is_signed => 31, _ => 1, } } #[inline] const fn max_step_18(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 8, 32 if !is_signed => 8, 64 if is_signed => 16, 64 if !is_signed => 16, 128 if is_signed => 31, 128 if !is_signed => 31, _ => 1, } } #[inline] const fn min_step_18(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 3, 16 if !is_signed => 3, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 15, 64 if !is_signed => 15, 128 if is_signed => 30, 128 if !is_signed => 30, _ => 1, } } #[inline] const fn max_step_19(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 8, 32 if !is_signed => 8, 64 if is_signed => 15, 64 if !is_signed => 16, 128 if is_signed => 30, 128 if !is_signed => 31, _ => 1, } } #[inline] const fn min_step_19(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 3, 16 if !is_signed => 3, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 14, 64 if !is_signed => 15, 128 if is_signed => 29, 128 if !is_signed => 30, _ => 1, } } #[inline] const fn max_step_20(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 8, 32 if !is_signed => 8, 64 if is_signed => 15, 64 if !is_signed => 15, 128 if is_signed => 30, 128 if !is_signed => 30, _ => 1, } } #[inline] const fn min_step_20(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 3, 16 if !is_signed => 3, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 14, 64 if !is_signed => 14, 128 if is_signed => 29, 128 if !is_signed => 29, _ => 1, } } #[inline] const fn max_step_21(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 8, 32 if !is_signed => 8, 64 if is_signed => 15, 64 if !is_signed => 15, 128 if is_signed => 29, 128 if !is_signed => 30, _ => 1, } } #[inline] const fn min_step_21(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 3, 16 if !is_signed => 3, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 14, 64 if !is_signed => 14, 128 if is_signed => 28, 128 if !is_signed => 29, _ => 1, } } #[inline] const fn max_step_22(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 7, 32 if !is_signed => 8, 64 if is_signed => 15, 64 if !is_signed => 15, 128 if is_signed => 29, 128 if !is_signed => 29, _ => 1, } } #[inline] const fn min_step_22(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 3, 16 if !is_signed => 3, 32 if is_signed => 6, 32 if !is_signed => 7, 64 if is_signed => 14, 64 if !is_signed => 14, 128 if is_signed => 28, 128 if !is_signed => 28, _ => 1, } } #[inline] const fn max_step_23(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 7, 32 if !is_signed => 8, 64 if is_signed => 14, 64 if !is_signed => 15, 128 if is_signed => 29, 128 if !is_signed => 29, _ => 1, } } #[inline] const fn min_step_23(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 3, 16 if !is_signed => 3, 32 if is_signed => 6, 32 if !is_signed => 7, 64 if is_signed => 13, 64 if !is_signed => 14, 128 if is_signed => 28, 128 if !is_signed => 28, _ => 1, } } #[inline] const fn max_step_24(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 14, 64 if !is_signed => 14, 128 if is_signed => 28, 128 if !is_signed => 28, _ => 1, } } #[inline] const fn min_step_24(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 3, 16 if !is_signed => 3, 32 if is_signed => 6, 32 if !is_signed => 6, 64 if is_signed => 13, 64 if !is_signed => 13, 128 if is_signed => 27, 128 if !is_signed => 27, _ => 1, } } #[inline] const fn max_step_25(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 14, 64 if !is_signed => 14, 128 if is_signed => 28, 128 if !is_signed => 28, _ => 1, } } #[inline] const fn min_step_25(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 3, 16 if !is_signed => 3, 32 if is_signed => 6, 32 if !is_signed => 6, 64 if is_signed => 13, 64 if !is_signed => 13, 128 if is_signed => 27, 128 if !is_signed => 27, _ => 1, } } #[inline] const fn max_step_26(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 14, 64 if !is_signed => 14, 128 if is_signed => 28, 128 if !is_signed => 28, _ => 1, } } #[inline] const fn min_step_26(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 3, 16 if !is_signed => 3, 32 if is_signed => 6, 32 if !is_signed => 6, 64 if is_signed => 13, 64 if !is_signed => 13, 128 if is_signed => 27, 128 if !is_signed => 27, _ => 1, } } #[inline] const fn max_step_27(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 14, 64 if !is_signed => 14, 128 if is_signed => 27, 128 if !is_signed => 27, _ => 1, } } #[inline] const fn min_step_27(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 3, 16 if !is_signed => 3, 32 if is_signed => 6, 32 if !is_signed => 6, 64 if is_signed => 13, 64 if !is_signed => 13, 128 if is_signed => 26, 128 if !is_signed => 26, _ => 1, } } #[inline] const fn max_step_28(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 14, 64 if !is_signed => 14, 128 if is_signed => 27, 128 if !is_signed => 27, _ => 1, } } #[inline] const fn min_step_28(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 3, 16 if !is_signed => 3, 32 if is_signed => 6, 32 if !is_signed => 6, 64 if is_signed => 13, 64 if !is_signed => 13, 128 if is_signed => 26, 128 if !is_signed => 26, _ => 1, } } #[inline] const fn max_step_29(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 13, 64 if !is_signed => 14, 128 if is_signed => 27, 128 if !is_signed => 27, _ => 1, } } #[inline] const fn min_step_29(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 3, 16 if !is_signed => 3, 32 if is_signed => 6, 32 if !is_signed => 6, 64 if is_signed => 12, 64 if !is_signed => 13, 128 if is_signed => 26, 128 if !is_signed => 26, _ => 1, } } #[inline] const fn max_step_30(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 13, 64 if !is_signed => 14, 128 if is_signed => 26, 128 if !is_signed => 27, _ => 1, } } #[inline] const fn min_step_30(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 3, 16 if !is_signed => 3, 32 if is_signed => 6, 32 if !is_signed => 6, 64 if is_signed => 12, 64 if !is_signed => 13, 128 if is_signed => 25, 128 if !is_signed => 26, _ => 1, } } #[inline] const fn max_step_31(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 4, 16 if !is_signed => 4, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 13, 64 if !is_signed => 13, 128 if is_signed => 26, 128 if !is_signed => 26, _ => 1, } } #[inline] const fn min_step_31(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 3, 16 if !is_signed => 3, 32 if is_signed => 6, 32 if !is_signed => 6, 64 if is_signed => 12, 64 if !is_signed => 12, 128 if is_signed => 25, 128 if !is_signed => 25, _ => 1, } } #[inline] const fn max_step_32(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 3, 16 if !is_signed => 4, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 13, 64 if !is_signed => 13, 128 if is_signed => 26, 128 if !is_signed => 26, _ => 1, } } #[inline] const fn min_step_32(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 3, 16 if !is_signed => 3, 32 if is_signed => 6, 32 if !is_signed => 6, 64 if is_signed => 12, 64 if !is_signed => 12, 128 if is_signed => 25, 128 if !is_signed => 25, _ => 1, } } #[inline] const fn max_step_33(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 3, 16 if !is_signed => 4, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 13, 64 if !is_signed => 13, 128 if is_signed => 26, 128 if !is_signed => 26, _ => 1, } } #[inline] const fn min_step_33(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 2, 16 if !is_signed => 3, 32 if is_signed => 6, 32 if !is_signed => 6, 64 if is_signed => 12, 64 if !is_signed => 12, 128 if is_signed => 25, 128 if !is_signed => 25, _ => 1, } } #[inline] const fn max_step_34(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 3, 16 if !is_signed => 4, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 13, 64 if !is_signed => 13, 128 if is_signed => 25, 128 if !is_signed => 26, _ => 1, } } #[inline] const fn min_step_34(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 2, 16 if !is_signed => 3, 32 if is_signed => 6, 32 if !is_signed => 6, 64 if is_signed => 12, 64 if !is_signed => 12, 128 if is_signed => 24, 128 if !is_signed => 25, _ => 1, } } #[inline] const fn max_step_35(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 3, 16 if !is_signed => 4, 32 if is_signed => 7, 32 if !is_signed => 7, 64 if is_signed => 13, 64 if !is_signed => 13, 128 if is_signed => 25, 128 if !is_signed => 25, _ => 1, } } #[inline] const fn min_step_35(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 2, 16 if !is_signed => 3, 32 if is_signed => 6, 32 if !is_signed => 6, 64 if is_signed => 12, 64 if !is_signed => 12, 128 if is_signed => 24, 128 if !is_signed => 24, _ => 1, } } #[inline] const fn max_step_36(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 2, 8 if !is_signed => 2, 16 if is_signed => 3, 16 if !is_signed => 4, 32 if is_signed => 6, 32 if !is_signed => 7, 64 if is_signed => 13, 64 if !is_signed => 13, 128 if is_signed => 25, 128 if !is_signed => 25, _ => 1, } } #[inline] const fn min_step_36(bits: usize, is_signed: bool) -> usize { match bits { 8 if is_signed => 1, 8 if !is_signed => 1, 16 if is_signed => 2, 16 if !is_signed => 3, 32 if is_signed => 5, 32 if !is_signed => 6, 64 if is_signed => 12, 64 if !is_signed => 12, 128 if is_signed => 24, 128 if !is_signed => 24, _ => 1, } } lexical-util-0.8.5/tests/algorithm_tests.rs000064400000000000000000000040220072674642500172000ustar 00000000000000#[cfg(feature = "write")] use lexical_util::algorithm; #[test] #[cfg(feature = "write")] fn copy_to_dest_test() { let src = b"12345"; let mut dst = [b'0'; 16]; assert_eq!(5, unsafe { algorithm::copy_to_dst(&mut dst, src) }); assert_eq!(&dst[..5], src); } #[test] #[cfg(feature = "write")] fn ltrim_char_test() { let w = "0001"; let x = "1010"; let y = "1.00"; let z = "1e05"; assert_eq!(algorithm::ltrim_char_count(w.as_bytes(), b'0'), 3); assert_eq!(algorithm::ltrim_char_count(x.as_bytes(), b'0'), 0); assert_eq!(algorithm::ltrim_char_count(x.as_bytes(), b'1'), 1); assert_eq!(algorithm::ltrim_char_count(y.as_bytes(), b'0'), 0); assert_eq!(algorithm::ltrim_char_count(y.as_bytes(), b'1'), 1); assert_eq!(algorithm::ltrim_char_count(z.as_bytes(), b'0'), 0); assert_eq!(algorithm::ltrim_char_count(z.as_bytes(), b'1'), 1); assert_eq!(algorithm::ltrim_char_count(z.as_bytes(), b'5'), 0); } #[test] #[cfg(feature = "write")] fn rtrim_char_test() { let w = "0001"; let x = "1010"; let y = "1.00"; let z = "1e05"; assert_eq!(algorithm::rtrim_char_count(w.as_bytes(), b'0'), 0); assert_eq!(algorithm::rtrim_char_count(x.as_bytes(), b'0'), 1); assert_eq!(algorithm::rtrim_char_count(x.as_bytes(), b'1'), 0); assert_eq!(algorithm::rtrim_char_count(y.as_bytes(), b'0'), 2); assert_eq!(algorithm::rtrim_char_count(y.as_bytes(), b'1'), 0); assert_eq!(algorithm::rtrim_char_count(z.as_bytes(), b'0'), 0); assert_eq!(algorithm::rtrim_char_count(z.as_bytes(), b'5'), 1); assert_eq!(algorithm::rtrim_char_slice(w.as_bytes(), b'0').1, 0); assert_eq!(algorithm::rtrim_char_slice(x.as_bytes(), b'0').1, 1); assert_eq!(algorithm::rtrim_char_slice(x.as_bytes(), b'1').1, 0); assert_eq!(algorithm::rtrim_char_slice(y.as_bytes(), b'0').1, 2); assert_eq!(algorithm::rtrim_char_slice(y.as_bytes(), b'1').1, 0); assert_eq!(algorithm::rtrim_char_slice(z.as_bytes(), b'0').1, 0); assert_eq!(algorithm::rtrim_char_slice(z.as_bytes(), b'5').1, 1); } lexical-util-0.8.5/tests/ascii_tests.rs000064400000000000000000000037440072674642500163140ustar 00000000000000use lexical_util::ascii; #[test] fn is_valid_ascii_test() { assert_eq!(ascii::is_valid_ascii(b'\x00'), false); assert_eq!(ascii::is_valid_ascii(b'\n'), true); assert_eq!(ascii::is_valid_ascii(b'\r'), true); assert_eq!(ascii::is_valid_ascii(b'\x1b'), false); assert_eq!(ascii::is_valid_ascii(b' '), true); assert_eq!(ascii::is_valid_ascii(b'0'), true); assert_eq!(ascii::is_valid_ascii(b'9'), true); assert_eq!(ascii::is_valid_ascii(b':'), true); assert_eq!(ascii::is_valid_ascii(b'A'), true); assert_eq!(ascii::is_valid_ascii(b'Z'), true); assert_eq!(ascii::is_valid_ascii(b']'), true); assert_eq!(ascii::is_valid_ascii(b'a'), true); assert_eq!(ascii::is_valid_ascii(b'z'), true); assert_eq!(ascii::is_valid_ascii(b'~'), true); assert_eq!(ascii::is_valid_ascii(b'\x7f'), false); } #[test] fn is_valid_ascii_slice_test() { assert_eq!(ascii::is_valid_ascii_slice(b" 09a"), true); assert_eq!(ascii::is_valid_ascii_slice(b" 09a\x1b"), false); } #[test] fn is_valid_letter_test() { assert_eq!(ascii::is_valid_letter(b'\x00'), false); assert_eq!(ascii::is_valid_letter(b'\n'), false); assert_eq!(ascii::is_valid_letter(b'\r'), false); assert_eq!(ascii::is_valid_letter(b'\x1b'), false); assert_eq!(ascii::is_valid_letter(b' '), false); assert_eq!(ascii::is_valid_letter(b'0'), false); assert_eq!(ascii::is_valid_letter(b'9'), false); assert_eq!(ascii::is_valid_letter(b':'), false); assert_eq!(ascii::is_valid_letter(b'A'), true); assert_eq!(ascii::is_valid_letter(b'Z'), true); assert_eq!(ascii::is_valid_letter(b']'), false); assert_eq!(ascii::is_valid_letter(b'a'), true); assert_eq!(ascii::is_valid_letter(b'z'), true); assert_eq!(ascii::is_valid_letter(b'~'), false); assert_eq!(ascii::is_valid_letter(b'\x7f'), false); } #[test] fn is_valid_letter_slice_test() { assert_eq!(ascii::is_valid_letter_slice(b" 09a"), false); assert_eq!(ascii::is_valid_letter_slice(b"aZAz"), true); } lexical-util-0.8.5/tests/bf16_tests.rs000064400000000000000000000041230072674642500157520ustar 00000000000000#![cfg(feature = "f16")] use lexical_util::bf16::bf16; use lexical_util::num::Float; use proptest::prelude::*; use quickcheck::quickcheck; #[test] fn as_f32_test() { assert_eq!(bf16::from_bits(1).as_f32(), 9.18355e-41f32); assert_eq!(bf16::ZERO.as_f32(), 0.0f32); assert_eq!(bf16::ZERO.to_bits(), 0); assert_eq!(bf16::ONE.as_f32(), 1.0f32); assert_eq!(bf16::ONE.to_bits(), (127 << 7)); assert_eq!(bf16::TWO.as_f32(), 2.0f32); assert_eq!(bf16::TWO.to_bits(), (128 << 7)); assert_eq!(bf16::from_bits(126 << 7).as_f32(), 0.5f32); assert!(bf16::NAN.as_f32().is_nan()); assert!(bf16::INFINITY.as_f32().is_inf()); assert!(bf16::NEG_INFINITY.as_f32().is_inf()); } #[test] fn from_f32_test() { assert_eq!(bf16::from_f32(4.5917e-41f32).to_bits(), 0); assert_eq!(bf16::from_f32(4.5918e-41f32).to_bits(), 0); assert_eq!(bf16::from_f32(4.5919e-41f32).to_bits(), 1); assert_eq!(bf16::from_f32(9.18354e-41f32).to_bits(), 1); assert_eq!(bf16::from_f32(9.18355e-41f32).to_bits(), 1); assert_eq!(bf16::from_f32(9.18356e-41f32).to_bits(), 1); assert_eq!(bf16::from_f32(1.37752e-40f32).to_bits(), 1); assert_eq!(bf16::from_f32(1.37753e-40f32).to_bits(), 2); assert_eq!(bf16::from_f32(1.37754e-40f32).to_bits(), 2); assert!(bf16::from_f32(f32::NAN).is_nan()); assert!(bf16::from_f32(f32::INFINITY).is_inf()); assert!(bf16::from_f32(f32::NEG_INFINITY).is_inf()); } #[test] fn math_tests() { assert_eq!(bf16::ONE + bf16::ONE, bf16::TWO); assert_eq!(bf16::ONE * bf16::ONE, bf16::ONE); assert_eq!(bf16::ONE / bf16::ONE, bf16::ONE); assert_eq!(bf16::ONE - bf16::ONE, bf16::ZERO); assert_eq!(bf16::ONE % bf16::ONE, bf16::ZERO); } quickcheck! { #[cfg_attr(miri, ignore)] fn f32_roundtrip_quickcheck(x: u16) -> bool { let f = bf16::from_bits(x).as_f32(); bf16::from_f32(f).to_bits() == x } } proptest! { #[test] #[cfg_attr(miri, ignore)] fn f32_roundtrip_proptest(x in u16::MIN..u16::MAX) { let f = bf16::from_bits(x).as_f32(); prop_assert_eq!(bf16::from_f32(f).to_bits(), x); } } lexical-util-0.8.5/tests/digit_tests.rs000064400000000000000000000062760072674642500163270ustar 00000000000000#![cfg(any(feature = "parse", feature = "write"))] use lexical_util::digit; #[cfg(feature = "parse")] fn char_to_digit(c: u8, radix: u32, expected: Option) { assert_eq!(digit::char_to_digit_const(c, radix), expected); assert_eq!(digit::char_to_digit(c, radix), expected); } #[test] #[cfg(feature = "parse")] fn char_to_digit_test() { char_to_digit(b'0', 2, Some(0)); char_to_digit(b'1', 2, Some(1)); char_to_digit(b'9', 2, None); char_to_digit(b'A', 2, None); char_to_digit(b'Z', 2, None); char_to_digit(b'0', 10, Some(0)); char_to_digit(b'1', 10, Some(1)); char_to_digit(b'9', 10, Some(9)); char_to_digit(b'A', 10, None); char_to_digit(b'Z', 10, None); char_to_digit(b'0', 16, Some(0)); char_to_digit(b'1', 16, Some(1)); char_to_digit(b'9', 16, Some(9)); char_to_digit(b'A', 16, Some(10)); char_to_digit(b'Z', 16, None); // char_to_digit doesn't care about the radix. // check some more comprehensive cases. for c in b'0'..=b'9' { char_to_digit(c, 10, Some(c as u32 - b'0' as u32)); } char_to_digit(0x29, 10, None); char_to_digit(0x3A, 10, None); char_to_digit(0x59, 10, None); for c in b'0'..=b'8' { char_to_digit(c, 9, Some(c as u32 - b'0' as u32)); } char_to_digit(0x29, 9, None); char_to_digit(0x39, 9, None); char_to_digit(0x3A, 9, None); char_to_digit(0x59, 9, None); for c in b'0'..=b'9' { char_to_digit(c, 16, Some(c as u32 - b'0' as u32)); } for c in b'a'..=b'f' { char_to_digit(c, 16, Some(c as u32 - b'a' as u32 + 10)); } for c in b'A'..=b'F' { char_to_digit(c, 16, Some(c as u32 - b'A' as u32 + 10)); } char_to_digit(0x29, 16, None); char_to_digit(0x40, 16, None); char_to_digit(0x3A, 16, None); char_to_digit(0x59, 16, None); char_to_digit(0x41, 16, Some(10)); char_to_digit(0x47, 16, None); char_to_digit(0x5A, 16, None); char_to_digit(0x61, 16, Some(10)); char_to_digit(0x67, 16, None); char_to_digit(0x7A, 16, None); } #[cfg(feature = "parse")] fn char_is_digit(c: u8, radix: u32, expected: bool) { assert_eq!(digit::char_is_digit_const(c, radix), expected); assert_eq!(digit::char_is_digit(c, radix), expected); } #[test] #[cfg(feature = "parse")] fn char_is_digit_const_test() { char_is_digit(b'0', 2, true); char_is_digit(b'1', 2, true); char_is_digit(b'9', 2, false); char_is_digit(b'A', 2, false); char_is_digit(b'Z', 2, false); char_is_digit(b'0', 10, true); char_is_digit(b'1', 10, true); char_is_digit(b'9', 10, true); char_is_digit(b'A', 10, false); char_is_digit(b'Z', 10, false); char_is_digit(b'0', 16, true); char_is_digit(b'1', 16, true); char_is_digit(b'9', 16, true); char_is_digit(b'A', 16, true); char_is_digit(b'Z', 16, false); } #[cfg(feature = "write")] fn digit_to_char(digit: u32, radix: u32, expected: u8) { assert_eq!(digit::digit_to_char_const(digit, radix), expected); assert_eq!(unsafe { digit::digit_to_char(digit) }, expected); } #[test] #[cfg(feature = "write")] fn digit_to_char_const_test() { digit_to_char(9, 10, b'9'); digit_to_char(10, 36, b'A'); digit_to_char(11, 36, b'B'); } lexical-util-0.8.5/tests/div128_tests.rs000064400000000000000000000017000072674642500162270ustar 00000000000000#![cfg(not(feature = "compact"))] #![cfg(feature = "write")] use lexical_util::div128::u128_divrem; use lexical_util::step::u64_step; use proptest::{prop_assert_eq, proptest}; proptest! { #[test] #[cfg_attr(miri, ignore)] fn u128_divrem_proptest(i in u128::min_value()..u128::max_value()) { let (hi, lo) = u128_divrem(i, 10); let step = u64_step(10); let d = 10u128.pow(step as u32); let expected = (i / d, (i % d) as u64); prop_assert_eq!((hi, lo), expected); } #[test] #[cfg_attr(miri, ignore)] #[cfg(feature = "radix")] fn u128_divrem_radix_proptest(i in u128::min_value()..u128::max_value(), radix in 2u32..=36) { // Simulate a const expr. let (hi, lo) = u128_divrem(i, radix); let step = u64_step(radix); let d = (radix as u128).pow(step as u32); let expected = (i / d, (i % d) as u64); prop_assert_eq!((hi, lo), expected); } } lexical-util-0.8.5/tests/f16_tests.rs000064400000000000000000000040710072674642500156120ustar 00000000000000#![cfg(feature = "f16")] use lexical_util::f16::f16; use lexical_util::num::Float; use proptest::prelude::*; use quickcheck::quickcheck; #[test] fn as_f32_test() { assert_eq!(f16::from_bits(1).as_f32(), 0.000000059604645); assert_eq!(f16::ZERO.as_f32(), 0.0f32); assert_eq!(f16::ZERO.to_bits(), 0); assert_eq!(f16::ONE.as_f32(), 1.0f32); assert_eq!(f16::ONE.to_bits(), (15 << 10)); assert_eq!(f16::TWO.as_f32(), 2.0f32); assert_eq!(f16::TWO.to_bits(), (16 << 10)); assert_eq!(f16::from_bits(14 << 10).as_f32(), 0.5f32); assert!(f16::NAN.as_f32().is_nan()); assert!(f16::INFINITY.as_f32().is_inf()); assert!(f16::NEG_INFINITY.as_f32().is_inf()); } #[test] fn from_f32_test() { assert_eq!(f16::from_f32(2.980232e-08).to_bits(), 0); assert_eq!(f16::from_f32(2.9802322e-08).to_bits(), 0); assert_eq!(f16::from_f32(2.9802326e-08).to_bits(), 1); assert_eq!(f16::from_f32(5.960464e-08).to_bits(), 1); assert_eq!(f16::from_f32(5.9604645e-08).to_bits(), 1); assert_eq!(f16::from_f32(5.960465e-08).to_bits(), 1); assert!(f16::from_f32(f32::NAN).is_nan()); assert!(f16::from_f32(f32::INFINITY).is_inf()); assert!(f16::from_f32(f32::NEG_INFINITY).is_inf()); } #[test] fn math_tests() { assert_eq!(f16::ONE + f16::ONE, f16::TWO); assert_eq!(f16::ONE * f16::ONE, f16::ONE); assert_eq!(f16::ONE / f16::ONE, f16::ONE); assert_eq!(f16::ONE - f16::ONE, f16::ZERO); assert_eq!(f16::ONE % f16::ONE, f16::ZERO); } quickcheck! { #[cfg_attr(miri, ignore)] fn f32_roundtrip_quickcheck(x: u16) -> bool { let f = f16::from_bits(x).as_f32(); if f.is_nan() { f16::from_f32(f).is_nan() } else { f16::from_f32(f).to_bits() == x } } } proptest! { #[test] #[cfg_attr(miri, ignore)] fn f32_roundtrip_proptest(x in u16::MIN..u16::MAX) { let f = f16::from_bits(x).as_f32(); if f.is_nan() { prop_assert!(f16::from_f32(f).is_nan()); } else { prop_assert_eq!(f16::from_f32(f).to_bits(), x); } } } lexical-util-0.8.5/tests/feature_format_tests.rs000064400000000000000000000250060072674642500202220ustar 00000000000000#![cfg(feature = "format")] use core::num; use lexical_util::format; #[test] fn ignore_test() { let fmt = format::NumberFormat::<{ format::IGNORE }> {}; assert_eq!(fmt.flags(), format::DIGIT_SEPARATOR_FLAG_MASK); assert_eq!(fmt.digit_separator(), b'_'); assert_eq!(fmt.required_integer_digits(), false); assert_eq!(fmt.required_fraction_digits(), false); assert_eq!(fmt.required_exponent_digits(), false); assert_eq!(fmt.required_mantissa_digits(), false); assert_eq!(fmt.required_digits(), false); assert_eq!(fmt.no_positive_mantissa_sign(), false); assert_eq!(fmt.required_mantissa_sign(), false); assert_eq!(fmt.no_exponent_notation(), false); assert_eq!(fmt.no_positive_exponent_sign(), false); assert_eq!(fmt.required_exponent_sign(), false); assert_eq!(fmt.no_exponent_without_fraction(), false); assert_eq!(fmt.no_special(), false); assert_eq!(fmt.case_sensitive_special(), false); assert_eq!(fmt.no_integer_leading_zeros(), false); assert_eq!(fmt.no_float_leading_zeros(), false); assert_eq!(fmt.required_exponent_notation(), false); assert_eq!(fmt.case_sensitive_exponent(), false); #[cfg(feature = "power-of-two")] assert_eq!(fmt.case_sensitive_base_prefix(), false); #[cfg(feature = "power-of-two")] assert_eq!(fmt.case_sensitive_base_suffix(), false); assert_eq!(fmt.integer_internal_digit_separator(), true); assert_eq!(fmt.fraction_internal_digit_separator(), true); assert_eq!(fmt.exponent_internal_digit_separator(), true); assert_eq!(fmt.internal_digit_separator(), true); assert_eq!(fmt.integer_leading_digit_separator(), true); assert_eq!(fmt.fraction_leading_digit_separator(), true); assert_eq!(fmt.exponent_leading_digit_separator(), true); assert_eq!(fmt.leading_digit_separator(), true); assert_eq!(fmt.integer_trailing_digit_separator(), true); assert_eq!(fmt.fraction_trailing_digit_separator(), true); assert_eq!(fmt.exponent_trailing_digit_separator(), true); assert_eq!(fmt.trailing_digit_separator(), true); assert_eq!(fmt.integer_consecutive_digit_separator(), true); assert_eq!(fmt.fraction_consecutive_digit_separator(), true); assert_eq!(fmt.exponent_consecutive_digit_separator(), true); assert_eq!(fmt.consecutive_digit_separator(), true); assert_eq!(fmt.special_digit_separator(), true); } fn test_flag() { let fmt = format::NumberFormat:: {}; assert_eq!(fmt.flags(), FORMAT); assert_eq!(fmt.digit_separator(), 0); } macro_rules! test_flag { ($field:ident, $flag:ident) => {{ test_flag::<{ format::$flag }>(); if format::$flag & format::CONSECUTIVE_DIGIT_SEPARATOR == 0 { const FORMAT: u128 = format::NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .$field(true) .build(); let fmt = format::NumberFormat:: {}; assert_eq!(fmt.is_valid(), true); assert_eq!(fmt.$field(), true); } else { const FORMAT: u128 = format::NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .internal_digit_separator(true) .leading_digit_separator(true) .trailing_digit_separator(true) .$field(true) .build(); let fmt = format::NumberFormat:: {}; assert_eq!(fmt.is_valid(), true); assert_eq!(fmt.$field(), true); } }}; } #[test] fn flags_test() { test_flag!(required_integer_digits, REQUIRED_INTEGER_DIGITS); test_flag!(required_fraction_digits, REQUIRED_FRACTION_DIGITS); test_flag!(required_exponent_digits, REQUIRED_EXPONENT_DIGITS); test_flag!(required_mantissa_digits, REQUIRED_MANTISSA_DIGITS); test_flag!(no_positive_mantissa_sign, NO_POSITIVE_MANTISSA_SIGN); test_flag!(required_mantissa_sign, REQUIRED_MANTISSA_SIGN); test_flag!(no_exponent_notation, NO_EXPONENT_NOTATION); test_flag!(no_positive_exponent_sign, NO_POSITIVE_EXPONENT_SIGN); test_flag!(required_exponent_sign, REQUIRED_EXPONENT_SIGN); test_flag!(no_exponent_without_fraction, NO_EXPONENT_WITHOUT_FRACTION); test_flag!(no_special, NO_SPECIAL); test_flag!(case_sensitive_special, CASE_SENSITIVE_SPECIAL); test_flag!(no_integer_leading_zeros, NO_INTEGER_LEADING_ZEROS); test_flag!(no_float_leading_zeros, NO_FLOAT_LEADING_ZEROS); test_flag!(required_exponent_notation, REQUIRED_EXPONENT_NOTATION); test_flag!(case_sensitive_exponent, CASE_SENSITIVE_EXPONENT); #[cfg(feature = "power-of-two")] test_flag!(case_sensitive_base_prefix, CASE_SENSITIVE_BASE_PREFIX); #[cfg(feature = "power-of-two")] test_flag!(case_sensitive_base_suffix, CASE_SENSITIVE_BASE_SUFFIX); test_flag!(integer_internal_digit_separator, INTEGER_INTERNAL_DIGIT_SEPARATOR); test_flag!(fraction_internal_digit_separator, FRACTION_INTERNAL_DIGIT_SEPARATOR); test_flag!(exponent_internal_digit_separator, EXPONENT_INTERNAL_DIGIT_SEPARATOR); test_flag!(integer_leading_digit_separator, INTEGER_LEADING_DIGIT_SEPARATOR); test_flag!(fraction_leading_digit_separator, FRACTION_LEADING_DIGIT_SEPARATOR); test_flag!(exponent_leading_digit_separator, EXPONENT_LEADING_DIGIT_SEPARATOR); test_flag!(integer_trailing_digit_separator, INTEGER_TRAILING_DIGIT_SEPARATOR); test_flag!(fraction_trailing_digit_separator, FRACTION_TRAILING_DIGIT_SEPARATOR); test_flag!(exponent_trailing_digit_separator, EXPONENT_TRAILING_DIGIT_SEPARATOR); test_flag!(integer_consecutive_digit_separator, INTEGER_CONSECUTIVE_DIGIT_SEPARATOR); test_flag!(fraction_consecutive_digit_separator, FRACTION_CONSECUTIVE_DIGIT_SEPARATOR); test_flag!(exponent_consecutive_digit_separator, EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR); test_flag!(special_digit_separator, SPECIAL_DIGIT_SEPARATOR); } #[test] fn constants_test() { // Don't check the actual values: just check they're defined. let _: u128 = format::RUST_LITERAL; let _: u128 = format::RUST_STRING; let _: u128 = format::PYTHON_LITERAL; let _: u128 = format::PYTHON_STRING; let _: u128 = format::PYTHON3_LITERAL; let _: u128 = format::PYTHON3_STRING; let _: u128 = format::PYTHON36_LITERAL; let _: u128 = format::PYTHON35_LITERAL; let _: u128 = format::PYTHON2_LITERAL; let _: u128 = format::PYTHON2_STRING; let _: u128 = format::CXX17_LITERAL; let _: u128 = format::CXX17_STRING; let _: u128 = format::CXX14_LITERAL; let _: u128 = format::CXX14_STRING; let _: u128 = format::CXX11_LITERAL; let _: u128 = format::CXX11_STRING; let _: u128 = format::CXX03_LITERAL; let _: u128 = format::CXX03_STRING; let _: u128 = format::CXX98_LITERAL; let _: u128 = format::CXX98_STRING; let _: u128 = format::C18_LITERAL; let _: u128 = format::C18_STRING; let _: u128 = format::C11_LITERAL; let _: u128 = format::C11_STRING; let _: u128 = format::C99_LITERAL; let _: u128 = format::C99_STRING; let _: u128 = format::C90_LITERAL; let _: u128 = format::C90_STRING; let _: u128 = format::C89_LITERAL; let _: u128 = format::C89_STRING; let _: u128 = format::RUBY_LITERAL; let _: u128 = format::RUBY_STRING; let _: u128 = format::SWIFT_LITERAL; let _: u128 = format::SWIFT_STRING; let _: u128 = format::GO_LITERAL; let _: u128 = format::GO_STRING; let _: u128 = format::HASKELL_LITERAL; let _: u128 = format::HASKELL_STRING; let _: u128 = format::JAVASCRIPT_LITERAL; let _: u128 = format::JAVASCRIPT_STRING; let _: u128 = format::PERL_LITERAL; let _: u128 = format::PERL_STRING; let _: u128 = format::PHP_LITERAL; let _: u128 = format::PHP_STRING; let _: u128 = format::JAVA_LITERAL; let _: u128 = format::JAVA_STRING; let _: u128 = format::R_LITERAL; let _: u128 = format::R_STRING; let _: u128 = format::KOTLIN_LITERAL; let _: u128 = format::KOTLIN_STRING; let _: u128 = format::JULIA_LITERAL; let _: u128 = format::JULIA_STRING; let _: u128 = format::CSHARP7_LITERAL; let _: u128 = format::CSHARP7_STRING; let _: u128 = format::CSHARP6_LITERAL; let _: u128 = format::CSHARP6_STRING; let _: u128 = format::CSHARP5_LITERAL; let _: u128 = format::CSHARP5_STRING; let _: u128 = format::CSHARP4_LITERAL; let _: u128 = format::CSHARP4_STRING; let _: u128 = format::CSHARP3_LITERAL; let _: u128 = format::CSHARP3_STRING; let _: u128 = format::CSHARP2_LITERAL; let _: u128 = format::CSHARP2_STRING; let _: u128 = format::CSHARP1_LITERAL; let _: u128 = format::CSHARP1_STRING; let _: u128 = format::KAWA_LITERAL; let _: u128 = format::KAWA_STRING; let _: u128 = format::GAMBITC_LITERAL; let _: u128 = format::GAMBITC_STRING; let _: u128 = format::GUILE_LITERAL; let _: u128 = format::GUILE_STRING; let _: u128 = format::CLOJURE_LITERAL; let _: u128 = format::CLOJURE_STRING; let _: u128 = format::ERLANG_LITERAL; let _: u128 = format::ERLANG_STRING; let _: u128 = format::ELM_LITERAL; let _: u128 = format::ELM_STRING; let _: u128 = format::SCALA_LITERAL; let _: u128 = format::SCALA_STRING; let _: u128 = format::ELIXIR_LITERAL; let _: u128 = format::ELIXIR_STRING; let _: u128 = format::FORTRAN_LITERAL; let _: u128 = format::FORTRAN_STRING; let _: u128 = format::D_LITERAL; let _: u128 = format::D_STRING; let _: u128 = format::COFFEESCRIPT_LITERAL; let _: u128 = format::COFFEESCRIPT_STRING; let _: u128 = format::COBOL_LITERAL; let _: u128 = format::COBOL_STRING; let _: u128 = format::FSHARP_LITERAL; let _: u128 = format::FSHARP_STRING; let _: u128 = format::VB_LITERAL; let _: u128 = format::VB_STRING; let _: u128 = format::OCAML_LITERAL; let _: u128 = format::OCAML_STRING; let _: u128 = format::OBJECTIVEC_LITERAL; let _: u128 = format::OBJECTIVEC_STRING; let _: u128 = format::REASONML_LITERAL; let _: u128 = format::REASONML_STRING; let _: u128 = format::OCTAVE_LITERAL; let _: u128 = format::OCTAVE_STRING; let _: u128 = format::MATLAB_LITERAL; let _: u128 = format::MATLAB_STRING; let _: u128 = format::ZIG_LITERAL; let _: u128 = format::ZIG_STRING; let _: u128 = format::SAGE_LITERAL; let _: u128 = format::SAGE_STRING; let _: u128 = format::JSON; let _: u128 = format::TOML; let _: u128 = format::YAML; let _: u128 = format::XML; let _: u128 = format::SQLITE; let _: u128 = format::POSTGRESQL; let _: u128 = format::MYSQL; let _: u128 = format::MONGODB; } lexical-util-0.8.5/tests/format_builder_tests.rs000064400000000000000000000035130072674642500202140ustar 00000000000000use lexical_util::format::{NumberFormat, NumberFormatBuilder}; #[test] fn decimal_test() { const FORMAT: u128 = NumberFormatBuilder::decimal(); let format = NumberFormat:: {}; assert!(format.is_valid()); assert_eq!(format.radix(), 10); assert_eq!(format.mantissa_radix(), 10); assert_eq!(format.exponent_base(), 10); assert_eq!(format.exponent_radix(), 10); } #[test] #[cfg(feature = "power-of-two")] fn binary_test() { const FORMAT: u128 = NumberFormatBuilder::binary(); let format = NumberFormat:: {}; assert!(format.is_valid()); assert_eq!(format.radix(), 2); assert_eq!(format.mantissa_radix(), 2); assert_eq!(format.exponent_base(), 2); assert_eq!(format.exponent_radix(), 2); } #[test] #[cfg(feature = "power-of-two")] fn octal_test() { const FORMAT: u128 = NumberFormatBuilder::octal(); let format = NumberFormat:: {}; assert!(format.is_valid()); assert_eq!(format.radix(), 8); assert_eq!(format.mantissa_radix(), 8); assert_eq!(format.exponent_base(), 8); assert_eq!(format.exponent_radix(), 8); } #[test] #[cfg(feature = "power-of-two")] fn hexadecimal_test() { const FORMAT: u128 = NumberFormatBuilder::hexadecimal(); let format = NumberFormat:: {}; assert!(format.is_valid()); assert_eq!(format.radix(), 16); assert_eq!(format.mantissa_radix(), 16); assert_eq!(format.exponent_base(), 16); assert_eq!(format.exponent_radix(), 16); } #[test] #[cfg(feature = "power-of-two")] fn from_radix_test() { const FORMAT: u128 = NumberFormatBuilder::from_radix(32); let format = NumberFormat:: {}; assert!(format.is_valid()); assert_eq!(format.radix(), 32); assert_eq!(format.mantissa_radix(), 32); assert_eq!(format.exponent_base(), 32); assert_eq!(format.exponent_radix(), 32); } lexical-util-0.8.5/tests/format_flags_tests.rs000064400000000000000000000040170072674642500176620ustar 00000000000000#[cfg(feature = "format")] use core::num; #[cfg(feature = "format")] use lexical_util::format; #[cfg(feature = "format")] const fn from_digit_separator(digit_separator: u8) -> u128 { format::NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(digit_separator)) .digit_separator_flags(true) .build() } #[cfg(feature = "format")] fn is_valid_digit_separator(digit_separator: u8) -> bool { let format = from_digit_separator(digit_separator); format::is_valid_digit_separator(format) } #[test] #[cfg(feature = "format")] fn test_is_valid_digit_separator() { assert_eq!(is_valid_digit_separator(b'_'), true); assert_eq!(is_valid_digit_separator(b'\''), true); assert_eq!(is_valid_digit_separator(b'.'), true); assert_eq!(is_valid_digit_separator(b'e'), true); assert_eq!(is_valid_digit_separator(b'0'), false); assert_eq!(is_valid_digit_separator(128), false); // Try with a custom radix. #[cfg(feature = "radix")] { let format = format::NumberFormat::<{ from_digit_separator(b'e') }>::rebuild().radix(16).build(); assert_eq!(format::is_valid_digit_separator(format), false); } } #[cfg(all(feature = "power-of-two", feature = "format"))] fn is_valid_punctuation(digit_separator: u8, base_prefix: u8, base_suffix: u8) -> bool { let fmt = format::NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(digit_separator)) .digit_separator_flags(true) .base_prefix(num::NonZeroU8::new(base_prefix)) .base_suffix(num::NonZeroU8::new(base_suffix)) .build(); format::is_valid_punctuation(fmt) } #[test] #[cfg(all(feature = "power-of-two", feature = "format"))] fn test_is_valid_punctuation() { assert_eq!(is_valid_punctuation(b'_', b'h', 0), true); assert_eq!(is_valid_punctuation(b'e', b'h', 0), true); assert_eq!(is_valid_punctuation(b'^', b'h', 0), true); assert_eq!(is_valid_punctuation(b'\'', b'h', 0), true); assert_eq!(is_valid_punctuation(b'\'', b'h', b'h'), false); } lexical-util-0.8.5/tests/iterator_tests.rs000064400000000000000000000075440072674642500170570ustar 00000000000000#![cfg(feature = "parse")] use lexical_util::iterator::{AsBytes, Bytes, BytesIter}; #[test] #[cfg(not(feature = "format"))] fn digits_iterator_test() { use lexical_util::format::STANDARD; type Digits<'a> = Bytes<'a, { STANDARD }>; assert!(Digits::IS_CONTIGUOUS); let digits = b"12345"; let mut byte1 = Digits::new(digits); let mut byte2 = Digits::new(digits); assert!(byte1.integer_iter().eq(byte2.integer_iter())); let mut byte = digits.bytes::<{ STANDARD }>(); let mut iter = byte.integer_iter(); assert_eq!(iter.as_slice(), &digits[..]); assert_eq!(iter.as_ptr(), digits.as_ptr()); assert_eq!(iter.is_consumed(), false); assert_eq!(iter.is_done(), false); assert_eq!(u32::from_le(iter.read::().unwrap()), 0x34333231); assert_eq!(iter.length(), 5); assert_eq!(iter.cursor(), 0); assert_eq!(iter.current_count(), 0); unsafe { iter.step_by_unchecked(4); } assert_eq!(iter.length(), 5); assert_eq!(iter.cursor(), 4); assert_eq!(iter.current_count(), 4); assert_eq!(unsafe { iter.peek_unchecked() }, &b'5'); assert_eq!(iter.peek(), Some(&b'5')); assert_eq!(iter.next(), Some(&b'5')); assert_eq!(iter.peek(), None); assert_eq!(iter.next(), None); let mut byte = digits.bytes::<{ STANDARD }>(); let mut iter = byte.integer_iter(); assert_eq!(iter.read::(), None); assert_eq!(iter.nth(4).unwrap(), &b'5'); assert_eq!(iter.as_slice(), &digits[digits.len()..]); assert_eq!(iter.as_ptr(), digits[digits.len()..].as_ptr()); let mut byte = digits.bytes::<{ STANDARD }>(); let mut iter = byte.integer_iter(); assert_eq!(iter.peek(), Some(&b'1')); unsafe { iter.step_unchecked(); } assert_eq!(iter.peek(), Some(&b'2')); unsafe { iter.step_unchecked(); } } #[test] #[cfg(feature = "format")] fn skip_iterator_test() { use core::num; use lexical_util::format::{NumberFormat, NumberFormatBuilder}; use static_assertions::const_assert; pub const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .digit_separator_flags(true) .build(); const_assert!(NumberFormat::<{ FORMAT }> {}.is_valid()); type Digits<'a> = Bytes<'a, { FORMAT }>; assert!(!Digits::IS_CONTIGUOUS); let digits = b"123_45"; let mut byte1 = Digits::new(digits); let mut byte2 = Digits::new(digits); assert!(byte1.integer_iter().eq(byte2.integer_iter())); let mut byte = digits.bytes::<{ FORMAT }>(); let mut iter = byte.integer_iter(); assert_eq!(iter.as_slice(), &digits[..]); assert_eq!(iter.as_ptr(), digits.as_ptr()); assert_eq!(iter.is_consumed(), false); assert_eq!(iter.is_done(), false); assert_eq!(iter.length(), 6); assert_eq!(iter.cursor(), 0); assert_eq!(iter.current_count(), 0); unsafe { iter.step_unchecked() }; assert_eq!(iter.cursor(), 1); assert_eq!(iter.current_count(), 1); iter.next(); assert_eq!(iter.cursor(), 2); assert_eq!(iter.current_count(), 2); let mut byte = digits.bytes::<{ FORMAT }>(); let mut iter = byte.integer_iter(); assert_eq!(unsafe { iter.peek_unchecked() }, &b'1'); assert_eq!(iter.peek(), Some(&b'1')); assert_eq!(iter.next(), Some(&b'1')); assert_eq!(iter.next(), Some(&b'2')); assert_eq!(iter.next(), Some(&b'3')); assert_eq!(iter.cursor(), 3); assert_eq!(iter.current_count(), 3); assert_eq!(iter.next(), Some(&b'4')); assert_eq!(iter.cursor(), 5); assert_eq!(iter.current_count(), 4); assert_eq!(iter.next(), Some(&b'5')); assert_eq!(iter.next(), None); let mut byte = digits.bytes::<{ FORMAT }>(); let mut iter = byte.integer_iter(); assert_eq!(iter.nth(4).unwrap(), &b'5'); assert_eq!(iter.as_slice(), &digits[digits.len()..]); assert_eq!(iter.as_ptr(), digits[digits.len()..].as_ptr()); } lexical-util-0.8.5/tests/mul_tests.rs000064400000000000000000000030450072674642500160130ustar 00000000000000use lexical_util::mul::{mul, mulhi}; use quickcheck::quickcheck; quickcheck! { #[cfg_attr(miri, ignore)] fn mul_u16_quickcheck(x: u16, y: u16) -> bool { let (hi, lo) = mul::(x, y); let hi = hi as u32; let lo = lo as u32; let expected = x as u32 * y as u32; ((hi << 16) | lo) == expected } #[cfg_attr(miri, ignore)] fn mul_u32_quickcheck(x: u32, y: u32) -> bool { let (hi, lo) = mul::(x, y); let hi = hi as u64; let lo = lo as u64; let expected = x as u64 * y as u64; ((hi << 32) | lo) == expected } #[cfg_attr(miri, ignore)] fn mul_u64_quickcheck(x: u64, y: u64) -> bool { let (hi, lo) = mul::(x, y); let hi = hi as u128; let lo = lo as u128; let expected = x as u128 * y as u128; ((hi << 64) | lo) == expected } #[cfg_attr(miri, ignore)] fn mulhi_u16_quickcheck(x: u16, y: u16) -> bool { let actual = mulhi::(x, y); let expected = (x as u32 * y as u32) >> 16; actual == expected as u16 } #[cfg_attr(miri, ignore)] fn mulhi_u32_quickcheck(x: u32, y: u32) -> bool { let actual = mulhi::(x, y); let expected = (x as u64 * y as u64) >> 32; actual == expected as u32 } #[cfg_attr(miri, ignore)] fn mulhi_u64_quickcheck(x: u64, y: u64) -> bool { let actual = mulhi::(x, y); let expected = (x as u128 * y as u128) >> 64; actual == expected as u64 } } lexical-util-0.8.5/tests/not_feature_format_tests.rs000064400000000000000000000053750072674642500211110ustar 00000000000000#![cfg(not(feature = "format"))] use lexical_util::format::{self, NumberFormat, STANDARD}; #[test] fn format_properties_test() { let format = NumberFormat::<{ STANDARD }> {}; assert_eq!(format.flags(), STANDARD & format::FLAG_MASK); assert_eq!(format.interface_flags(), STANDARD & format::INTERFACE_FLAG_MASK); assert_eq!(format.digit_separator(), b'\x00'); assert_eq!(format.base_prefix(), b'\x00'); assert_eq!(format.base_suffix(), b'\x00'); assert_eq!(format.mantissa_radix(), 10); assert_eq!(format.radix(), 10); assert_eq!(format.exponent_base(), 10); assert_eq!(format.exponent_radix(), 10); assert_eq!(format.required_integer_digits(), false); assert_eq!(format.required_fraction_digits(), false); assert_eq!(format.required_exponent_digits(), true); assert_eq!(format.required_mantissa_digits(), true); assert_eq!(format.required_digits(), true); assert_eq!(format.no_positive_mantissa_sign(), false); assert_eq!(format.required_mantissa_sign(), false); assert_eq!(format.no_exponent_notation(), false); assert_eq!(format.no_positive_exponent_sign(), false); assert_eq!(format.required_exponent_sign(), false); assert_eq!(format.no_exponent_without_fraction(), false); assert_eq!(format.no_special(), false); assert_eq!(format.case_sensitive_special(), false); assert_eq!(format.no_integer_leading_zeros(), false); assert_eq!(format.no_float_leading_zeros(), false); assert_eq!(format.required_exponent_notation(), false); assert_eq!(format.case_sensitive_exponent(), false); assert_eq!(format.case_sensitive_base_prefix(), false); assert_eq!(format.case_sensitive_base_suffix(), false); assert_eq!(format.integer_internal_digit_separator(), false); assert_eq!(format.fraction_internal_digit_separator(), false); assert_eq!(format.exponent_internal_digit_separator(), false); assert_eq!(format.internal_digit_separator(), false); assert_eq!(format.integer_leading_digit_separator(), false); assert_eq!(format.fraction_leading_digit_separator(), false); assert_eq!(format.exponent_leading_digit_separator(), false); assert_eq!(format.leading_digit_separator(), false); assert_eq!(format.integer_trailing_digit_separator(), false); assert_eq!(format.fraction_trailing_digit_separator(), false); assert_eq!(format.exponent_trailing_digit_separator(), false); assert_eq!(format.trailing_digit_separator(), false); assert_eq!(format.integer_consecutive_digit_separator(), false); assert_eq!(format.fraction_consecutive_digit_separator(), false); assert_eq!(format.exponent_consecutive_digit_separator(), false); assert_eq!(format.consecutive_digit_separator(), false); assert_eq!(format.special_digit_separator(), false); } lexical-util-0.8.5/tests/num_tests.rs000064400000000000000000000137230072674642500160210ustar 00000000000000use lexical_util::num; fn as_primitive(t: T) { let _: u8 = t.as_u8(); let _: u16 = t.as_u16(); let _: u32 = t.as_u32(); let _: u64 = t.as_u64(); let _: u128 = t.as_u128(); let _: usize = t.as_usize(); let _: i8 = t.as_i8(); let _: i16 = t.as_i16(); let _: i32 = t.as_i32(); let _: i64 = t.as_i64(); let _: i128 = t.as_i128(); let _: isize = t.as_isize(); let _: f32 = t.as_f32(); let _: f64 = t.as_f64(); } #[test] fn as_primitive_test() { as_primitive(1u8); as_primitive(1u16); as_primitive(1u32); as_primitive(1u64); as_primitive(1u128); as_primitive(1usize); as_primitive(1i8); as_primitive(1i16); as_primitive(1i32); as_primitive(1i64); as_primitive(1i128); as_primitive(1isize); as_primitive(1f32); as_primitive(1f64); } fn as_cast(t: T) { let _: i8 = num::as_cast(t); let _: i16 = num::as_cast(t); let _: i32 = num::as_cast(t); let _: i64 = num::as_cast(t); let _: i128 = num::as_cast(t); let _: isize = num::as_cast(t); let _: u8 = num::as_cast(t); let _: u16 = num::as_cast(t); let _: u32 = num::as_cast(t); let _: u64 = num::as_cast(t); let _: u128 = num::as_cast(t); let _: usize = num::as_cast(t); let _: f32 = num::as_cast(t); let _: f64 = num::as_cast(t); } #[test] fn as_cast_test() { as_cast(1u8); as_cast(1u16); as_cast(1u32); as_cast(1u64); as_cast(1u128); as_cast(1usize); as_cast(1i8); as_cast(1i16); as_cast(1i32); as_cast(1i64); as_cast(1i128); as_cast(1isize); as_cast(1f32); as_cast(1f64); } fn check_number(x: T, mut y: T) { // Copy, partialeq, partialord let _ = x; assert!(x < y); assert!(x != y); // Operations let _ = y + x; let _ = y - x; let _ = y * x; let _ = y / x; let _ = y % x; y += x; y -= x; y *= x; y /= x; y %= x; // Conversions already tested. } #[test] fn number_test() { check_number(1u8, 5); check_number(1u16, 5); check_number(1u32, 5); check_number(1u64, 5); check_number(1u128, 5); check_number(1usize, 5); check_number(1i8, 5); check_number(1i16, 5); check_number(1i32, 5); check_number(1i64, 5); check_number(1i128, 5); check_number(1isize, 5); check_number(1f32, 5.0); check_number(1f64, 5.0); } fn check_integer(mut x: T) { // Copy, partialeq, partialord, ord, eq let _ = x; assert!(x > T::ONE); assert!(x != T::ONE); assert_eq!(x.min(T::ONE), T::ONE); assert_eq!(x.max(T::ONE), x); // Operations let _ = x + T::ONE; let _ = x - T::ONE; let _ = x * T::ONE; let _ = x / T::ONE; let _ = x % T::ONE; x += T::ONE; x -= T::ONE; x *= T::ONE; x /= T::ONE; x %= T::ONE; // Bitwise operations let _ = x & T::ONE; let _ = x | T::ONE; let _ = x ^ T::ONE; x &= T::ONE; x |= T::ONE; x ^= T::ONE; // Bitshifts let _ = x << 1i32; let _ = x >> 1i32; x <<= 1i32; x >>= 1i32; // Conversions already tested. } #[test] fn integer_test() { check_integer(65u8); check_integer(65u16); check_integer(65u32); check_integer(65u64); check_integer(65u128); check_integer(65usize); check_integer(65i8); check_integer(65i16); check_integer(65i32); check_integer(65i64); check_integer(65i128); check_integer(65isize); } #[test] fn ceil_divmod_test() { use lexical_util::num::Integer; assert_eq!(5usize.ceil_divmod(7), (1, -2)); assert_eq!(0usize.ceil_divmod(7), (0, 0)); assert_eq!(35usize.ceil_divmod(7), (5, 0)); assert_eq!(36usize.ceil_divmod(7), (6, -6)); } #[cfg(feature = "floats")] fn check_float(mut x: T) { // Copy, partialeq, partialord let _ = x; assert!(x > T::ONE); assert!(x != T::ONE); // Operations let _ = x + T::ONE; let _ = x - T::ONE; let _ = x * T::ONE; let _ = x / T::ONE; let _ = x % T::ONE; let _ = -x; x += T::ONE; x -= T::ONE; x *= T::ONE; x /= T::ONE; x %= T::ONE; // Check functions let _ = x.to_bits(); assert_eq!(T::from_bits(x.to_bits()), x); let _ = x.is_sign_positive(); let _ = x.is_sign_negative(); let _ = x.ln(); let _ = x.floor(); // Check properties let _ = x.to_bits() & T::SIGN_MASK; let _ = x.to_bits() & T::EXPONENT_MASK; let _ = x.to_bits() & T::HIDDEN_BIT_MASK; let _ = x.to_bits() & T::MANTISSA_MASK; assert!(T::from_bits(T::INFINITY_BITS).is_special()); } #[test] #[cfg(feature = "floats")] fn float_test() { use lexical_util::num::Float; check_float(123f32); check_float(123f64); // b00000000000000000000000000000001 let f: f32 = 1e-45; assert!(f.is_odd()); assert!(f.next().is_even()); assert!(f.next_positive().is_even()); assert!(f.prev().is_even()); assert!(f.prev_positive().is_even()); assert!(f.round_positive_even().is_even()); assert_eq!(f.prev().next(), f); assert_eq!(f.prev_positive().next_positive(), f); assert_eq!(f.round_positive_even(), f.next()); // b00111101110011001100110011001101 let f: f32 = 0.1; assert!(f.is_odd()); assert!(f.next().is_even()); assert!(f.next_positive().is_even()); assert!(f.prev().is_even()); assert!(f.prev_positive().is_even()); assert!(f.round_positive_even().is_even()); assert_eq!(f.prev().next(), f); assert_eq!(f.prev_positive().next_positive(), f); assert_eq!(f.round_positive_even(), f.next()); // b01000000000000000000000000000000 let f: f32 = 1.0; assert!(f.is_even()); assert!(f.next().is_odd()); assert!(f.next_positive().is_odd()); assert!(f.prev().is_odd()); assert!(f.prev_positive().is_odd()); assert!(f.round_positive_even().is_even()); assert_eq!(f.prev().next(), f); assert_eq!(f.prev_positive().next_positive(), f); assert_ne!(f.round_positive_even(), f.next()); } lexical-util-0.8.5/tests/skip_tests.rs000064400000000000000000000660520072674642500161730ustar 00000000000000#![cfg(all(feature = "format", feature = "parse"))] use core::num; use lexical_util::format::{NumberFormat, NumberFormatBuilder}; use lexical_util::iterator::AsBytes; use static_assertions::const_assert; fn skip_iter_eq(input: &[u8], output: &[u8]) { // next is done in terms of peek, so we're safe here. let mut input = input.bytes::<{ FORMAT }>(); let mut output = output.bytes::<{ FORMAT }>(); assert!(input.integer_iter().eq(output.integer_iter())); } #[test] fn test_skip_iter_i() { // Test iterators that skip single, internal-only digit separators. pub const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .integer_internal_digit_separator(true) .build(); const_assert!(NumberFormat::<{ FORMAT }> {}.is_valid()); skip_iter_eq::<{ FORMAT }>(b"123.45", b"123.45"); skip_iter_eq::<{ FORMAT }>(b"1e45", b"1e45"); skip_iter_eq::<{ FORMAT }>(b"1e", b"1e"); skip_iter_eq::<{ FORMAT }>(b"1", b"1"); skip_iter_eq::<{ FORMAT }>(b"_45", b"_45"); skip_iter_eq::<{ FORMAT }>(b"__45", b"__45"); skip_iter_eq::<{ FORMAT }>(b"_.45", b"_.45"); skip_iter_eq::<{ FORMAT }>(b"__.45", b"__.45"); skip_iter_eq::<{ FORMAT }>(b"4_5", b"45"); skip_iter_eq::<{ FORMAT }>(b"4__5", b"4_5"); skip_iter_eq::<{ FORMAT }>(b"4_", b"4_"); skip_iter_eq::<{ FORMAT }>(b"4__", b"4__"); skip_iter_eq::<{ FORMAT }>(b"4_.", b"4_."); skip_iter_eq::<{ FORMAT }>(b"4__.", b"4__."); skip_iter_eq::<{ FORMAT }>(b"_45_5", b"_455"); skip_iter_eq::<{ FORMAT }>(b"__45__5", b"__45_5"); skip_iter_eq::<{ FORMAT }>(b"_.45_5", b"_.455"); skip_iter_eq::<{ FORMAT }>(b"__.45__5", b"__.45_5"); skip_iter_eq::<{ FORMAT }>(b"4_5_", b"45_"); skip_iter_eq::<{ FORMAT }>(b"4__5__", b"4_5__"); skip_iter_eq::<{ FORMAT }>(b"4_5_.5", b"45_.5"); skip_iter_eq::<{ FORMAT }>(b"4__5__.5", b"4_5__.5"); skip_iter_eq::<{ FORMAT }>(b"_45_", b"_45_"); skip_iter_eq::<{ FORMAT }>(b"__45__", b"__45__"); skip_iter_eq::<{ FORMAT }>(b"_45_.56", b"_45_.56"); skip_iter_eq::<{ FORMAT }>(b"__45__.56", b"__45__.56"); skip_iter_eq::<{ FORMAT }>(b"_4_5_", b"_45_"); skip_iter_eq::<{ FORMAT }>(b"__4__5__", b"__4_5__"); skip_iter_eq::<{ FORMAT }>(b"_4_5_.56", b"_45_.56"); skip_iter_eq::<{ FORMAT }>(b"__4__5__.56", b"__4_5__.56"); } #[test] fn test_skip_iter_l() { // Test iterators that skip single, leading-only digit separators. pub const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .integer_leading_digit_separator(true) .build(); const_assert!(NumberFormat::<{ FORMAT }> {}.is_valid()); skip_iter_eq::<{ FORMAT }>(b"123.45", b"123.45"); skip_iter_eq::<{ FORMAT }>(b"1e45", b"1e45"); skip_iter_eq::<{ FORMAT }>(b"1e", b"1e"); skip_iter_eq::<{ FORMAT }>(b"1", b"1"); skip_iter_eq::<{ FORMAT }>(b"_45", b"45"); skip_iter_eq::<{ FORMAT }>(b"__45", b"_45"); skip_iter_eq::<{ FORMAT }>(b"_.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"__.45", b"_.45"); skip_iter_eq::<{ FORMAT }>(b"4_5", b"4_5"); skip_iter_eq::<{ FORMAT }>(b"4__5", b"4__5"); skip_iter_eq::<{ FORMAT }>(b"4_", b"4_"); skip_iter_eq::<{ FORMAT }>(b"4__", b"4__"); skip_iter_eq::<{ FORMAT }>(b"4_.", b"4_."); skip_iter_eq::<{ FORMAT }>(b"4__.", b"4__."); skip_iter_eq::<{ FORMAT }>(b"_45_5", b"45_5"); skip_iter_eq::<{ FORMAT }>(b"__45__5", b"_45__5"); skip_iter_eq::<{ FORMAT }>(b"_.45_5", b".45_5"); skip_iter_eq::<{ FORMAT }>(b"__.45__5", b"_.45__5"); skip_iter_eq::<{ FORMAT }>(b"4_5_", b"4_5_"); skip_iter_eq::<{ FORMAT }>(b"4__5__", b"4__5__"); skip_iter_eq::<{ FORMAT }>(b"4_5_.5", b"4_5_.5"); skip_iter_eq::<{ FORMAT }>(b"4__5__.5", b"4__5__.5"); skip_iter_eq::<{ FORMAT }>(b"_45_", b"45_"); skip_iter_eq::<{ FORMAT }>(b"__45__", b"_45__"); skip_iter_eq::<{ FORMAT }>(b"_45_.56", b"45_.56"); skip_iter_eq::<{ FORMAT }>(b"__45__.56", b"_45__.56"); skip_iter_eq::<{ FORMAT }>(b"_4_5_", b"4_5_"); skip_iter_eq::<{ FORMAT }>(b"__4__5__", b"_4__5__"); skip_iter_eq::<{ FORMAT }>(b"_4_5_.56", b"4_5_.56"); skip_iter_eq::<{ FORMAT }>(b"__4__5__.56", b"_4__5__.56"); } #[test] fn test_skip_iter_t() { // Test iterators that skip single, trailing-only digit separators. pub const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .integer_trailing_digit_separator(true) .build(); const_assert!(NumberFormat::<{ FORMAT }> {}.is_valid()); skip_iter_eq::<{ FORMAT }>(b"123.45", b"123.45"); skip_iter_eq::<{ FORMAT }>(b"1e45", b"1e45"); skip_iter_eq::<{ FORMAT }>(b"1e", b"1e"); skip_iter_eq::<{ FORMAT }>(b"1", b"1"); skip_iter_eq::<{ FORMAT }>(b"_45", b"_45"); skip_iter_eq::<{ FORMAT }>(b"__45", b"__45"); skip_iter_eq::<{ FORMAT }>(b"_.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"__.45", b"_.45"); skip_iter_eq::<{ FORMAT }>(b"4_5", b"4_5"); skip_iter_eq::<{ FORMAT }>(b"4__5", b"4__5"); skip_iter_eq::<{ FORMAT }>(b"4_", b"4"); skip_iter_eq::<{ FORMAT }>(b"4__", b"4_"); skip_iter_eq::<{ FORMAT }>(b"4_.", b"4."); skip_iter_eq::<{ FORMAT }>(b"4__.", b"4_."); skip_iter_eq::<{ FORMAT }>(b"_45_5", b"_45_5"); skip_iter_eq::<{ FORMAT }>(b"__45__5", b"__45__5"); skip_iter_eq::<{ FORMAT }>(b"_.45_5", b".45_5"); skip_iter_eq::<{ FORMAT }>(b"__.45__5", b"_.45__5"); skip_iter_eq::<{ FORMAT }>(b"4_5_", b"4_5"); skip_iter_eq::<{ FORMAT }>(b"4__5__", b"4__5_"); skip_iter_eq::<{ FORMAT }>(b"4_5_.5", b"4_5.5"); skip_iter_eq::<{ FORMAT }>(b"4__5__.5", b"4__5_.5"); skip_iter_eq::<{ FORMAT }>(b"_45_", b"_45"); skip_iter_eq::<{ FORMAT }>(b"__45__", b"__45_"); skip_iter_eq::<{ FORMAT }>(b"_45_.56", b"_45.56"); skip_iter_eq::<{ FORMAT }>(b"__45__.56", b"__45_.56"); skip_iter_eq::<{ FORMAT }>(b"_4_5_", b"_4_5"); skip_iter_eq::<{ FORMAT }>(b"__4__5__", b"__4__5_"); skip_iter_eq::<{ FORMAT }>(b"_4_5_.56", b"_4_5.56"); skip_iter_eq::<{ FORMAT }>(b"__4__5__.56", b"__4__5_.56"); } #[test] fn test_skip_iter_il() { // Test iterators that skip single, internal or leading-only digit separators. pub const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .integer_internal_digit_separator(true) .integer_leading_digit_separator(true) .build(); const_assert!(NumberFormat::<{ FORMAT }> {}.is_valid()); skip_iter_eq::<{ FORMAT }>(b"123.45", b"123.45"); skip_iter_eq::<{ FORMAT }>(b"1e45", b"1e45"); skip_iter_eq::<{ FORMAT }>(b"1e", b"1e"); skip_iter_eq::<{ FORMAT }>(b"1", b"1"); skip_iter_eq::<{ FORMAT }>(b"_45", b"45"); skip_iter_eq::<{ FORMAT }>(b"__45", b"_45"); skip_iter_eq::<{ FORMAT }>(b"_.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"__.45", b"_.45"); skip_iter_eq::<{ FORMAT }>(b"4_5", b"45"); skip_iter_eq::<{ FORMAT }>(b"4__5", b"4_5"); skip_iter_eq::<{ FORMAT }>(b"4_", b"4_"); skip_iter_eq::<{ FORMAT }>(b"4__", b"4__"); skip_iter_eq::<{ FORMAT }>(b"4_.", b"4_."); skip_iter_eq::<{ FORMAT }>(b"4__.", b"4__."); skip_iter_eq::<{ FORMAT }>(b"_45_5", b"455"); skip_iter_eq::<{ FORMAT }>(b"__45__5", b"_45_5"); skip_iter_eq::<{ FORMAT }>(b"_.45_5", b".455"); skip_iter_eq::<{ FORMAT }>(b"__.45__5", b"_.45_5"); skip_iter_eq::<{ FORMAT }>(b"4_5_", b"45_"); skip_iter_eq::<{ FORMAT }>(b"4__5__", b"4_5__"); skip_iter_eq::<{ FORMAT }>(b"4_5_.5", b"45_.5"); skip_iter_eq::<{ FORMAT }>(b"4__5__.5", b"4_5__.5"); skip_iter_eq::<{ FORMAT }>(b"_45_", b"45_"); skip_iter_eq::<{ FORMAT }>(b"__45__", b"_45__"); skip_iter_eq::<{ FORMAT }>(b"_45_.56", b"45_.56"); skip_iter_eq::<{ FORMAT }>(b"__45__.56", b"_45__.56"); skip_iter_eq::<{ FORMAT }>(b"_4_5_", b"45_"); skip_iter_eq::<{ FORMAT }>(b"__4__5__", b"_4_5__"); skip_iter_eq::<{ FORMAT }>(b"_4_5_.56", b"45_.56"); skip_iter_eq::<{ FORMAT }>(b"__4__5__.56", b"_4_5__.56"); } #[test] fn test_skip_iter_it() { // Test iterators that skip single, internal or trailing-only digit separators. pub const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .integer_internal_digit_separator(true) .integer_trailing_digit_separator(true) .build(); const_assert!(NumberFormat::<{ FORMAT }> {}.is_valid()); skip_iter_eq::<{ FORMAT }>(b"123.45", b"123.45"); skip_iter_eq::<{ FORMAT }>(b"1e45", b"1e45"); skip_iter_eq::<{ FORMAT }>(b"1e", b"1e"); skip_iter_eq::<{ FORMAT }>(b"1", b"1"); skip_iter_eq::<{ FORMAT }>(b"_45", b"_45"); skip_iter_eq::<{ FORMAT }>(b"__45", b"__45"); skip_iter_eq::<{ FORMAT }>(b"_.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"__.45", b"_.45"); skip_iter_eq::<{ FORMAT }>(b"4_5", b"45"); skip_iter_eq::<{ FORMAT }>(b"4__5", b"4_5"); skip_iter_eq::<{ FORMAT }>(b"4_", b"4"); skip_iter_eq::<{ FORMAT }>(b"4__", b"4_"); skip_iter_eq::<{ FORMAT }>(b"4_.", b"4."); skip_iter_eq::<{ FORMAT }>(b"4__.", b"4_."); skip_iter_eq::<{ FORMAT }>(b"_45_5", b"_455"); skip_iter_eq::<{ FORMAT }>(b"__45__5", b"__45_5"); skip_iter_eq::<{ FORMAT }>(b"_.45_5", b".455"); skip_iter_eq::<{ FORMAT }>(b"__.45__5", b"_.45_5"); skip_iter_eq::<{ FORMAT }>(b"4_5_", b"45"); skip_iter_eq::<{ FORMAT }>(b"4__5__", b"4_5_"); skip_iter_eq::<{ FORMAT }>(b"4_5_.5", b"45.5"); skip_iter_eq::<{ FORMAT }>(b"4__5__.5", b"4_5_.5"); skip_iter_eq::<{ FORMAT }>(b"_45_", b"_45"); skip_iter_eq::<{ FORMAT }>(b"__45__", b"__45_"); skip_iter_eq::<{ FORMAT }>(b"_45_.56", b"_45.56"); skip_iter_eq::<{ FORMAT }>(b"__45__.56", b"__45_.56"); skip_iter_eq::<{ FORMAT }>(b"_4_5_", b"_45"); skip_iter_eq::<{ FORMAT }>(b"__4__5__", b"__4_5_"); skip_iter_eq::<{ FORMAT }>(b"_4_5_.56", b"_45.56"); skip_iter_eq::<{ FORMAT }>(b"__4__5__.56", b"__4_5_.56"); } #[test] fn test_skip_iter_lt() { // Test iterators that skip single, leading or trailing-only digit separators. pub const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .integer_leading_digit_separator(true) .integer_trailing_digit_separator(true) .build(); const_assert!(NumberFormat::<{ FORMAT }> {}.is_valid()); skip_iter_eq::<{ FORMAT }>(b"123.45", b"123.45"); skip_iter_eq::<{ FORMAT }>(b"1e45", b"1e45"); skip_iter_eq::<{ FORMAT }>(b"1e", b"1e"); skip_iter_eq::<{ FORMAT }>(b"1", b"1"); skip_iter_eq::<{ FORMAT }>(b"_45", b"45"); skip_iter_eq::<{ FORMAT }>(b"__45", b"_45"); skip_iter_eq::<{ FORMAT }>(b"_.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"__.45", b"_.45"); skip_iter_eq::<{ FORMAT }>(b"4_5", b"4_5"); skip_iter_eq::<{ FORMAT }>(b"4__5", b"4__5"); skip_iter_eq::<{ FORMAT }>(b"4_", b"4"); skip_iter_eq::<{ FORMAT }>(b"4__", b"4_"); skip_iter_eq::<{ FORMAT }>(b"4_.", b"4."); skip_iter_eq::<{ FORMAT }>(b"4__.", b"4_."); skip_iter_eq::<{ FORMAT }>(b"_45_5", b"45_5"); skip_iter_eq::<{ FORMAT }>(b"__45__5", b"_45__5"); skip_iter_eq::<{ FORMAT }>(b"_.45_5", b".45_5"); skip_iter_eq::<{ FORMAT }>(b"__.45__5", b"_.45__5"); skip_iter_eq::<{ FORMAT }>(b"4_5_", b"4_5"); skip_iter_eq::<{ FORMAT }>(b"4__5__", b"4__5_"); skip_iter_eq::<{ FORMAT }>(b"4_5_.5", b"4_5.5"); skip_iter_eq::<{ FORMAT }>(b"4__5__.5", b"4__5_.5"); skip_iter_eq::<{ FORMAT }>(b"_45_", b"45"); skip_iter_eq::<{ FORMAT }>(b"__45__", b"_45_"); skip_iter_eq::<{ FORMAT }>(b"_45_.56", b"45.56"); skip_iter_eq::<{ FORMAT }>(b"__45__.56", b"_45_.56"); skip_iter_eq::<{ FORMAT }>(b"_4_5_", b"4_5"); skip_iter_eq::<{ FORMAT }>(b"__4__5__", b"_4__5_"); skip_iter_eq::<{ FORMAT }>(b"_4_5_.56", b"4_5.56"); skip_iter_eq::<{ FORMAT }>(b"__4__5__.56", b"_4__5_.56"); } #[test] fn test_skip_iter_ilt() { // Test iterators that skip single digit separators. pub const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .integer_internal_digit_separator(true) .integer_leading_digit_separator(true) .integer_trailing_digit_separator(true) .build(); const_assert!(NumberFormat::<{ FORMAT }> {}.is_valid()); skip_iter_eq::<{ FORMAT }>(b"123.45", b"123.45"); skip_iter_eq::<{ FORMAT }>(b"1e45", b"1e45"); skip_iter_eq::<{ FORMAT }>(b"1e", b"1e"); skip_iter_eq::<{ FORMAT }>(b"1", b"1"); skip_iter_eq::<{ FORMAT }>(b"_45", b"45"); skip_iter_eq::<{ FORMAT }>(b"__45", b"_45"); skip_iter_eq::<{ FORMAT }>(b"_.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"__.45", b"_.45"); skip_iter_eq::<{ FORMAT }>(b"4_5", b"45"); skip_iter_eq::<{ FORMAT }>(b"4__5", b"4_5"); skip_iter_eq::<{ FORMAT }>(b"4_", b"4"); skip_iter_eq::<{ FORMAT }>(b"4__", b"4_"); skip_iter_eq::<{ FORMAT }>(b"4_.", b"4."); skip_iter_eq::<{ FORMAT }>(b"4__.", b"4_."); skip_iter_eq::<{ FORMAT }>(b"_45_5", b"455"); skip_iter_eq::<{ FORMAT }>(b"__45__5", b"_45_5"); skip_iter_eq::<{ FORMAT }>(b"_.45_5", b".455"); skip_iter_eq::<{ FORMAT }>(b"__.45__5", b"_.45_5"); skip_iter_eq::<{ FORMAT }>(b"4_5_", b"45"); skip_iter_eq::<{ FORMAT }>(b"4__5__", b"4_5_"); skip_iter_eq::<{ FORMAT }>(b"4_5_.5", b"45.5"); skip_iter_eq::<{ FORMAT }>(b"4__5__.5", b"4_5_.5"); skip_iter_eq::<{ FORMAT }>(b"_45_", b"45"); skip_iter_eq::<{ FORMAT }>(b"__45__", b"_45_"); skip_iter_eq::<{ FORMAT }>(b"_45_.56", b"45.56"); skip_iter_eq::<{ FORMAT }>(b"__45__.56", b"_45_.56"); skip_iter_eq::<{ FORMAT }>(b"_4_5_", b"45"); skip_iter_eq::<{ FORMAT }>(b"__4__5__", b"_4_5_"); skip_iter_eq::<{ FORMAT }>(b"_4_5_.56", b"45.56"); skip_iter_eq::<{ FORMAT }>(b"__4__5__.56", b"_4_5_.56"); } #[test] fn test_skip_iter_ic() { // Test iterators that skip multiple, internal digit separators. pub const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .integer_internal_digit_separator(true) .integer_consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ FORMAT }> {}.is_valid()); skip_iter_eq::<{ FORMAT }>(b"123.45", b"123.45"); skip_iter_eq::<{ FORMAT }>(b"1e45", b"1e45"); skip_iter_eq::<{ FORMAT }>(b"1e", b"1e"); skip_iter_eq::<{ FORMAT }>(b"1", b"1"); skip_iter_eq::<{ FORMAT }>(b"_45", b"_45"); skip_iter_eq::<{ FORMAT }>(b"__45", b"__45"); skip_iter_eq::<{ FORMAT }>(b"_.45", b"_.45"); skip_iter_eq::<{ FORMAT }>(b"__.45", b"__.45"); skip_iter_eq::<{ FORMAT }>(b"4_5", b"45"); skip_iter_eq::<{ FORMAT }>(b"4__5", b"45"); skip_iter_eq::<{ FORMAT }>(b"4_", b"4_"); skip_iter_eq::<{ FORMAT }>(b"4__", b"4__"); skip_iter_eq::<{ FORMAT }>(b"4_.", b"4_."); skip_iter_eq::<{ FORMAT }>(b"4__.", b"4__."); skip_iter_eq::<{ FORMAT }>(b"_45_5", b"_455"); skip_iter_eq::<{ FORMAT }>(b"__45__5", b"__455"); skip_iter_eq::<{ FORMAT }>(b"_.45_5", b"_.455"); skip_iter_eq::<{ FORMAT }>(b"__.45__5", b"__.455"); skip_iter_eq::<{ FORMAT }>(b"4_5_", b"45_"); skip_iter_eq::<{ FORMAT }>(b"4__5__", b"45__"); skip_iter_eq::<{ FORMAT }>(b"4_5_.5", b"45_.5"); skip_iter_eq::<{ FORMAT }>(b"4__5__.5", b"45__.5"); skip_iter_eq::<{ FORMAT }>(b"_45_", b"_45_"); skip_iter_eq::<{ FORMAT }>(b"__45__", b"__45__"); skip_iter_eq::<{ FORMAT }>(b"_45_.56", b"_45_.56"); skip_iter_eq::<{ FORMAT }>(b"__45__.56", b"__45__.56"); skip_iter_eq::<{ FORMAT }>(b"_4_5_", b"_45_"); skip_iter_eq::<{ FORMAT }>(b"__4__5__", b"__45__"); skip_iter_eq::<{ FORMAT }>(b"_4_5_.56", b"_45_.56"); skip_iter_eq::<{ FORMAT }>(b"__4__5__.56", b"__45__.56"); } #[test] fn test_skip_iter_lc() { // Test iterators that skip multiple, leading digit separators. pub const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .integer_leading_digit_separator(true) .integer_consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ FORMAT }> {}.is_valid()); skip_iter_eq::<{ FORMAT }>(b"123.45", b"123.45"); skip_iter_eq::<{ FORMAT }>(b"1e45", b"1e45"); skip_iter_eq::<{ FORMAT }>(b"1e", b"1e"); skip_iter_eq::<{ FORMAT }>(b"1", b"1"); skip_iter_eq::<{ FORMAT }>(b"_45", b"45"); skip_iter_eq::<{ FORMAT }>(b"__45", b"45"); skip_iter_eq::<{ FORMAT }>(b"_.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"__.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"4_5", b"4_5"); skip_iter_eq::<{ FORMAT }>(b"4__5", b"4__5"); skip_iter_eq::<{ FORMAT }>(b"4_", b"4_"); skip_iter_eq::<{ FORMAT }>(b"4__", b"4__"); skip_iter_eq::<{ FORMAT }>(b"4_.", b"4_."); skip_iter_eq::<{ FORMAT }>(b"4__.", b"4__."); skip_iter_eq::<{ FORMAT }>(b"_45_5", b"45_5"); skip_iter_eq::<{ FORMAT }>(b"__45__5", b"45__5"); skip_iter_eq::<{ FORMAT }>(b"_.45_5", b".45_5"); skip_iter_eq::<{ FORMAT }>(b"__.45__5", b".45__5"); skip_iter_eq::<{ FORMAT }>(b"4_5_", b"4_5_"); skip_iter_eq::<{ FORMAT }>(b"4__5__", b"4__5__"); skip_iter_eq::<{ FORMAT }>(b"4_5_.5", b"4_5_.5"); skip_iter_eq::<{ FORMAT }>(b"4__5__.5", b"4__5__.5"); skip_iter_eq::<{ FORMAT }>(b"_45_", b"45_"); skip_iter_eq::<{ FORMAT }>(b"__45__", b"45__"); skip_iter_eq::<{ FORMAT }>(b"_45_.56", b"45_.56"); skip_iter_eq::<{ FORMAT }>(b"__45__.56", b"45__.56"); skip_iter_eq::<{ FORMAT }>(b"_4_5_", b"4_5_"); skip_iter_eq::<{ FORMAT }>(b"__4__5__", b"4__5__"); skip_iter_eq::<{ FORMAT }>(b"_4_5_.56", b"4_5_.56"); skip_iter_eq::<{ FORMAT }>(b"__4__5__.56", b"4__5__.56"); } #[test] fn test_skip_iter_tc() { // Test iterators that skip multiple, trailing digit separators. pub const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .integer_trailing_digit_separator(true) .integer_consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ FORMAT }> {}.is_valid()); skip_iter_eq::<{ FORMAT }>(b"123.45", b"123.45"); skip_iter_eq::<{ FORMAT }>(b"1e45", b"1e45"); skip_iter_eq::<{ FORMAT }>(b"1e", b"1e"); skip_iter_eq::<{ FORMAT }>(b"1", b"1"); skip_iter_eq::<{ FORMAT }>(b"_45", b"_45"); skip_iter_eq::<{ FORMAT }>(b"__45", b"__45"); skip_iter_eq::<{ FORMAT }>(b"_.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"__.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"4_5", b"4_5"); skip_iter_eq::<{ FORMAT }>(b"4__5", b"4__5"); skip_iter_eq::<{ FORMAT }>(b"4_", b"4"); skip_iter_eq::<{ FORMAT }>(b"4__", b"4"); skip_iter_eq::<{ FORMAT }>(b"4_.", b"4."); skip_iter_eq::<{ FORMAT }>(b"4__.", b"4."); skip_iter_eq::<{ FORMAT }>(b"_45_5", b"_45_5"); skip_iter_eq::<{ FORMAT }>(b"__45__5", b"__45__5"); skip_iter_eq::<{ FORMAT }>(b"_.45_5", b".45_5"); skip_iter_eq::<{ FORMAT }>(b"__.45__5", b".45__5"); skip_iter_eq::<{ FORMAT }>(b"4_5_", b"4_5"); skip_iter_eq::<{ FORMAT }>(b"4__5__", b"4__5"); skip_iter_eq::<{ FORMAT }>(b"4_5_.5", b"4_5.5"); skip_iter_eq::<{ FORMAT }>(b"4__5__.5", b"4__5.5"); skip_iter_eq::<{ FORMAT }>(b"_45_", b"_45"); skip_iter_eq::<{ FORMAT }>(b"__45__", b"__45"); skip_iter_eq::<{ FORMAT }>(b"_45_.56", b"_45.56"); skip_iter_eq::<{ FORMAT }>(b"__45__.56", b"__45.56"); skip_iter_eq::<{ FORMAT }>(b"_4_5_", b"_4_5"); skip_iter_eq::<{ FORMAT }>(b"__4__5__", b"__4__5"); skip_iter_eq::<{ FORMAT }>(b"_4_5_.56", b"_4_5.56"); skip_iter_eq::<{ FORMAT }>(b"__4__5__.56", b"__4__5.56"); } #[test] fn test_skip_iter_ilc() { // Test iterators that skip multiple, internal or leading digit separators. pub const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .integer_internal_digit_separator(true) .integer_leading_digit_separator(true) .integer_consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ FORMAT }> {}.is_valid()); skip_iter_eq::<{ FORMAT }>(b"123.45", b"123.45"); skip_iter_eq::<{ FORMAT }>(b"1e45", b"1e45"); skip_iter_eq::<{ FORMAT }>(b"1e", b"1e"); skip_iter_eq::<{ FORMAT }>(b"1", b"1"); skip_iter_eq::<{ FORMAT }>(b"_45", b"45"); skip_iter_eq::<{ FORMAT }>(b"__45", b"45"); skip_iter_eq::<{ FORMAT }>(b"_.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"__.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"4_5", b"45"); skip_iter_eq::<{ FORMAT }>(b"4__5", b"45"); skip_iter_eq::<{ FORMAT }>(b"4_", b"4_"); skip_iter_eq::<{ FORMAT }>(b"4__", b"4__"); skip_iter_eq::<{ FORMAT }>(b"4_.", b"4_."); skip_iter_eq::<{ FORMAT }>(b"4__.", b"4__."); skip_iter_eq::<{ FORMAT }>(b"_45_5", b"455"); skip_iter_eq::<{ FORMAT }>(b"__45__5", b"455"); skip_iter_eq::<{ FORMAT }>(b"_.45_5", b".455"); skip_iter_eq::<{ FORMAT }>(b"__.45__5", b".455"); skip_iter_eq::<{ FORMAT }>(b"4_5_", b"45_"); skip_iter_eq::<{ FORMAT }>(b"4__5__", b"45__"); skip_iter_eq::<{ FORMAT }>(b"4_5_.5", b"45_.5"); skip_iter_eq::<{ FORMAT }>(b"4__5__.5", b"45__.5"); skip_iter_eq::<{ FORMAT }>(b"_45_", b"45_"); skip_iter_eq::<{ FORMAT }>(b"__45__", b"45__"); skip_iter_eq::<{ FORMAT }>(b"_45_.56", b"45_.56"); skip_iter_eq::<{ FORMAT }>(b"__45__.56", b"45__.56"); skip_iter_eq::<{ FORMAT }>(b"_4_5_", b"45_"); skip_iter_eq::<{ FORMAT }>(b"__4__5__", b"45__"); skip_iter_eq::<{ FORMAT }>(b"_4_5_.56", b"45_.56"); skip_iter_eq::<{ FORMAT }>(b"__4__5__.56", b"45__.56"); } #[test] fn test_skip_iter_itc() { // Test iterators that skip multiple, internal or trailing digit separators. pub const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .integer_internal_digit_separator(true) .integer_trailing_digit_separator(true) .integer_consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ FORMAT }> {}.is_valid()); skip_iter_eq::<{ FORMAT }>(b"123.45", b"123.45"); skip_iter_eq::<{ FORMAT }>(b"1e45", b"1e45"); skip_iter_eq::<{ FORMAT }>(b"1e", b"1e"); skip_iter_eq::<{ FORMAT }>(b"1", b"1"); skip_iter_eq::<{ FORMAT }>(b"_45", b"_45"); skip_iter_eq::<{ FORMAT }>(b"__45", b"__45"); skip_iter_eq::<{ FORMAT }>(b"_.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"__.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"4_5", b"45"); skip_iter_eq::<{ FORMAT }>(b"4__5", b"45"); skip_iter_eq::<{ FORMAT }>(b"4_", b"4"); skip_iter_eq::<{ FORMAT }>(b"4__", b"4"); skip_iter_eq::<{ FORMAT }>(b"4_.", b"4."); skip_iter_eq::<{ FORMAT }>(b"4__.", b"4."); skip_iter_eq::<{ FORMAT }>(b"_45_5", b"_455"); skip_iter_eq::<{ FORMAT }>(b"__45__5", b"__455"); skip_iter_eq::<{ FORMAT }>(b"_.45_5", b".455"); skip_iter_eq::<{ FORMAT }>(b"__.45__5", b".455"); skip_iter_eq::<{ FORMAT }>(b"4_5_", b"45"); skip_iter_eq::<{ FORMAT }>(b"4__5__", b"45"); skip_iter_eq::<{ FORMAT }>(b"4_5_.5", b"45.5"); skip_iter_eq::<{ FORMAT }>(b"4__5__.5", b"45.5"); skip_iter_eq::<{ FORMAT }>(b"_45_", b"_45"); skip_iter_eq::<{ FORMAT }>(b"__45__", b"__45"); skip_iter_eq::<{ FORMAT }>(b"_45_.56", b"_45.56"); skip_iter_eq::<{ FORMAT }>(b"__45__.56", b"__45.56"); skip_iter_eq::<{ FORMAT }>(b"_4_5_", b"_45"); skip_iter_eq::<{ FORMAT }>(b"__4__5__", b"__45"); skip_iter_eq::<{ FORMAT }>(b"_4_5_.56", b"_45.56"); skip_iter_eq::<{ FORMAT }>(b"__4__5__.56", b"__45.56"); } #[test] fn test_skip_iter_ltc() { // Test iterators that skip multiple, leading or trailing digit separators. pub const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .integer_leading_digit_separator(true) .integer_trailing_digit_separator(true) .integer_consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ FORMAT }> {}.is_valid()); skip_iter_eq::<{ FORMAT }>(b"123.45", b"123.45"); skip_iter_eq::<{ FORMAT }>(b"1e45", b"1e45"); skip_iter_eq::<{ FORMAT }>(b"1e", b"1e"); skip_iter_eq::<{ FORMAT }>(b"1", b"1"); skip_iter_eq::<{ FORMAT }>(b"_45", b"45"); skip_iter_eq::<{ FORMAT }>(b"__45", b"45"); skip_iter_eq::<{ FORMAT }>(b"_.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"__.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"4_5", b"4_5"); skip_iter_eq::<{ FORMAT }>(b"4__5", b"4__5"); skip_iter_eq::<{ FORMAT }>(b"4_", b"4"); skip_iter_eq::<{ FORMAT }>(b"4__", b"4"); skip_iter_eq::<{ FORMAT }>(b"4_.", b"4."); skip_iter_eq::<{ FORMAT }>(b"4__.", b"4."); skip_iter_eq::<{ FORMAT }>(b"_45_5", b"45_5"); skip_iter_eq::<{ FORMAT }>(b"__45__5", b"45__5"); skip_iter_eq::<{ FORMAT }>(b"_.45_5", b".45_5"); skip_iter_eq::<{ FORMAT }>(b"__.45__5", b".45__5"); skip_iter_eq::<{ FORMAT }>(b"4_5_", b"4_5"); skip_iter_eq::<{ FORMAT }>(b"4__5__", b"4__5"); skip_iter_eq::<{ FORMAT }>(b"4_5_.5", b"4_5.5"); skip_iter_eq::<{ FORMAT }>(b"4__5__.5", b"4__5.5"); skip_iter_eq::<{ FORMAT }>(b"_45_", b"45"); skip_iter_eq::<{ FORMAT }>(b"__45__", b"45"); skip_iter_eq::<{ FORMAT }>(b"_45_.56", b"45.56"); skip_iter_eq::<{ FORMAT }>(b"__45__.56", b"45.56"); skip_iter_eq::<{ FORMAT }>(b"_4_5_", b"4_5"); skip_iter_eq::<{ FORMAT }>(b"__4__5__", b"4__5"); skip_iter_eq::<{ FORMAT }>(b"_4_5_.56", b"4_5.56"); skip_iter_eq::<{ FORMAT }>(b"__4__5__.56", b"4__5.56"); } #[test] fn test_skip_iter_iltc() { // Test iterators that skip multiple digit separators. pub const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'_')) .integer_internal_digit_separator(true) .integer_leading_digit_separator(true) .integer_trailing_digit_separator(true) .integer_consecutive_digit_separator(true) .build(); const_assert!(NumberFormat::<{ FORMAT }> {}.is_valid()); skip_iter_eq::<{ FORMAT }>(b"123.45", b"123.45"); skip_iter_eq::<{ FORMAT }>(b"1e45", b"1e45"); skip_iter_eq::<{ FORMAT }>(b"1e", b"1e"); skip_iter_eq::<{ FORMAT }>(b"1", b"1"); skip_iter_eq::<{ FORMAT }>(b"_45", b"45"); skip_iter_eq::<{ FORMAT }>(b"__45", b"45"); skip_iter_eq::<{ FORMAT }>(b"_.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"__.45", b".45"); skip_iter_eq::<{ FORMAT }>(b"4_5", b"45"); skip_iter_eq::<{ FORMAT }>(b"4__5", b"45"); skip_iter_eq::<{ FORMAT }>(b"4_", b"4"); skip_iter_eq::<{ FORMAT }>(b"4__", b"4"); skip_iter_eq::<{ FORMAT }>(b"4_.", b"4."); skip_iter_eq::<{ FORMAT }>(b"4__.", b"4."); skip_iter_eq::<{ FORMAT }>(b"_45_5", b"455"); skip_iter_eq::<{ FORMAT }>(b"__45__5", b"455"); skip_iter_eq::<{ FORMAT }>(b"_.45_5", b".455"); skip_iter_eq::<{ FORMAT }>(b"__.45__5", b".455"); skip_iter_eq::<{ FORMAT }>(b"4_5_", b"45"); skip_iter_eq::<{ FORMAT }>(b"4__5__", b"45"); skip_iter_eq::<{ FORMAT }>(b"4_5_.5", b"45.5"); skip_iter_eq::<{ FORMAT }>(b"4__5__.5", b"45.5"); skip_iter_eq::<{ FORMAT }>(b"_45_", b"45"); skip_iter_eq::<{ FORMAT }>(b"__45__", b"45"); skip_iter_eq::<{ FORMAT }>(b"_45_.56", b"45.56"); skip_iter_eq::<{ FORMAT }>(b"__45__.56", b"45.56"); skip_iter_eq::<{ FORMAT }>(b"_4_5_", b"45"); skip_iter_eq::<{ FORMAT }>(b"__4__5__", b"45"); skip_iter_eq::<{ FORMAT }>(b"_4_5_.56", b"45.56"); skip_iter_eq::<{ FORMAT }>(b"__4__5__.56", b"45.56"); }