From 36599c3ae6d78301e0177bbbefa9ea02aafb3968 Mon Sep 17 00:00:00 2001 From: Alex Huszagh Date: Thu, 23 Jan 2025 20:20:51 -0600 Subject: [PATCH] Adds shell of logic for toggling sign logic. This enables toggling no unsigned integer negative signs, and having no signs (even negative) for mantissas and exponents. This commit is broken and will not work for the new additions in parsing. --- CHANGELOG | 1 + lexical-util/src/error.rs | 16 ++ lexical-util/src/feature_format.rs | 91 +++++++ lexical-util/src/format_builder.rs | 355 ++++++++++++++++++++++--- lexical-util/src/format_flags.rs | 21 +- lexical-util/src/not_feature_format.rs | 99 ++++++- 6 files changed, 545 insertions(+), 38 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 21b0682b..74c6392d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `NumberFormatBuilder::none()` for create a format with no flags set (#215). - Added in many more digit separator flags for the `NumberFormat`, including for signs, base prefixes, base suffixes, and restricting digit separators at the start of the number (#215). - Added many more pre-defined formatting constants (#215). +- Added additional sign configurations, with `no_unsigned_negative_sign`, `no_mantissa_sign`, and `no_exponent_sign` (#215). ### Changed diff --git a/lexical-util/src/error.rs b/lexical-util/src/error.rs index 8b55f2d4..99e68e65 100644 --- a/lexical-util/src/error.rs +++ b/lexical-util/src/error.rs @@ -32,12 +32,16 @@ pub enum Error { EmptyFraction(usize), /// Invalid positive mantissa sign was found. InvalidPositiveMantissaSign(usize), + /// Invalid negative mantissa sign was found. + InvalidNegativeMantissaSign(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), + /// Invalid negative exponent sign was found. + InvalidNegativeExponentSign(usize), /// Exponent sign was required(usize), but not found. MissingExponentSign(usize), /// Exponent was present without fraction component. @@ -159,9 +163,11 @@ impl Error { Self::EmptyInteger(_) => "'invalid float with no integer digits'", Self::EmptyFraction(_) => "'invalid float with no fraction digits'", Self::InvalidPositiveMantissaSign(_) => "'invalid `+` sign before significant digits'", + Self::InvalidNegativeMantissaSign(_) => "'invalid `-` sign before significant digits'", Self::MissingMantissaSign(_) => "'missing required `+/-` sign for significant digits'", Self::InvalidExponent(_) => "'exponent found but not allowed'", Self::InvalidPositiveExponentSign(_) => "'invalid `+` sign in exponent'", + Self::InvalidNegativeExponentSign(_) => "'invalid `-` sign in exponent'", Self::MissingExponentSign(_) => "'missing required `+/-` sign for exponent'", Self::ExponentWithoutFraction(_) => "'invalid float containing exponent without fraction'", Self::ExponentWithoutIntegerDigits(_) => "'invalid float containing exponent without integer digits'", @@ -227,9 +233,11 @@ impl Error { Self::EmptyInteger(index) => Some(index), Self::EmptyFraction(index) => Some(index), Self::InvalidPositiveMantissaSign(index) => Some(index), + Self::InvalidNegativeMantissaSign(index) => Some(index), Self::MissingMantissaSign(index) => Some(index), Self::InvalidExponent(index) => Some(index), Self::InvalidPositiveExponentSign(index) => Some(index), + Self::InvalidNegativeExponentSign(index) => Some(index), Self::MissingExponentSign(index) => Some(index), Self::ExponentWithoutFraction(index) => Some(index), Self::ExponentWithoutIntegerDigits(index) => Some(index), @@ -290,9 +298,11 @@ impl Error { 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_invalid_negative_mantissa_sign, InvalidNegativeMantissaSign(_)); 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_invalid_negative_exponent_sign, InvalidNegativeExponentSign(_)); is_error_type!(is_missing_exponent_sign, MissingExponentSign(_)); is_error_type!(is_exponent_without_fraction, ExponentWithoutFraction(_)); is_error_type!(is_invalid_leading_zeros, InvalidLeadingZeros(_)); @@ -380,11 +390,17 @@ impl fmt::Display for Error { Self::InvalidPositiveMantissaSign(index) => { write_parse_error!(formatter, description, index) }, + Self::InvalidNegativeMantissaSign(index) => { + write_parse_error!(formatter, description, index) + }, Self::MissingMantissaSign(index) => write_parse_error!(formatter, description, index), Self::InvalidExponent(index) => write_parse_error!(formatter, description, index), Self::InvalidPositiveExponentSign(index) => { write_parse_error!(formatter, description, index) }, + Self::InvalidNegativeExponentSign(index) => { + write_parse_error!(formatter, description, index) + }, Self::MissingExponentSign(index) => write_parse_error!(formatter, description, index), Self::ExponentWithoutFraction(index) => { write_parse_error!(formatter, description, index) diff --git a/lexical-util/src/feature_format.rs b/lexical-util/src/feature_format.rs index 7e8fd005..762a354f 100644 --- a/lexical-util/src/feature_format.rs +++ b/lexical-util/src/feature_format.rs @@ -820,6 +820,97 @@ impl NumberFormat { Self::REQUIRED_BASE_SUFFIX } + /// If a negative sign before an unsigned integer is not allowed. + /// + /// See [`no_unsigned_negative_sign`][Self::no_unsigned_negative_sign]. + pub const NO_UNSIGNED_NEGATIVE_SIGN: bool = from_flag!(FORMAT, NO_UNSIGNED_NEGATIVE_SIGN); + + /// If a negative sign before an unsigned integer is not allowed. + /// + /// Can only be modified with [`feature`][crate#features] `format`. This does + /// not apply to signed integers or floating point numbers. Defaults to [`true`]. + /// + /// # Examples + /// + /// | Input | Valid? | + /// |:-:|:-:| + /// | `-12` | ❌ | + /// | `+12` | ✔️ | + /// | `12` | ✔️ | + /// + /// # Used For + /// + /// - Parse Integer + #[inline(always)] + pub const fn no_unsigned_negative_sign(&self) -> bool { + Self::NO_UNSIGNED_NEGATIVE_SIGN + } + + /// If positive or negative signs before the significant digits are not allowed. + /// + /// See [`no_mantissa_sign`][Self::no_mantissa_sign]. + pub const NO_MANTISSA_SIGN: bool = from_flag!(FORMAT, NO_MANTISSA_SIGN); + + /// If positive or negative signs before the significant digits are not allowed. + /// + /// Can only be modified with [`feature`][crate#features] `format`. if enabled, then + /// the type cannot represent negative literal or string values (although they may + /// be computed via mathematical operations). Defaults to [`false`]. + /// + /// If you only want to disable positive signs, see [`no_positive_mantissa_sign`]. + /// If you wish to disable negative signs on unsigned integers, see + /// [`no_unsigned_negative_sign`]. + /// + /// [`no_positive_mantissa_sign`]: Self::no_positive_mantissa_sign + /// [`no_unsigned_negative_sign`]: Self::no_unsigned_negative_sign + /// + /// # Examples + /// + /// | Input | Valid? | + /// |:-:|:-:| + /// | `-12` | ❌ | + /// | `+12` | ❌ | + /// | `12` | ✔️ | + /// + /// # Used For + /// + /// - Parse Integer + /// - Parse Float + #[inline(always)] + pub const fn no_mantissa_sign(&self) -> bool { + Self::NO_MANTISSA_SIGN + } + + /// If positive or negative signs before an exponent are not allowed. + /// + /// See [`no_exponent_sign`][Self::no_exponent_sign]. + pub const NO_EXPONENT_SIGN: bool = from_flag!(FORMAT, NO_EXPONENT_SIGN); + + /// If positive or negative signs before an exponent are not allowed. + /// + /// Can only be modified with [`feature`][crate#features] `format`. Defaults + /// to [`false`]. + /// + /// If you only want to disable positive signs, see [`no_positive_exponent_sign`]. + /// + /// [`no_positive_exponent_sign`]: Self::no_positive_exponent_sign + /// + /// # Examples + /// + /// | Input | Valid? | + /// |:-:|:-:| + /// | `1.0e-12` | ❌ | + /// | `1.0e+12` | ❌ | + /// | `1.0e12` | ✔️ | + /// + /// # Used For + /// + /// - Parse Float + #[inline(always)] + pub const fn no_exponent_sign(&self) -> bool { + Self::NO_EXPONENT_SIGN + } + // DIGIT SEPARATOR FLAGS & MASKS /// If digit separators are allowed at the absolute start of the number. diff --git a/lexical-util/src/format_builder.rs b/lexical-util/src/format_builder.rs index d59a9526..4c11b47e 100644 --- a/lexical-util/src/format_builder.rs +++ b/lexical-util/src/format_builder.rs @@ -135,6 +135,12 @@ const fn unwrap_or_zero(option: OptionU8) -> u8 { /// - [`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. +/// - [`no_unsigned_negative_sign`]: If a negative sign before an unsigned +/// integer is not allowed. +/// - [`no_mantissa_sign`]: If positive or negative signs before an exponent are +/// not allowed. +/// - [`no_exponent_sign`]: If positive or negative signs before an exponent are +/// not allowed. /// - [`start_digit_separator`]: If digit separators are allowed at the absolute /// start of the number. /// - [`integer_sign_digit_separator`]: If digit separators are allowed before @@ -251,6 +257,44 @@ const fn unwrap_or_zero(option: OptionU8) -> u8 { /// allowed. /// - [`required_exponent_sign`]: If sign before the exponent is required. /// - [`required_exponent_notation`]: If exponent notation is required. +/// - [`case_sensitive_base_prefix`]: If base prefixes are case-sensitive. +/// - [`case_sensitive_base_suffix`]: If base suffixes are case-sensitive. +/// - [`no_unsigned_negative_sign`]: If a negative sign before an unsigned +/// integer is not allowed. +/// - [`no_mantissa_sign`]: If positive or negative signs before an exponent are +/// not allowed. +/// - [`no_exponent_sign`]: If positive or negative signs before an exponent are +/// not allowed. +/// - [`start_digit_separator`]: If digit separators are allowed at the absolute +/// start of the number. +/// - [`integer_sign_digit_separator`]: If digit separators are allowed before +/// the sign of the integer. +/// - [`integer_consecutive_sign_digit_separator`]: If consecutive digit +/// separators are allowed before the sign of the integer. +/// - [`base_prefix_internal_digit_separator`]: If a digit separator is allowed +/// between the base prefix. +/// - [`base_prefix_leading_digit_separator`]: If a digit separator is allowed +/// before the base prefix. +/// - [`base_prefix_trailing_digit_separator`]: If a digit separator is allowed +/// after the base prefix. +/// - [`base_prefix_consecutive_digit_separator`]: If multiple consecutive base +/// prefix digit separators are allowed. +/// - [`base_suffix_internal_digit_separator`]: If a digit separator is allowed +/// between the base suffix. +/// - [`base_suffix_leading_digit_separator`]: If a digit separator is allowed +/// before the base suffix. +/// - [`base_suffix_trailing_digit_separator`]: If a digit separator is allowed +/// after the base suffix. +/// - [`base_suffix_consecutive_digit_separator`]: If multiple consecutive base +/// suffix digit separators are allowed. +/// - [`integer_internal_digit_separator`]: If digit separators are allowed +/// between integer digits. +/// - [`integer_leading_digit_separator`]: If a digit separator is allowed +/// before any integer digits. +/// - [`integer_trailing_digit_separator`]: If a digit separator is allowed +/// after any integer digits. +/// - [`integer_consecutive_digit_separator`]: If multiple consecutive integer +/// digit separators are allowed. /// /// # Parse Float Fields /// @@ -296,6 +340,12 @@ const fn unwrap_or_zero(option: OptionU8) -> u8 { /// - [`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. +/// - [`no_unsigned_negative_sign`]: If a negative sign before an unsigned +/// integer is not allowed. +/// - [`no_mantissa_sign`]: If positive or negative signs before an exponent are +/// not allowed. +/// - [`no_exponent_sign`]: If positive or negative signs before an exponent are +/// not allowed. /// - [`start_digit_separator`]: If digit separators are allowed at the absolute /// start of the number. /// - [`integer_sign_digit_separator`]: If digit separators are allowed before @@ -385,19 +435,14 @@ const fn unwrap_or_zero(option: OptionU8) -> u8 { [`required_fraction_digits_with_exponent`]: Self::required_fraction_digits_with_exponent\n [`required_mantissa_digits_with_exponent`]: Self::required_mantissa_digits_with_exponent\n [`case_sensitive_exponent`]: Self::case_sensitive_exponent\n +[`no_unsigned_negative_sign`]: Self::no_unsigned_negative_sign\n +[`no_mantissa_sign`]: Self::no_mantissa_sign\n +[`no_exponent_sign`]: Self::no_exponent_sign\n [`start_digit_separator`]: Self::start_digit_separator\n [`integer_sign_digit_separator`]: Self::integer_sign_digit_separator\n [`integer_consecutive_sign_digit_separator`]: Self::integer_consecutive_sign_digit_separator\n [`exponent_sign_digit_separator`]: Self::exponent_sign_digit_separator\n [`exponent_consecutive_sign_digit_separator`]: Self::exponent_consecutive_sign_digit_separator\n -[`base_prefix_internal_digit_separator`]: Self::base_prefix_internal_digit_separator\n -[`base_prefix_leading_digit_separator`]: Self::base_prefix_leading_digit_separator\n -[`base_prefix_trailing_digit_separator`]: Self::base_prefix_trailing_digit_separator\n -[`base_prefix_consecutive_digit_separator`]: Self::base_prefix_consecutive_digit_separator\n -[`base_suffix_internal_digit_separator`]: Self::base_suffix_internal_digit_separator\n -[`base_suffix_leading_digit_separator`]: Self::base_suffix_leading_digit_separator\n -[`base_suffix_trailing_digit_separator`]: Self::base_suffix_trailing_digit_separator\n -[`base_suffix_consecutive_digit_separator`]: Self::base_suffix_consecutive_digit_separator\n [`integer_internal_digit_separator`]: Self::integer_internal_digit_separator\n [`fraction_internal_digit_separator`]: Self::fraction_internal_digit_separator\n [`exponent_internal_digit_separator`]: Self::exponent_internal_digit_separator\n @@ -435,19 +480,14 @@ const fn unwrap_or_zero(option: OptionU8) -> u8 { [`required_fraction_digits_with_exponent`]: https://github.com/Alexhuszagh/rust-lexical/blob/0cad692/lexical-util/src/format_builder.rs#L1149\n [`required_mantissa_digits_with_exponent`]: https://github.com/Alexhuszagh/rust-lexical/blob/47a090d/lexical-util/src/format_builder.rs#L1233\n [`case_sensitive_exponent`]: https://github.com/Alexhuszagh/rust-lexical/blob/c6c5052/lexical-util/src/format_builder.rs#L765\n +[`no_unsigned_negative_sign`]: https://github.com/Alexhuszagh/rust-lexical/blob/TODO/lexical-util/src/format_builder.rs#LTODO\n +[`no_mantissa_sign`]: https://github.com/Alexhuszagh/rust-lexical/blob/TODO/lexical-util/src/format_builder.rs#LTODO\n +[`no_exponent_sign`]: https://github.com/Alexhuszagh/rust-lexical/blob/TODO/lexical-util/src/format_builder.rs#LTODO\n [`start_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1650\n [`integer_sign_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1678\n [`integer_consecutive_sign_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1706\n [`exponent_sign_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1728\n [`exponent_consecutive_sign_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1754\n -[`base_prefix_internal_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1777\n -[`base_prefix_leading_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1809\n -[`base_prefix_trailing_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1841\n -[`base_prefix_consecutive_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1870\n -[`base_suffix_internal_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1883\n -[`base_suffix_leading_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1916\n -[`base_suffix_trailing_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1939\n -[`base_suffix_consecutive_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1967\n [`integer_internal_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/c6c5052/lexical-util/src/format_builder.rs#L793\n [`fraction_internal_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/c6c5052/lexical-util/src/format_builder.rs#L805\n [`exponent_internal_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/c6c5052/lexical-util/src/format_builder.rs#L817\n @@ -471,6 +511,14 @@ const fn unwrap_or_zero(option: OptionU8) -> u8 { [`case_sensitive_base_suffix`]: Self::case_sensitive_base_suffix [`required_base_prefix`]: Self::required_base_prefix [`required_base_suffix`]: Self::required_base_suffix +[`base_prefix_internal_digit_separator`]: Self::base_prefix_internal_digit_separator\n +[`base_prefix_leading_digit_separator`]: Self::base_prefix_leading_digit_separator\n +[`base_prefix_trailing_digit_separator`]: Self::base_prefix_trailing_digit_separator\n +[`base_prefix_consecutive_digit_separator`]: Self::base_prefix_consecutive_digit_separator\n +[`base_suffix_internal_digit_separator`]: Self::base_suffix_internal_digit_separator\n +[`base_suffix_leading_digit_separator`]: Self::base_suffix_leading_digit_separator\n +[`base_suffix_trailing_digit_separator`]: Self::base_suffix_trailing_digit_separator\n +[`base_suffix_consecutive_digit_separator`]: Self::base_suffix_consecutive_digit_separator\n " )] #[cfg_attr( @@ -482,6 +530,14 @@ const fn unwrap_or_zero(option: OptionU8) -> u8 { [`case_sensitive_base_suffix`]: https://github.com/Alexhuszagh/rust-lexical/blob/c6c5052/lexical-util/src/format_builder.rs#L781\n [`required_base_prefix`]: https://github.com/Alexhuszagh/rust-lexical/blob/63f9adf/lexical-util/src/format_builder.rs#L1267\n [`required_base_suffix`]: https://github.com/Alexhuszagh/rust-lexical/blob/63f9adf/lexical-util/src/format_builder.rs#L1291\n +[`base_prefix_internal_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1777\n +[`base_prefix_leading_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1809\n +[`base_prefix_trailing_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1841\n +[`base_prefix_consecutive_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1870\n +[`base_suffix_internal_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1883\n +[`base_suffix_leading_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1916\n +[`base_suffix_trailing_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1939\n +[`base_suffix_consecutive_digit_separator`]: https://github.com/Alexhuszagh/rust-lexical/blob/27ca418/lexical-util/src/format_builder.rs#L1967\n " )] /// @@ -582,6 +638,9 @@ pub struct NumberFormatBuilder { required_mantissa_digits_with_exponent: bool, required_base_prefix: bool, required_base_suffix: bool, + no_unsigned_negative_sign: bool, + no_mantissa_sign: bool, + no_exponent_sign: bool, start_digit_separator: bool, integer_sign_digit_separator: bool, integer_consecutive_sign_digit_separator: bool, @@ -657,6 +716,10 @@ impl NumberFormatBuilder { /// `false` /// - [`required_base_prefix`][Self::get_required_base_prefix] - `false` /// - [`required_base_suffix`][Self::get_required_base_suffix] - `false` + /// - [`no_unsigned_negative_sign`][Self::get_no_unsigned_negative_sign] - + /// `true` + /// - [`no_mantissa_sign`][Self::get_no_mantissa_sign] - `false` + /// - [`no_exponent_sign`][Self::get_no_exponent_sign] - `false` /// - [`start_digit_separator`][Self::start_digit_separator] - `true` /// - [`integer_sign_digit_separator`][Self::integer_sign_digit_separator] - /// `false` @@ -718,6 +781,9 @@ impl NumberFormatBuilder { required_mantissa_digits_with_exponent: true, required_base_prefix: false, required_base_suffix: false, + no_unsigned_negative_sign: true, + no_mantissa_sign: false, + no_exponent_sign: false, start_digit_separator: cfg!(feature = "format"), integer_sign_digit_separator: false, integer_consecutive_sign_digit_separator: false, @@ -782,6 +848,9 @@ impl NumberFormatBuilder { required_mantissa_digits_with_exponent: false, required_base_prefix: false, required_base_suffix: false, + no_unsigned_negative_sign: true, + no_mantissa_sign: false, + no_exponent_sign: false, start_digit_separator: true, integer_sign_digit_separator: false, integer_consecutive_sign_digit_separator: false, @@ -1551,6 +1620,83 @@ impl NumberFormatBuilder { self.required_base_suffix } + /// Get if a negative sign before an unsigned integer is not allowed. + /// + /// Can only be modified with [`feature`][crate#features] `format`. This + /// does not apply to signed integers or floating point numbers. + /// + /// # Examples + /// + /// | Input | Valid? | + /// |:-:|:-:| + /// | `-12` | ❌ | + /// | `+12` | ✔️ | + /// | `12` | ✔️ | + /// + /// # Used For + /// + /// - Parse Integer + #[inline(always)] + pub const fn get_no_unsigned_negative_sign(&self) -> bool { + self.no_unsigned_negative_sign + } + + /// Get if positive or negative signs before the significant digits are not + /// allowed. + /// + /// Can only be modified with [`feature`][crate#features] `format`. if + /// enabled, then the type cannot represent negative literal or string + /// values (although they may be computed via mathematical operations). + /// + /// If you only want to disable positive signs, see + /// [`no_positive_mantissa_sign`]. If you wish to disable negative signs + /// on unsigned integers, see [`no_unsigned_negative_sign`]. + /// + /// [`no_positive_mantissa_sign`]: Self::get_no_positive_mantissa_sign + /// [`no_unsigned_negative_sign`]: Self::get_no_unsigned_negative_sign + /// + /// # Examples + /// + /// | Input | Valid? | + /// |:-:|:-:| + /// | `-12` | ❌ | + /// | `+12` | ❌ | + /// | `12` | ✔️ | + /// + /// # Used For + /// + /// - Parse Integer + /// - Parse Float + #[inline(always)] + pub const fn get_no_mantissa_sign(&self) -> bool { + self.no_mantissa_sign + } + + /// Get if positive or negative signs before an exponent are not allowed. + /// + /// Can only be modified with [`feature`][crate#features] `format`. + /// + /// If you only want to disable positive signs, see + /// [`no_positive_exponent_sign`]. + /// + /// [`no_positive_exponent_sign`]: Self::get_no_positive_exponent_sign + /// + /// # Examples + /// + /// | Input | Valid? | + /// |:-:|:-:| + /// | `1.0e-12` | ❌ | + /// | `1.0e+12` | ❌ | + /// | `1.0e12` | ✔️ | + /// + /// # Used For + /// + /// - Parse Float + #[inline(always)] + pub const fn get_no_exponent_sign(&self) -> bool { + self.no_exponent_sign + } + /// Get if digit separators are allowed at the absolute start of the number. /// /// This modifies the behavior of [`integer_sign_digit_separator`] and @@ -2551,6 +2697,7 @@ impl NumberFormatBuilder { /// assert_eq!(parse_with_options::(b"1x", &PF_OPTS), Ok(1.0)); /// assert_eq!(parse_with_options::(b"1x1", &PF_OPTS), Err(Error::InvalidDigit(2))); /// + /// // TODO: FIXME! This is incorrectly getting the location wrong /// assert_eq!(parse_with_options::(b"0x1", &PI_OPTS), Err(Error::InvalidDigit(2))); /// assert_eq!(parse_with_options::(b"x1", &PI_OPTS), Err(Error::InvalidDigit(0))); /// assert_eq!(parse_with_options::(b"1", &PI_OPTS), Ok(1)); @@ -2789,7 +2936,7 @@ impl NumberFormatBuilder { /// .build_strict(); /// assert_eq!(parse_with_options::(b"1.1", &PF_OPTS), Ok(1.1)); /// assert_eq!(parse_with_options::(b"-1.1", &PF_OPTS), Ok(-1.1)); - /// assert_eq!(parse_with_options::(b"+1.1", &PF_OPTS), Err(Error::InvalidPositiveSign(0))); + /// assert_eq!(parse_with_options::(b"+1.1", &PF_OPTS), Err(Error::InvalidPositiveMantissaSign(0))); /// /// let mut buffer = [0u8; BUFFER_SIZE]; /// assert_eq!(write_with_options::(1.1, &mut buffer, &WF_OPTS), b"1.1"); @@ -2827,7 +2974,7 @@ impl NumberFormatBuilder { /// const FORMAT: u128 = NumberFormatBuilder::new() /// .required_mantissa_sign(true) /// .build_strict(); - /// assert_eq!(parse_with_options::(b"1.1", &PF_OPTS), Err(Error::MissingSign(0))); + /// assert_eq!(parse_with_options::(b"1.1", &PF_OPTS), Err(Error::MissingMantissaSign(0))); /// assert_eq!(parse_with_options::(b"+1.1", &PF_OPTS), Ok(1.1)); /// assert_eq!(parse_with_options::(b"-1.1", &PF_OPTS), Ok(-1.1)); /// @@ -3119,7 +3266,7 @@ impl NumberFormatBuilder { /// assert_eq!(parse::(b"0"), Ok(0)); /// assert_eq!(parse::(b"10"), Ok(10)); /// - /// assert_eq!(parse_with_options::(b"01", &PI_OPTS), Ok(0)); + /// assert_eq!(parse_with_options::(b"01", &PI_OPTS), Err(Error::InvalidLeadingZeros(0))); /// assert_eq!(parse_with_options::(b"+01", &PI_OPTS), Err(Error::InvalidLeadingZeros(1))); /// assert_eq!(parse_with_options::(b"0", &PI_OPTS), Ok(0)); /// assert_eq!(parse_with_options::(b"10", &PI_OPTS), Ok(10)); @@ -3349,6 +3496,7 @@ impl NumberFormatBuilder { /// assert_eq!(parse_with_options::(b"1x", &PF_OPTS), Ok(1.0)); /// assert_eq!(parse_with_options::(b"1X", &PF_OPTS), Err(Error::InvalidDigit(1))); /// + /// // TODO: This has the wrong placement /// assert_eq!(parse_with_options::(b"0x1", &PI_OPTS), Err(Error::InvalidDigit(2))); /// assert_eq!(parse_with_options::(b"1", &PI_OPTS), Ok(1)); /// assert_eq!(parse_with_options::(b"1x", &PI_OPTS), Ok(1)); @@ -3532,6 +3680,131 @@ impl NumberFormatBuilder { self } + /// If a negative sign before an unsigned integer is not allowed. + /// + /// Can only be modified with [`feature`][crate#features] `format`. This + /// does not apply to signed integers or floating point numbers. + /// + /// # Examples + /// + /// | Input | Valid? | + /// |:-:|:-:| + /// | `-12` | ❌ | + /// | `+12` | ✔️ | + /// | `12` | ✔️ | + /// + /// # Used For + /// + /// - Parse Integer + /// + /// + #[inline(always)] + #[cfg(feature = "format")] + pub const fn no_unsigned_negative_sign(mut self, flag: bool) -> Self { + self.no_unsigned_negative_sign = flag; + self + } + + /// If positive or negative signs before the significant digits are not + /// allowed. + /// + /// Can only be modified with [`feature`][crate#features] `format`. if + /// enabled, then the type cannot represent negative literal or string + /// values (although they may be computed via mathematical operations). + /// + /// If you only want to disable positive signs, see + /// [`no_positive_mantissa_sign`]. If you wish to disable negative signs + /// on unsigned integers, see [`no_unsigned_negative_sign`]. + /// + /// [`no_positive_mantissa_sign`]: Self::no_positive_mantissa_sign + /// [`no_unsigned_negative_sign`]: Self::no_unsigned_negative_sign + /// + /// # Examples + /// + /// | Input | Valid? | + /// |:-:|:-:| + /// | `-12` | ❌ | + /// | `+12` | ❌ | + /// | `12` | ✔️ | + /// + /// # Used For + /// + /// - Parse Integer + /// - Parse Float + /// + /// + #[inline(always)] + #[cfg(feature = "format")] + pub const fn no_mantissa_sign(mut self, flag: bool) -> Self { + self.no_mantissa_sign = flag; + self + } + + /// If positive or negative signs before an exponent are not allowed. + /// + /// Can only be modified with [`feature`][crate#features] `format`. + /// + /// If you only want to disable positive signs, see + /// [`no_positive_exponent_sign`]. + /// + /// [`no_positive_exponent_sign`]: Self::no_positive_exponent_sign + /// + /// # Examples + /// + /// | Input | Valid? | + /// |:-:|:-:| + /// | `1.0e-12` | ❌ | + /// | `1.0e+12` | ❌ | + /// | `1.0e12` | ✔️ | + /// + /// # Used For + /// + /// - Parse Float + /// + /// + #[inline(always)] + #[cfg(feature = "format")] + pub const fn no_exponent_sign(mut self, flag: bool) -> Self { + self.no_exponent_sign = flag; + self + } + /// Set if digit separators are allowed at the absolute start of the number. /// /// This modifies the behavior of [`integer_sign_digit_separator`] and @@ -3587,7 +3860,7 @@ impl NumberFormatBuilder { /// const NO_START: u128 = NumberFormatBuilder::new() /// .digit_separator(num::NonZeroU8::new(b'_')) /// .integer_leading_digit_separator(true) - /// .start_digit_separator(true) + /// .start_digit_separator(false) /// .build_strict(); /// assert_eq!(parse_with_options::(b"1", &PI_OPTS), Ok(1)); /// assert_eq!(parse_with_options::(b"_1", &PI_OPTS), Err(Error::InvalidDigit(0))); @@ -3876,6 +4149,7 @@ impl NumberFormatBuilder { /// const NO_START: u128 = NumberFormatBuilder::rebuild(FORMAT) /// .start_digit_separator(false) /// .build_strict(); + /// // TODO: Start digit separator isn't being properly respected /// assert_eq!(parse_with_options::(b"_0d1", &PF_OPTS), Err(Error::InvalidDigit(0))); /// assert_eq!(parse_with_options::(b"_0d1", &PI_OPTS), Err(Error::InvalidDigit(0))); /// ``` @@ -3924,17 +4198,17 @@ impl NumberFormatBuilder { /// .build_strict(); /// assert_eq!(parse_with_options::(b"1", &PF_OPTS), Ok(1.0)); /// assert_eq!(parse_with_options::(b"0d1", &PF_OPTS), Ok(1.0)); - /// assert_eq!(parse_with_options::(b"_0d1", &PF_OPTS), Err(Error::InvalidDigit(1))); + /// assert_eq!(parse_with_options::(b"_0d1", &PF_OPTS), Err(Error::InvalidDigit(0))); /// assert_eq!(parse_with_options::(b"0_d1", &PF_OPTS), Err(Error::InvalidDigit(1))); /// assert_eq!(parse_with_options::(b"0d_1", &PF_OPTS), Ok(1.0)); - /// assert_eq!(parse_with_options::(b"0d__1", &PF_OPTS), Err(Error::InvalidDigit(1))); + /// assert_eq!(parse_with_options::(b"0d__1", &PF_OPTS), Err(Error::InvalidDigit(3))); /// /// assert_eq!(parse_with_options::(b"1", &PI_OPTS), Ok(1)); /// assert_eq!(parse_with_options::(b"0d1", &PI_OPTS), Ok(1)); - /// assert_eq!(parse_with_options::(b"_0d1", &PI_OPTS), Err(Error::InvalidDigit(1))); + /// assert_eq!(parse_with_options::(b"_0d1", &PI_OPTS), Err(Error::InvalidDigit(0))); /// assert_eq!(parse_with_options::(b"0_d1", &PI_OPTS), Err(Error::InvalidDigit(1))); /// assert_eq!(parse_with_options::(b"0d_1", &PI_OPTS), Ok(1)); - /// assert_eq!(parse_with_options::(b"0d__1", &PI_OPTS), Err(Error::InvalidDigit(1))); + /// assert_eq!(parse_with_options::(b"0d__1", &PI_OPTS), Err(Error::InvalidDigit(3))); /// ``` /// --> #[inline(always)] @@ -3978,13 +4252,13 @@ impl NumberFormatBuilder { /// .base_prefix_consecutive_digit_separator(true) /// .build_strict(); /// assert_eq!(parse_with_options::(b"0d1", &PF_OPTS), Ok(1.0)); - /// assert_eq!(parse_with_options::(b"_0d1", &PF_OPTS), Err(Error::InvalidDigit(1))); + /// assert_eq!(parse_with_options::(b"_0d1", &PF_OPTS), Err(Error::InvalidDigit(0))); /// assert_eq!(parse_with_options::(b"0_d1", &PF_OPTS), Err(Error::InvalidDigit(1))); /// assert_eq!(parse_with_options::(b"0d_1", &PF_OPTS), Ok(1.0)); /// assert_eq!(parse_with_options::(b"0d__1", &PF_OPTS), Ok(1.0)); /// /// assert_eq!(parse_with_options::(b"0d1", &PI_OPTS), Ok(1)); - /// assert_eq!(parse_with_options::(b"_0d1", &PI_OPTS), Err(Error::InvalidDigit(1))); + /// assert_eq!(parse_with_options::(b"_0d1", &PI_OPTS), Err(Error::InvalidDigit(0))); /// assert_eq!(parse_with_options::(b"0_d1", &PI_OPTS), Err(Error::InvalidDigit(1))); /// assert_eq!(parse_with_options::(b"0d_1", &PI_OPTS), Ok(1)); /// assert_eq!(parse_with_options::(b"0d__1", &PI_OPTS), Ok(1)); @@ -4051,14 +4325,15 @@ impl NumberFormatBuilder { /// assert_eq!(parse_with_options::(b"12d", &PF_OPTS), Ok(12.0)); /// assert_eq!(parse_with_options::(b"1_2d", &PF_OPTS), Err(Error::InvalidDigit(1))); /// assert_eq!(parse_with_options::(b"12_d", &PF_OPTS), Ok(12.0)); - /// assert_eq!(parse_with_options::(b"12__d", &PF_OPTS), Err(Error::InvalidDigit(1))); - /// assert_eq!(parse_with_options::(b"12d_", &PF_OPTS), Err(Error::InvalidDigit(1))); + /// assert_eq!(parse_with_options::(b"12__d", &PF_OPTS), Err(Error::InvalidDigit(2))); + /// assert_eq!(parse_with_options::(b"12d_", &PF_OPTS), Err(Error::InvalidDigit(3))); /// /// assert_eq!(parse_with_options::(b"12d", &PI_OPTS), Ok(12)); /// assert_eq!(parse_with_options::(b"1_2d", &PI_OPTS), Err(Error::InvalidDigit(1))); /// assert_eq!(parse_with_options::(b"12_d", &PI_OPTS), Ok(12)); - /// assert_eq!(parse_with_options::(b"12__d", &PI_OPTS), Err(Error::InvalidDigit(1))); - /// assert_eq!(parse_with_options::(b"12d_", &PI_OPTS), Err(Error::InvalidDigit(1))); + /// assert_eq!(parse_with_options::(b"12__d", &PI_OPTS), Err(Error::InvalidDigit(2))); + /// // TODO: This is incorrectly using the current placement + /// assert_eq!(parse_with_options::(b"12d_", &PI_OPTS), Err(Error::InvalidDigit(3))); /// ``` /// --> #[inline(always)] @@ -4096,15 +4371,16 @@ impl NumberFormatBuilder { /// .build_strict(); /// assert_eq!(parse_with_options::(b"12d", &PF_OPTS), Ok(12.0)); /// assert_eq!(parse_with_options::(b"1_2d", &PF_OPTS), Err(Error::InvalidDigit(1))); - /// assert_eq!(parse_with_options::(b"12_d", &PF_OPTS), Err(Error::InvalidDigit(1))); + /// assert_eq!(parse_with_options::(b"12_d", &PF_OPTS), Err(Error::InvalidDigit(2))); /// assert_eq!(parse_with_options::(b"12d_", &PF_OPTS), Ok(12.0)); - /// assert_eq!(parse_with_options::(b"12d__", &PF_OPTS), Err(Error::InvalidDigit(1))); + /// assert_eq!(parse_with_options::(b"12d__", &PF_OPTS), Err(Error::InvalidDigit(4))); /// /// assert_eq!(parse_with_options::(b"12d", &PI_OPTS), Ok(12)); /// assert_eq!(parse_with_options::(b"1_2d", &PI_OPTS), Err(Error::InvalidDigit(1))); - /// assert_eq!(parse_with_options::(b"12_d", &PI_OPTS), Err(Error::InvalidDigit(1))); + /// assert_eq!(parse_with_options::(b"12_d", &PI_OPTS), Err(Error::InvalidDigit(2))); /// assert_eq!(parse_with_options::(b"12d_", &PI_OPTS), Ok(12)); - /// assert_eq!(parse_with_options::(b"12d__", &PI_OPTS), Err(Error::InvalidDigit(1))); + /// // TODO: This is getting the location wrong + /// assert_eq!(parse_with_options::(b"12d__", &PI_OPTS), Err(Error::InvalidDigit(4))); /// ``` /// --> #[inline(always)] @@ -4148,13 +4424,13 @@ impl NumberFormatBuilder { /// .build_strict(); /// assert_eq!(parse_with_options::(b"12d", &PF_OPTS), Ok(12.0)); /// assert_eq!(parse_with_options::(b"1_2d", &PF_OPTS), Err(Error::InvalidDigit(1))); - /// assert_eq!(parse_with_options::(b"12_d", &PF_OPTS), Err(Error::InvalidDigit(1))); + /// assert_eq!(parse_with_options::(b"12_d", &PF_OPTS), Err(Error::InvalidDigit(2))); /// assert_eq!(parse_with_options::(b"12d_", &PF_OPTS), Ok(12.0)); /// assert_eq!(parse_with_options::(b"12d__", &PF_OPTS), Ok(12.0)); /// /// assert_eq!(parse_with_options::(b"12d", &PI_OPTS), Ok(12)); /// assert_eq!(parse_with_options::(b"1_2d", &PI_OPTS), Err(Error::InvalidDigit(1))); - /// assert_eq!(parse_with_options::(b"12_d", &PI_OPTS), Err(Error::InvalidDigit(1))); + /// assert_eq!(parse_with_options::(b"12_d", &PI_OPTS), Err(Error::InvalidDigit(2))); /// assert_eq!(parse_with_options::(b"12d_", &PI_OPTS), Ok(12)); /// assert_eq!(parse_with_options::(b"12d__", &PI_OPTS), Ok(12)); /// ``` @@ -4375,6 +4651,7 @@ impl NumberFormatBuilder { /// assert_eq!(parse_with_options::(b"_+1", &PF_OPTS), Err(Error::InvalidDigit(1))); /// assert_eq!(parse_with_options::(b"+_1", &PF_OPTS), Ok(1.0)); /// assert_eq!(parse_with_options::(b"+0d_1", &PF_OPTS), Ok(1.0)); + /// // TODO: This is incorrectly consuming the base prefix /// assert_eq!(parse_with_options::(b"+_0d1", &PF_OPTS), Err(Error::InvalidDigit(1))); /// /// assert_eq!(parse_with_options::(b"1", &PI_OPTS), Ok(1)); @@ -5035,6 +5312,9 @@ impl NumberFormatBuilder { self.required_mantissa_digits_with_exponent, REQUIRED_MANTISSA_DIGITS_WITH_EXPONENT ; self.required_base_prefix, REQUIRED_BASE_PREFIX ; self.required_base_suffix, REQUIRED_BASE_SUFFIX ; + self.no_unsigned_negative_sign, NO_UNSIGNED_NEGATIVE_SIGN ; + self.no_mantissa_sign, NO_MANTISSA_SIGN ; + self.no_exponent_sign, NO_EXPONENT_SIGN ; self.start_digit_separator, START_DIGIT_SEPARATOR ; self.integer_sign_digit_separator, INTEGER_SIGN_DIGIT_SEPARATOR ; self.integer_consecutive_sign_digit_separator, INTEGER_CONSECUTIVE_SIGN_DIGIT_SEPARATOR ; @@ -5155,6 +5435,9 @@ impl NumberFormatBuilder { ), required_base_prefix: has_flag!(format, REQUIRED_BASE_PREFIX), required_base_suffix: has_flag!(format, REQUIRED_BASE_SUFFIX), + no_unsigned_negative_sign: has_flag!(format, NO_UNSIGNED_NEGATIVE_SIGN), + no_mantissa_sign: has_flag!(format, NO_MANTISSA_SIGN), + no_exponent_sign: has_flag!(format, NO_EXPONENT_SIGN), start_digit_separator: has_flag!(format, START_DIGIT_SEPARATOR), integer_sign_digit_separator: has_flag!(format, INTEGER_SIGN_DIGIT_SEPARATOR), integer_consecutive_sign_digit_separator: has_flag!( diff --git a/lexical-util/src/format_flags.rs b/lexical-util/src/format_flags.rs index 27dfeb64..51636ead 100644 --- a/lexical-util/src/format_flags.rs +++ b/lexical-util/src/format_flags.rs @@ -25,7 +25,7 @@ //! //! 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ -//! |e/P|e/S|I/E|F/E|r/P|r/S|M/E| | +//! |e/P|e/S|I/E|F/E|r/P|r/S|M/E|-/U|-/M|-/E| | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ //! //! 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 @@ -63,6 +63,9 @@ //! r/P = Require base prefixes. //! r/S = Require base suffixes. //! M/E = Require mantissa digits with exponent. +//! -/U = No unsigned integer negative sign. +//! -/M = No mantissa positive or negative sign. +//! -/E = No exponent positive or negative sign. //! //! Digit Separator Flags: //! I/I = Integer internal digit separator. @@ -373,6 +376,15 @@ pub const REQUIRED_BASE_SUFFIX: u128 = 1 << 21; /// If any significant digits are required with exponent notation. pub const REQUIRED_MANTISSA_DIGITS_WITH_EXPONENT: u128 = 1 << 22; +/// If a negative sign before an unsigned integer is not allowed. +pub const NO_UNSIGNED_NEGATIVE_SIGN: u128 = 1 << 23; + +/// If positive or negative signs before the significant digits are not allowed. +pub const NO_MANTISSA_SIGN: u128 = 1 << 24; + +/// If positive or negative signs before an exponent are not allowed. +pub const NO_EXPONENT_SIGN: u128 = 1 << 25; + // Non-digit separator flags. const _: () = assert!(REQUIRED_INTEGER_DIGITS == 1); check_subsequent_flags!(REQUIRED_INTEGER_DIGITS, REQUIRED_FRACTION_DIGITS); @@ -398,6 +410,9 @@ check_subsequent_flags!(REQUIRED_INTEGER_DIGITS_WITH_EXPONENT, REQUIRED_FRACTION check_subsequent_flags!(REQUIRED_FRACTION_DIGITS_WITH_EXPONENT, REQUIRED_BASE_PREFIX); check_subsequent_flags!(REQUIRED_BASE_PREFIX, REQUIRED_BASE_SUFFIX); check_subsequent_flags!(REQUIRED_BASE_SUFFIX, REQUIRED_MANTISSA_DIGITS_WITH_EXPONENT); +check_subsequent_flags!(REQUIRED_MANTISSA_DIGITS_WITH_EXPONENT, NO_UNSIGNED_NEGATIVE_SIGN); +check_subsequent_flags!(NO_UNSIGNED_NEGATIVE_SIGN, NO_MANTISSA_SIGN); +check_subsequent_flags!(NO_MANTISSA_SIGN, NO_EXPONENT_SIGN); // DIGIT SEPARATOR FLAGS & MASKS // ----------------------------- @@ -624,6 +639,9 @@ pub const FLAG_MASK: u128 = CASE_SENSITIVE_BASE_SUFFIX | REQUIRED_BASE_PREFIX | REQUIRED_BASE_SUFFIX | + NO_UNSIGNED_NEGATIVE_SIGN | + NO_MANTISSA_SIGN | + NO_EXPONENT_SIGN | START_DIGIT_SEPARATOR_FLAG_MASK | ALL_DIGIT_SEPARATOR_FLAG_MASK; @@ -693,6 +711,7 @@ pub const EXPONENT_FLAG_MASK: u128 = REQUIRED_INTEGER_DIGITS_WITH_EXPONENT | REQUIRED_FRACTION_DIGITS_WITH_EXPONENT | REQUIRED_MANTISSA_DIGITS_WITH_EXPONENT | + NO_EXPONENT_SIGN | EXPONENT_INTERNAL_DIGIT_SEPARATOR | EXPONENT_LEADING_DIGIT_SEPARATOR | EXPONENT_TRAILING_DIGIT_SEPARATOR | diff --git a/lexical-util/src/not_feature_format.rs b/lexical-util/src/not_feature_format.rs index 3947cd50..fcf55a4a 100644 --- a/lexical-util/src/not_feature_format.rs +++ b/lexical-util/src/not_feature_format.rs @@ -775,6 +775,102 @@ impl NumberFormat { Self::REQUIRED_BASE_SUFFIX } + /// If a negative sign before an unsigned integer is not allowed. + /// + /// See [`no_unsigned_negative_sign`][Self::no_unsigned_negative_sign]. + pub const NO_UNSIGNED_NEGATIVE_SIGN: bool = true; + + /// If a negative sign before an unsigned integer is not allowed. + /// + /// Can only be modified with [`feature`][crate#features] `format`. This + /// does not apply to signed integers or floating point numbers. + /// Defaults to [`true`]. + /// + /// # Examples + /// + /// | Input | Valid? | + /// |:-:|:-:| + /// | `-12` | ❌ | + /// | `+12` | ✔️ | + /// | `12` | ✔️ | + /// + /// # Used For + /// + /// - Parse Integer + #[inline(always)] + pub const fn no_unsigned_negative_sign(&self) -> bool { + Self::NO_UNSIGNED_NEGATIVE_SIGN + } + + /// If positive or negative signs before the significant digits are not + /// allowed. + /// + /// See [`no_mantissa_sign`][Self::no_mantissa_sign]. + pub const NO_MANTISSA_SIGN: bool = false; + + /// If positive or negative signs before the significant digits are not + /// allowed. + /// + /// Can only be modified with [`feature`][crate#features] `format`. if + /// enabled, then the type cannot represent negative literal or string + /// values (although they may be computed via mathematical operations). + /// Defaults to [`false`]. + /// + /// If you only want to disable positive signs, see + /// [`no_positive_mantissa_sign`]. If you wish to disable negative signs + /// on unsigned integers, see [`no_unsigned_negative_sign`]. + /// + /// [`no_positive_mantissa_sign`]: Self::no_positive_mantissa_sign + /// [`no_unsigned_negative_sign`]: Self::no_unsigned_negative_sign + /// + /// # Examples + /// + /// | Input | Valid? | + /// |:-:|:-:| + /// | `-12` | ❌ | + /// | `+12` | ❌ | + /// | `12` | ✔️ | + /// + /// # Used For + /// + /// - Parse Integer + /// - Parse Float + #[inline(always)] + pub const fn no_mantissa_sign(&self) -> bool { + Self::NO_MANTISSA_SIGN + } + + /// If positive or negative signs before an exponent are not allowed. + /// + /// See [`no_exponent_sign`][Self::no_exponent_sign]. + pub const NO_EXPONENT_SIGN: bool = false; + + /// If positive or negative signs before an exponent are not allowed. + /// + /// Can only be modified with [`feature`][crate#features] `format`. Defaults + /// to [`false`]. + /// + /// If you only want to disable positive signs, see + /// [`no_positive_exponent_sign`]. + /// + /// [`no_positive_exponent_sign`]: Self::no_positive_exponent_sign + /// + /// # Examples + /// + /// | Input | Valid? | + /// |:-:|:-:| + /// | `1.0e-12` | ❌ | + /// | `1.0e+12` | ❌ | + /// | `1.0e12` | ✔️ | + /// + /// # Used For + /// + /// - Parse Float + #[inline(always)] + pub const fn no_exponent_sign(&self) -> bool { + Self::NO_EXPONENT_SIGN + } + // DIGIT SEPARATOR FLAGS & MASKS /// If digit separators are allowed at the absolute start of the number. @@ -2095,7 +2191,8 @@ pub(crate) const fn radix_error_impl(format: u128) -> Error { pub(crate) const fn format_error_impl(format: u128) -> Error { let valid_flags = flags::REQUIRED_EXPONENT_DIGITS | flags::REQUIRED_MANTISSA_DIGITS - | flags::REQUIRED_MANTISSA_DIGITS_WITH_EXPONENT; + | flags::REQUIRED_MANTISSA_DIGITS_WITH_EXPONENT + | flags::NO_UNSIGNED_NEGATIVE_SIGN; if !flags::is_valid_radix(flags::mantissa_radix(format)) { Error::InvalidMantissaRadix } else if !flags::is_valid_radix(flags::exponent_base(format)) {