diff --git a/lexical-parse-float/src/bigint.rs b/lexical-parse-float/src/bigint.rs index 351df8ef..2e9fa6b6 100644 --- a/lexical-parse-float/src/bigint.rs +++ b/lexical-parse-float/src/bigint.rs @@ -390,7 +390,7 @@ impl StackVec { /// /// Safe if `self.len() < self.capacity()`. #[inline(always)] - pub unsafe fn push_unchecked(&mut self, value: Limb) { + unsafe fn push_unchecked(&mut self, value: Limb) { debug_assert!(self.len() < self.capacity()); // SAFETY: safe, capacity is less than the current size. unsafe { @@ -419,7 +419,7 @@ impl StackVec { /// /// Safe if `self.len() > 0`. #[inline(always)] - pub unsafe fn pop_unchecked(&mut self) -> Limb { + unsafe fn pop_unchecked(&mut self) -> Limb { debug_assert!(!self.is_empty()); // SAFETY: safe if `self.length > 0`. // We have a trivial drop and copy, so this is safe. @@ -445,7 +445,7 @@ impl StackVec { /// /// Safe if `self.len() + slc.len() <= self.capacity()`. #[inline(always)] - pub unsafe fn extend_unchecked(&mut self, slc: &[Limb]) { + unsafe fn extend_unchecked(&mut self, slc: &[Limb]) { let index = self.len(); let new_len = index + slc.len(); debug_assert!(self.len() + slc.len() <= self.capacity()); @@ -1228,6 +1228,7 @@ pub fn large_mul(x: &mut StackVec, y: &[Limb]) -> Optio // multiplication. if y.len() == 1 { // SAFETY: safe since `y.len() == 1`. + // NOTE: The compiler does not seem to optimize this out correctly. small_mul(x, unsafe { index_unchecked!(y[0]) })?; } else { *x = long_mul(y, x)?; @@ -1369,6 +1370,7 @@ pub fn shl_limbs(x: &mut StackVec, n: usize) -> Option< let x_len = x.len(); let ptr = x.as_mut_ptr(); let src = ptr; + // FIXME: Change to `split_at_mut` and `clone_from_slice`? // SAFE: since x is not empty, and `x.len() + n <= x.capacity()`. unsafe { // Move the elements. diff --git a/lexical-parse-float/src/options.rs b/lexical-parse-float/src/options.rs index 14f81542..75efb6a8 100644 --- a/lexical-parse-float/src/options.rs +++ b/lexical-parse-float/src/options.rs @@ -218,12 +218,14 @@ impl OptionsBuilder { /// Build the Options struct without validation. /// - /// # Safety + /// # Panics /// - /// Always safe, just marked as unsafe for API compatibility. - /// The result may be invalid if `is_valid` is not true. + /// This is completely safe, however, misusing this, especially + /// the `nan_string`, `inf_string`, and `infinity_string` could + /// panic at runtime. Always use [MAX_SPECIAL_STRING_LENGTH] and + /// check if [Self::is_valid] prior to using a created format string. #[inline(always)] - pub const unsafe fn build_unchecked(&self) -> Options { + pub const fn build_unchecked(&self) -> Options { Options { lossy: self.lossy, exponent: self.exponent, @@ -284,8 +286,7 @@ impl OptionsBuilder { } } - // SAFETY: always safe, since it must be valid. - Ok(unsafe { self.build_unchecked() }) + Ok(self.build_unchecked()) } } @@ -336,8 +337,7 @@ impl Options { /// Create options with default values. #[inline(always)] pub const fn new() -> Self { - // SAFETY: always safe since it uses the default arguments. - unsafe { Self::builder().build_unchecked() } + Self::builder().build_unchecked() } /// Create the default options for a given radix. @@ -351,8 +351,7 @@ impl Options { if radix >= 15 { builder = builder.exponent(b'^'); } - // SAFETY: always safe since it uses the default arguments. - unsafe { builder.build_unchecked() } + builder.build_unchecked() } // GETTERS @@ -402,67 +401,38 @@ impl Options { // SETTERS /// Set if we disable the use of arbitrary-precision arithmetic. - /// - /// # Safety - /// - /// Always safe, just marked as unsafe for API compatibility. #[inline(always)] - pub unsafe fn set_lossy(&mut self, lossy: bool) { + pub fn set_lossy(&mut self, lossy: bool) { self.lossy = lossy } /// Set the character to designate the exponent component of a float. - /// - /// # Safety - /// - /// Always safe, but may produce invalid output if the exponent - /// is not a valid ASCII character. #[inline(always)] - pub unsafe fn set_exponent(&mut self, exponent: u8) { + pub fn set_exponent(&mut self, exponent: u8) { self.exponent = exponent; } /// Set the character to separate the integer from the fraction components. - /// - /// # Safety - /// - /// Always safe, but may produce invalid output if the decimal point - /// is not a valid ASCII character. #[inline(always)] - pub unsafe fn set_decimal_point(&mut self, decimal_point: u8) { + pub fn set_decimal_point(&mut self, decimal_point: u8) { self.decimal_point = decimal_point; } /// Set the string representation for `NaN`. - /// Unsafe, use the builder API for option validation. - /// - /// # Safety - /// - /// Always safe, just marked as unsafe for API compatibility. #[inline(always)] - pub unsafe fn set_nan_string(&mut self, nan_string: Option<&'static [u8]>) { + pub fn set_nan_string(&mut self, nan_string: Option<&'static [u8]>) { self.nan_string = nan_string } /// Set the short string representation for `Infinity` - /// Unsafe, use the builder API for option validation. - /// - /// # Safety - /// - /// Always safe, just marked as unsafe for API compatibility. #[inline(always)] - pub unsafe fn set_inf_string(&mut self, inf_string: Option<&'static [u8]>) { + pub fn set_inf_string(&mut self, inf_string: Option<&'static [u8]>) { self.inf_string = inf_string } /// Set the long string representation for `Infinity` - /// Unsafe, use the builder API for option validation. - /// - /// # Safety - /// - /// Always safe, just marked as unsafe for API compatibility. #[inline(always)] - pub unsafe fn set_infinity_string(&mut self, infinity_string: Option<&'static [u8]>) { + pub fn set_infinity_string(&mut self, infinity_string: Option<&'static [u8]>) { self.infinity_string = infinity_string } @@ -515,10 +485,6 @@ const fn unwrap_str(option: Option<&'static [u8]>) -> &'static [u8] { // --------------------- // Only constants that differ from the standard version are included. -// SAFETY: all of these are safe, since they are checked to be valid -// after calling `build_unchecked`. Furthermore, even though the methods -// are marked as `unsafe`, none of the produced options can cause memory -// safety issues. /// Standard number format. #[rustfmt::skip] @@ -528,630 +494,512 @@ const_assert!(STANDARD.is_valid()); /// Numerical format with a decimal comma. /// This is the standard numerical format for most of the world. #[rustfmt::skip] -pub const DECIMAL_COMMA: Options = unsafe { - Options::builder() +pub const DECIMAL_COMMA: Options = Options::builder() .decimal_point(b',') - .build_unchecked() -}; + .build_unchecked(); const_assert!(DECIMAL_COMMA.is_valid()); /// Numerical format for hexadecimal floats, which use a `p` exponent. #[rustfmt::skip] -pub const HEX_FLOAT: Options = unsafe { - Options::builder() +pub const HEX_FLOAT: Options = Options::builder() .exponent(b'p') - .build_unchecked() -}; + .build_unchecked(); const_assert!(HEX_FLOAT.is_valid()); /// Numerical format where `^` is used as the exponent notation character. /// This isn't very common, but is useful when `e` or `p` are valid digits. #[rustfmt::skip] -pub const CARAT_EXPONENT: Options = unsafe { - Options::builder() +pub const CARAT_EXPONENT: Options = Options::builder() .exponent(b'^') - .build_unchecked() -}; + .build_unchecked(); const_assert!(CARAT_EXPONENT.is_valid()); /// Number format for a Rust literal floating-point number. #[rustfmt::skip] -pub const RUST_LITERAL: Options = unsafe { - Options::builder() +pub const RUST_LITERAL: Options = Options::builder() .nan_string(options::RUST_LITERAL) .inf_string(options::RUST_LITERAL) .infinity_string(options::RUST_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(RUST_LITERAL.is_valid()); /// Number format for a Python literal floating-point number. #[rustfmt::skip] -pub const PYTHON_LITERAL: Options = unsafe { - Options::builder() +pub const PYTHON_LITERAL: Options = Options::builder() .nan_string(options::PYTHON_LITERAL) .inf_string(options::PYTHON_LITERAL) .infinity_string(options::PYTHON_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(PYTHON_LITERAL.is_valid()); /// Number format for a C++ literal floating-point number. #[rustfmt::skip] -pub const CXX_LITERAL: Options = unsafe { - Options::builder() +pub const CXX_LITERAL: Options = Options::builder() .nan_string(options::CXX_LITERAL_NAN) .inf_string(options::CXX_LITERAL_INF) .infinity_string(options::CXX_LITERAL_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(CXX_LITERAL.is_valid()); /// Number format for a C literal floating-point number. #[rustfmt::skip] -pub const C_LITERAL: Options = unsafe { - Options::builder() +pub const C_LITERAL: Options = Options::builder() .nan_string(options::C_LITERAL_NAN) .inf_string(options::C_LITERAL_INF) .infinity_string(options::C_LITERAL_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(CXX_LITERAL.is_valid()); /// Number format for a Ruby literal floating-point number. #[rustfmt::skip] -pub const RUBY_LITERAL: Options = unsafe { - Options::builder() +pub const RUBY_LITERAL: Options = Options::builder() .nan_string(options::RUBY_LITERAL_NAN) .inf_string(options::RUBY_LITERAL_INF) .infinity_string(options::RUBY_LITERAL_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(RUBY_LITERAL.is_valid()); /// Number format to parse a Ruby float from string. /// Ruby can write NaN and Infinity as strings, but won't roundtrip them back to floats. #[rustfmt::skip] -pub const RUBY_STRING: Options = unsafe { - Options::builder() +pub const RUBY_STRING: Options = Options::builder() .nan_string(options::RUBY_STRING_NONE) .inf_string(options::RUBY_STRING_NONE) .infinity_string(options::RUBY_STRING_NONE) - .build_unchecked() -}; + .build_unchecked(); const_assert!(RUBY_STRING.is_valid()); /// Number format for a Swift literal floating-point number. #[rustfmt::skip] -pub const SWIFT_LITERAL: Options = unsafe { - Options::builder() +pub const SWIFT_LITERAL: Options = Options::builder() .nan_string(options::SWIFT_LITERAL) .inf_string(options::SWIFT_LITERAL) .infinity_string(options::SWIFT_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(SWIFT_LITERAL.is_valid()); /// Number format for a Go literal floating-point number. #[rustfmt::skip] -pub const GO_LITERAL: Options = unsafe { - Options::builder() +pub const GO_LITERAL: Options = Options::builder() .nan_string(options::GO_LITERAL) .inf_string(options::GO_LITERAL) .infinity_string(options::GO_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(GO_LITERAL.is_valid()); /// Number format for a Haskell literal floating-point number. #[rustfmt::skip] -pub const HASKELL_LITERAL: Options = unsafe { - Options::builder() +pub const HASKELL_LITERAL: Options = Options::builder() .nan_string(options::HASKELL_LITERAL) .inf_string(options::HASKELL_LITERAL) .infinity_string(options::HASKELL_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(HASKELL_LITERAL.is_valid()); /// Number format to parse a Haskell float from string. #[rustfmt::skip] -pub const HASKELL_STRING: Options = unsafe { - Options::builder() +pub const HASKELL_STRING: Options = Options::builder() .inf_string(options::HASKELL_STRING_INF) .infinity_string(options::HASKELL_STRING_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(HASKELL_STRING.is_valid()); /// Number format for a Javascript literal floating-point number. #[rustfmt::skip] -pub const JAVASCRIPT_LITERAL: Options = unsafe { - Options::builder() +pub const JAVASCRIPT_LITERAL: Options = Options::builder() .inf_string(options::JAVASCRIPT_INF) .infinity_string(options::JAVASCRIPT_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(JAVASCRIPT_LITERAL.is_valid()); /// Number format to parse a Javascript float from string. #[rustfmt::skip] -pub const JAVASCRIPT_STRING: Options = unsafe { - Options::builder() +pub const JAVASCRIPT_STRING: Options = Options::builder() .inf_string(options::JAVASCRIPT_INF) .infinity_string(options::JAVASCRIPT_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(JAVASCRIPT_STRING.is_valid()); /// Number format for a Perl literal floating-point number. #[rustfmt::skip] -pub const PERL_LITERAL: Options = unsafe { - Options::builder() +pub const PERL_LITERAL: Options = Options::builder() .nan_string(options::PERL_LITERAL) .inf_string(options::PERL_LITERAL) .infinity_string(options::PERL_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(PERL_LITERAL.is_valid()); /// Number format for a PHP literal floating-point number. #[rustfmt::skip] -pub const PHP_LITERAL: Options = unsafe { - Options::builder() +pub const PHP_LITERAL: Options = Options::builder() .nan_string(options::PHP_LITERAL_NAN) .inf_string(options::PHP_LITERAL_INF) .infinity_string(options::PHP_LITERAL_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(PHP_LITERAL.is_valid()); /// Number format for a Java literal floating-point number. #[rustfmt::skip] -pub const JAVA_LITERAL: Options = unsafe { - Options::builder() +pub const JAVA_LITERAL: Options = Options::builder() .nan_string(options::JAVA_LITERAL) .inf_string(options::JAVA_LITERAL) .infinity_string(options::JAVA_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(JAVA_LITERAL.is_valid()); /// Number format to parse a Java float from string. #[rustfmt::skip] -pub const JAVA_STRING: Options = unsafe { - Options::builder() +pub const JAVA_STRING: Options = Options::builder() .inf_string(options::JAVA_STRING_INF) .infinity_string(options::JAVA_STRING_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(JAVA_STRING.is_valid()); /// Number format for an R literal floating-point number. #[rustfmt::skip] -pub const R_LITERAL: Options = unsafe { - Options::builder() +pub const R_LITERAL: Options = Options::builder() .inf_string(options::R_LITERAL_INF) .infinity_string(options::R_LITERAL_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(R_LITERAL.is_valid()); /// Number format for a Kotlin literal floating-point number. #[rustfmt::skip] -pub const KOTLIN_LITERAL: Options = unsafe { - Options::builder() +pub const KOTLIN_LITERAL: Options = Options::builder() .nan_string(options::KOTLIN_LITERAL) .inf_string(options::KOTLIN_LITERAL) .infinity_string(options::KOTLIN_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(KOTLIN_LITERAL.is_valid()); /// Number format to parse a Kotlin float from string. #[rustfmt::skip] -pub const KOTLIN_STRING: Options = unsafe { - Options::builder() +pub const KOTLIN_STRING: Options = Options::builder() .inf_string(options::KOTLIN_STRING_INF) .infinity_string(options::KOTLIN_STRING_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(KOTLIN_STRING.is_valid()); /// Number format for a Julia literal floating-point number. #[rustfmt::skip] -pub const JULIA_LITERAL: Options = unsafe { - Options::builder() +pub const JULIA_LITERAL: Options = Options::builder() .inf_string(options::JULIA_LITERAL_INF) .infinity_string(options::JULIA_LITERAL_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(JULIA_LITERAL.is_valid()); /// Number format for a C# literal floating-point number. #[rustfmt::skip] -pub const CSHARP_LITERAL: Options = unsafe { - Options::builder() +pub const CSHARP_LITERAL: Options = Options::builder() .nan_string(options::CSHARP_LITERAL) .inf_string(options::CSHARP_LITERAL) .infinity_string(options::CSHARP_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(CSHARP_LITERAL.is_valid()); /// Number format to parse a C# float from string. #[rustfmt::skip] -pub const CSHARP_STRING: Options = unsafe { - Options::builder() +pub const CSHARP_STRING: Options = Options::builder() .inf_string(options::CSHARP_STRING_INF) .infinity_string(options::CSHARP_STRING_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(CSHARP_STRING.is_valid()); /// Number format for a Kawa literal floating-point number. #[rustfmt::skip] -pub const KAWA_LITERAL: Options = unsafe { - Options::builder() +pub const KAWA_LITERAL: Options = Options::builder() .nan_string(options::KAWA) .inf_string(options::KAWA) .infinity_string(options::KAWA) - .build_unchecked() -}; + .build_unchecked(); const_assert!(KAWA_LITERAL.is_valid()); /// Number format to parse a Kawa float from string. #[rustfmt::skip] -pub const KAWA_STRING: Options = unsafe { - Options::builder() +pub const KAWA_STRING: Options = Options::builder() .nan_string(options::KAWA) .inf_string(options::KAWA) .infinity_string(options::KAWA) - .build_unchecked() -}; + .build_unchecked(); const_assert!(KAWA_STRING.is_valid()); /// Number format for a Gambit-C literal floating-point number. #[rustfmt::skip] -pub const GAMBITC_LITERAL: Options = unsafe { - Options::builder() +pub const GAMBITC_LITERAL: Options = Options::builder() .nan_string(options::GAMBITC) .inf_string(options::GAMBITC) .infinity_string(options::GAMBITC) - .build_unchecked() -}; + .build_unchecked(); const_assert!(GAMBITC_LITERAL.is_valid()); /// Number format to parse a Gambit-C float from string. #[rustfmt::skip] -pub const GAMBITC_STRING: Options = unsafe { - Options::builder() +pub const GAMBITC_STRING: Options = Options::builder() .nan_string(options::GAMBITC) .inf_string(options::GAMBITC) .infinity_string(options::GAMBITC) - .build_unchecked() -}; + .build_unchecked(); const_assert!(GAMBITC_STRING.is_valid()); /// Number format for a Guile literal floating-point number. #[rustfmt::skip] -pub const GUILE_LITERAL: Options = unsafe { - Options::builder() +pub const GUILE_LITERAL: Options = Options::builder() .nan_string(options::GUILE) .inf_string(options::GUILE) .infinity_string(options::GUILE) - .build_unchecked() -}; + .build_unchecked(); const_assert!(GUILE_LITERAL.is_valid()); /// Number format to parse a Guile float from string. #[rustfmt::skip] -pub const GUILE_STRING: Options = unsafe { - Options::builder() +pub const GUILE_STRING: Options = Options::builder() .nan_string(options::GUILE) .inf_string(options::GUILE) .infinity_string(options::GUILE) - .build_unchecked() -}; + .build_unchecked(); const_assert!(GUILE_STRING.is_valid()); /// Number format for a Clojure literal floating-point number. #[rustfmt::skip] -pub const CLOJURE_LITERAL: Options = unsafe { - Options::builder() +pub const CLOJURE_LITERAL: Options = Options::builder() .nan_string(options::CLOJURE_LITERAL) .inf_string(options::CLOJURE_LITERAL) .infinity_string(options::CLOJURE_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(CLOJURE_LITERAL.is_valid()); /// Number format to parse a Clojure float from string. #[rustfmt::skip] -pub const CLOJURE_STRING: Options = unsafe { - Options::builder() +pub const CLOJURE_STRING: Options = Options::builder() .inf_string(options::CLOJURE_STRING_INF) .infinity_string(options::CLOJURE_STRING_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(CLOJURE_STRING.is_valid()); /// Number format for an Erlang literal floating-point number. #[rustfmt::skip] -pub const ERLANG_LITERAL: Options = unsafe { - Options::builder() +pub const ERLANG_LITERAL: Options = Options::builder() .nan_string(options::ERLANG_LITERAL_NAN) - .build_unchecked() -}; + .build_unchecked(); const_assert!(ERLANG_LITERAL.is_valid()); /// Number format to parse an Erlang float from string. #[rustfmt::skip] -pub const ERLANG_STRING: Options = unsafe { - Options::builder() +pub const ERLANG_STRING: Options = Options::builder() .nan_string(options::ERLANG_STRING) .inf_string(options::ERLANG_STRING) .infinity_string(options::ERLANG_STRING) - .build_unchecked() -}; + .build_unchecked(); const_assert!(ERLANG_STRING.is_valid()); /// Number format for an Elm literal floating-point number. #[rustfmt::skip] -pub const ELM_LITERAL: Options = unsafe { - Options::builder() +pub const ELM_LITERAL: Options = Options::builder() .nan_string(options::ELM_LITERAL) .inf_string(options::ELM_LITERAL) .infinity_string(options::ELM_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(ELM_LITERAL.is_valid()); /// Number format to parse an Elm float from string. #[rustfmt::skip] -pub const ELM_STRING: Options = unsafe { - Options::builder() +pub const ELM_STRING: Options = Options::builder() .nan_string(options::ELM_STRING_NAN) .inf_string(options::ELM_STRING_INF) .infinity_string(options::ELM_STRING_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(ELM_STRING.is_valid()); /// Number format for a Scala literal floating-point number. #[rustfmt::skip] -pub const SCALA_LITERAL: Options = unsafe { - Options::builder() +pub const SCALA_LITERAL: Options = Options::builder() .nan_string(options::SCALA_LITERAL) .inf_string(options::SCALA_LITERAL) .infinity_string(options::SCALA_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(SCALA_LITERAL.is_valid()); /// Number format to parse a Scala float from string. #[rustfmt::skip] -pub const SCALA_STRING: Options = unsafe { - Options::builder() +pub const SCALA_STRING: Options = Options::builder() .inf_string(options::SCALA_STRING_INF) .infinity_string(options::SCALA_STRING_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(SCALA_STRING.is_valid()); /// Number format for an Elixir literal floating-point number. #[rustfmt::skip] -pub const ELIXIR_LITERAL: Options = unsafe { - Options::builder() +pub const ELIXIR_LITERAL: Options = Options::builder() .nan_string(options::ELIXIR) .inf_string(options::ELIXIR) .infinity_string(options::ELIXIR) - .build_unchecked() -}; + .build_unchecked(); const_assert!(ELIXIR_LITERAL.is_valid()); /// Number format to parse an Elixir float from string. #[rustfmt::skip] -pub const ELIXIR_STRING: Options = unsafe { - Options::builder() +pub const ELIXIR_STRING: Options = Options::builder() .nan_string(options::ELIXIR) .inf_string(options::ELIXIR) .infinity_string(options::ELIXIR) - .build_unchecked() -}; + .build_unchecked(); const_assert!(ELIXIR_STRING.is_valid()); /// Number format for a FORTRAN literal floating-point number. #[rustfmt::skip] -pub const FORTRAN_LITERAL: Options = unsafe { - Options::builder() +pub const FORTRAN_LITERAL: Options = Options::builder() .nan_string(options::FORTRAN_LITERAL) .inf_string(options::FORTRAN_LITERAL) .infinity_string(options::FORTRAN_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(FORTRAN_LITERAL.is_valid()); /// Number format for a D literal floating-point number. #[rustfmt::skip] -pub const D_LITERAL: Options = unsafe { - Options::builder() +pub const D_LITERAL: Options = Options::builder() .nan_string(options::D_LITERAL) .inf_string(options::D_LITERAL) .infinity_string(options::D_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(D_LITERAL.is_valid()); /// Number format for a Coffeescript literal floating-point number. #[rustfmt::skip] -pub const COFFEESCRIPT_LITERAL: Options = unsafe { - Options::builder() +pub const COFFEESCRIPT_LITERAL: Options = Options::builder() .inf_string(options::COFFEESCRIPT_INF) .infinity_string(options::COFFEESCRIPT_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(COFFEESCRIPT_LITERAL.is_valid()); /// Number format to parse a Coffeescript float from string. #[rustfmt::skip] -pub const COFFEESCRIPT_STRING: Options = unsafe { - Options::builder() +pub const COFFEESCRIPT_STRING: Options = Options::builder() .inf_string(options::COFFEESCRIPT_INF) .infinity_string(options::COFFEESCRIPT_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(COFFEESCRIPT_STRING.is_valid()); /// Number format for a COBOL literal floating-point number. #[rustfmt::skip] -pub const COBOL_LITERAL: Options = unsafe { - Options::builder() +pub const COBOL_LITERAL: Options = Options::builder() .nan_string(options::COBOL) .inf_string(options::COBOL) .infinity_string(options::COBOL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(COBOL_LITERAL.is_valid()); /// Number format to parse a COBOL float from string. #[rustfmt::skip] -pub const COBOL_STRING: Options = unsafe { - Options::builder() +pub const COBOL_STRING: Options = Options::builder() .nan_string(options::COBOL) .inf_string(options::COBOL) .infinity_string(options::COBOL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(COBOL_STRING.is_valid()); /// Number format for an F# literal floating-point number. #[rustfmt::skip] -pub const FSHARP_LITERAL: Options = unsafe { - Options::builder() +pub const FSHARP_LITERAL: Options = Options::builder() .nan_string(options::FSHARP_LITERAL_NAN) .inf_string(options::FSHARP_LITERAL_INF) .infinity_string(options::FSHARP_LITERAL_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(FSHARP_LITERAL.is_valid()); /// Number format for a Visual Basic literal floating-point number. #[rustfmt::skip] -pub const VB_LITERAL: Options = unsafe { - Options::builder() +pub const VB_LITERAL: Options = Options::builder() .nan_string(options::VB_LITERAL) .inf_string(options::VB_LITERAL) .infinity_string(options::VB_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(VB_LITERAL.is_valid()); /// Number format to parse a Visual Basic float from string. #[rustfmt::skip] -pub const VB_STRING: Options = unsafe { - Options::builder() +pub const VB_STRING: Options = Options::builder() .inf_string(options::VB_STRING_INF) .infinity_string(options::VB_STRING_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(VB_STRING.is_valid()); /// Number format for an OCaml literal floating-point number. #[rustfmt::skip] -pub const OCAML_LITERAL: Options = unsafe { - Options::builder() +pub const OCAML_LITERAL: Options = Options::builder() .nan_string(options::OCAML_LITERAL_NAN) .inf_string(options::OCAML_LITERAL_INF) .infinity_string(options::OCAML_LITERAL_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(OCAML_LITERAL.is_valid()); /// Number format for an Objective-C literal floating-point number. #[rustfmt::skip] -pub const OBJECTIVEC_LITERAL: Options = unsafe { - Options::builder() +pub const OBJECTIVEC_LITERAL: Options = Options::builder() .nan_string(options::OBJECTIVEC) .inf_string(options::OBJECTIVEC) .infinity_string(options::OBJECTIVEC) - .build_unchecked() -}; + .build_unchecked(); const_assert!(OBJECTIVEC_LITERAL.is_valid()); /// Number format to parse an Objective-C float from string. #[rustfmt::skip] -pub const OBJECTIVEC_STRING: Options = unsafe { - Options::builder() +pub const OBJECTIVEC_STRING: Options = Options::builder() .nan_string(options::OBJECTIVEC) .inf_string(options::OBJECTIVEC) .infinity_string(options::OBJECTIVEC) - .build_unchecked() -}; + .build_unchecked(); const_assert!(OBJECTIVEC_STRING.is_valid()); /// Number format for an ReasonML literal floating-point number. #[rustfmt::skip] -pub const REASONML_LITERAL: Options = unsafe { - Options::builder() +pub const REASONML_LITERAL: Options = Options::builder() .nan_string(options::REASONML_LITERAL_NAN) .inf_string(options::REASONML_LITERAL_INF) .infinity_string(options::REASONML_LITERAL_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(REASONML_LITERAL.is_valid()); /// Number format for a MATLAB literal floating-point number. #[rustfmt::skip] -pub const MATLAB_LITERAL: Options = unsafe { - Options::builder() +pub const MATLAB_LITERAL: Options = Options::builder() .inf_string(options::MATLAB_LITERAL_INF) .infinity_string(options::MATLAB_LITERAL_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(MATLAB_LITERAL.is_valid()); /// Number format for a Zig literal floating-point number. #[rustfmt::skip] -pub const ZIG_LITERAL: Options = unsafe { - Options::builder() +pub const ZIG_LITERAL: Options = Options::builder() .nan_string(options::ZIG_LITERAL) .inf_string(options::ZIG_LITERAL) .infinity_string(options::ZIG_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(ZIG_LITERAL.is_valid()); /// Number format for a Safe literal floating-point number. #[rustfmt::skip] -pub const SAGE_LITERAL: Options = unsafe { - Options::builder() +pub const SAGE_LITERAL: Options = Options::builder() .inf_string(options::SAGE_LITERAL_INF) .infinity_string(options::SAGE_LITERAL_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(SAGE_LITERAL.is_valid()); /// Number format for a JSON literal floating-point number. #[rustfmt::skip] -pub const JSON: Options = unsafe { - Options::builder() +pub const JSON: Options = Options::builder() .nan_string(options::JSON) .inf_string(options::JSON) .infinity_string(options::JSON) - .build_unchecked() -}; + .build_unchecked(); const_assert!(JSON.is_valid()); /// Number format for a TOML literal floating-point number. #[rustfmt::skip] -pub const TOML: Options = unsafe { - Options::builder() +pub const TOML: Options = Options::builder() .nan_string(options::TOML) .inf_string(options::TOML) .infinity_string(options::TOML) - .build_unchecked() -}; + .build_unchecked(); const_assert!(TOML.is_valid()); /// Number format for a YAML literal floating-point number. @@ -1160,53 +1008,43 @@ pub const YAML: Options = JSON; /// Number format for an XML literal floating-point number. #[rustfmt::skip] -pub const XML: Options = unsafe { - Options::builder() +pub const XML: Options = Options::builder() .inf_string(options::XML_INF) .infinity_string(options::XML_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(XML.is_valid()); /// Number format for a SQLite literal floating-point number. #[rustfmt::skip] -pub const SQLITE: Options = unsafe { - Options::builder() +pub const SQLITE: Options = Options::builder() .nan_string(options::SQLITE) .inf_string(options::SQLITE) .infinity_string(options::SQLITE) - .build_unchecked() -}; + .build_unchecked(); const_assert!(SQLITE.is_valid()); /// Number format for a PostgreSQL literal floating-point number. #[rustfmt::skip] -pub const POSTGRESQL: Options = unsafe { - Options::builder() +pub const POSTGRESQL: Options = Options::builder() .nan_string(options::POSTGRESQL) .inf_string(options::POSTGRESQL) .infinity_string(options::POSTGRESQL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(POSTGRESQL.is_valid()); /// Number format for a MySQL literal floating-point number. #[rustfmt::skip] -pub const MYSQL: Options = unsafe { - Options::builder() +pub const MYSQL: Options = Options::builder() .nan_string(options::MYSQL) .inf_string(options::MYSQL) .infinity_string(options::MYSQL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(MYSQL.is_valid()); /// Number format for a MongoDB literal floating-point number. #[rustfmt::skip] -pub const MONGODB: Options = unsafe { - Options::builder() +pub const MONGODB: Options = Options::builder() .inf_string(options::MONGODB_INF) .infinity_string(options::MONGODB_INFINITY) - .build_unchecked() -}; + .build_unchecked(); const_assert!(MONGODB.is_valid()); diff --git a/lexical-parse-float/tests/options_tests.rs b/lexical-parse-float/tests/options_tests.rs index b6046cfd..0a35500d 100644 --- a/lexical-parse-float/tests/options_tests.rs +++ b/lexical-parse-float/tests/options_tests.rs @@ -107,21 +107,19 @@ fn builder_test() { assert_eq!(builder.get_infinity_string(), Some("Infiniiiiiity".as_bytes())); assert!(builder.is_valid()); - assert_eq!(builder.build(), Ok(unsafe { builder.build_unchecked() })); + assert_eq!(builder.build(), Ok(builder.build_unchecked())); } #[test] fn options_test() { let mut opts = Options::new(); - unsafe { - opts.set_lossy(true); - opts.set_exponent(b'^'); - opts.set_decimal_point(b','); - opts.set_nan_string(Some(b"nan")); - opts.set_inf_string(Some(b"Infinity")); - opts.set_infinity_string(Some(b"Infiniiiiiity")); - } + opts.set_lossy(true); + opts.set_exponent(b'^'); + opts.set_decimal_point(b','); + opts.set_nan_string(Some(b"nan")); + opts.set_inf_string(Some(b"Infinity")); + opts.set_infinity_string(Some(b"Infiniiiiiity")); assert_eq!(opts.lossy(), true); assert_eq!(opts.exponent(), b'^'); diff --git a/lexical-parse-integer/src/options.rs b/lexical-parse-integer/src/options.rs index 42e9f2ed..34cb45eb 100644 --- a/lexical-parse-integer/src/options.rs +++ b/lexical-parse-integer/src/options.rs @@ -52,12 +52,8 @@ impl OptionsBuilder { } /// Build the Options struct with bounds validation. - /// - /// # Safety - /// - /// Safe as long as`is_valid` is true. #[inline(always)] - pub const unsafe fn build_unchecked(&self) -> Options { + pub const fn build_unchecked(&self) -> Options { Options { no_multi_digit: self.no_multi_digit, } @@ -66,8 +62,7 @@ impl OptionsBuilder { /// Build the Options struct. #[inline(always)] pub const fn build(&self) -> Result { - // SAFETY: always safe, since it must be valid. - Ok(unsafe { self.build_unchecked() }) + Ok(self.build_unchecked()) } } @@ -107,8 +102,7 @@ impl Options { /// Create options with default values. #[inline(always)] pub const fn new() -> Self { - // SAFETY: always safe since it uses the default arguments. - unsafe { Self::builder().build_unchecked() } + Self::builder().build_unchecked() } // GETTERS @@ -128,12 +122,8 @@ impl Options { // SETTERS /// Set if we disable the use of multi-digit optimizations. - /// - /// # Safety - /// - /// Always safe, just marked as unsafe for API compatibility. #[inline(always)] - pub unsafe fn no_multi_digit(&mut self, no_multi_digit: bool) { + pub fn no_multi_digit(&mut self, no_multi_digit: bool) { self.no_multi_digit = no_multi_digit; } @@ -178,18 +168,14 @@ const_assert!(STANDARD.is_valid()); /// Optiobns optimized for small numbers. #[rustfmt::skip] -pub const SMALL_NUMBERS: Options = unsafe { - Options::builder() +pub const SMALL_NUMBERS: Options = Options::builder() .no_multi_digit(true) - .build_unchecked() -}; + .build_unchecked(); const_assert!(SMALL_NUMBERS.is_valid()); /// Optiobns optimized for large numbers and long strings. #[rustfmt::skip] -pub const LARGE_NUMBERS: Options = unsafe { - Options::builder() +pub const LARGE_NUMBERS: Options = Options::builder() .no_multi_digit(false) - .build_unchecked() -}; + .build_unchecked(); const_assert!(LARGE_NUMBERS.is_valid()); diff --git a/lexical-parse-integer/tests/options_tests.rs b/lexical-parse-integer/tests/options_tests.rs index 8301cc48..61a33e5c 100644 --- a/lexical-parse-integer/tests/options_tests.rs +++ b/lexical-parse-integer/tests/options_tests.rs @@ -4,7 +4,7 @@ use lexical_parse_integer::options::{Options, OptionsBuilder}; fn options_tests() { let builder = OptionsBuilder::new(); assert!(builder.is_valid()); - assert!(unsafe { builder.build_unchecked() }.is_valid()); + assert!(builder.build_unchecked().is_valid()); assert!(OptionsBuilder::default().is_valid()); let options: Options = Options::new(); diff --git a/lexical-util/src/algorithm.rs b/lexical-util/src/algorithm.rs index a9713b8a..2f3051b9 100644 --- a/lexical-util/src/algorithm.rs +++ b/lexical-util/src/algorithm.rs @@ -8,9 +8,9 @@ use crate::num::Integer; /// performance isn't the highest consideration here. #[inline(always)] #[cfg(feature = "write")] -pub fn copy_to_dst>(dst: &mut [u8], src: Bytes) -> usize { +pub fn copy_to_dst>(dst: &mut [T], src: Bytes) -> usize { let src = src.as_ref(); - dst[..src.len()].clone_from_slice(src); + dst[..src.len()].copy_from_slice(src); src.len() } diff --git a/lexical-util/src/iterator.rs b/lexical-util/src/iterator.rs index 37793b3c..cd4a6ced 100644 --- a/lexical-util/src/iterator.rs +++ b/lexical-util/src/iterator.rs @@ -49,13 +49,6 @@ pub unsafe trait BytesIter<'a>: Iterator + Buffer<'a> { /// does not set the cursor within skipped characters. unsafe fn set_cursor(&mut self, index: usize); - /// Set the cursor to the start of the buffer. - #[inline(always)] - fn seek_start(&mut self) { - // SAFETY: 0 is alwatys <= any usize value. - unsafe { self.set_cursor(0) }; - } - /// Get a slice to the full buffer, which may or may not be the same as /// `as_slice`. fn as_full_slice(&self) -> &'a [u8]; @@ -157,6 +150,9 @@ pub unsafe trait BytesIter<'a>: Iterator + Buffer<'a> { /// expected one. #[inline(always)] fn read_if bool>(&mut self, pred: Pred) -> Option { + // NOTE: This was implemented to remove usage of unsafe throughout to code + // base, however, performance was really not up to scratch. I'm not sure + // the cause of this. if let Some(peeked) = self.peek() { if pred(peeked) { // SAFETY: the slice cannot be empty because we peeked a value. diff --git a/lexical-write-float/src/options.rs b/lexical-write-float/src/options.rs index 66d05eb0..e041bfe5 100644 --- a/lexical-write-float/src/options.rs +++ b/lexical-write-float/src/options.rs @@ -209,6 +209,13 @@ impl OptionsBuilder { } /// Set the string representation for `NaN`. + /// + /// Panics + /// + /// Setting a value too large may cause a panic even if [FORMATTED_SIZE] + /// elements are provided. + /// + /// [FORMATTED_SIZE]: lexical_util::constants::FormattedSize::FORMATTED_SIZE #[inline(always)] pub const fn nan_string(mut self, nan_string: Option<&'static [u8]>) -> Self { self.nan_string = nan_string; @@ -216,6 +223,13 @@ impl OptionsBuilder { } /// Set the string representation for `Infinity`. + /// + /// Panics + /// + /// Setting a value too large may cause a panic even if [FORMATTED_SIZE] + /// elements are provided. + /// + /// [FORMATTED_SIZE]: lexical_util::constants::FormattedSize::FORMATTED_SIZE #[inline(always)] pub const fn inf_string(mut self, inf_string: Option<&'static [u8]>) -> Self { self.inf_string = inf_string; @@ -283,15 +297,16 @@ impl OptionsBuilder { } } - /// Build the Options struct with bounds validation. + /// Build the Options struct without validation. /// - /// # Safety + /// # Panics /// - /// Safe as long as `is_valid` is true. If `nan_string` or `inf_string` - /// are too long, writing special floats may lead to buffer overflows, - /// and therefore severe security vulnerabilities. + /// This is completely safe, however, misusing this, especially + /// the `nan_string` and `inf_string` representations could cause + /// panics at runtime. Always use [MAX_SPECIAL_STRING_LENGTH] and + /// check if [Self::is_valid] prior to using a created format string. #[inline(always)] - pub const unsafe fn build_unchecked(&self) -> Options { + pub const fn build_unchecked(&self) -> Options { Options { max_significant_digits: self.max_significant_digits, min_significant_digits: self.min_significant_digits, @@ -345,8 +360,7 @@ impl OptionsBuilder { } else if !is_valid_ascii(self.decimal_point) { Err(Error::InvalidDecimalPoint) } else { - // SAFETY: always safe, since it must be valid. - Ok(unsafe { self.build_unchecked() }) + Ok(self.build_unchecked()) } } } @@ -411,8 +425,7 @@ impl Options { /// Create options with default values. #[inline(always)] pub const fn new() -> Self { - // SAFETY: always safe since it uses the default arguments. - unsafe { Self::builder().build_unchecked() } + Self::builder().build_unchecked() } /// Create the default options for a given radix. @@ -426,8 +439,7 @@ impl Options { if radix >= 15 { builder = builder.exponent(b'^'); } - // SAFETY: always safe since it uses the default arguments. - unsafe { builder.build_unchecked() } + builder.build_unchecked() } // GETTERS @@ -501,65 +513,38 @@ impl Options { // SETTERS /// Set the maximum number of significant digits to write. - /// Unsafe, use the builder API for option validation. - /// - /// # Safety - /// - /// Always safe, just marked as unsafe for API compatibility. #[inline(always)] - pub unsafe fn set_max_significant_digits(&mut self, max_significant_digits: OptionUsize) { + pub fn set_max_significant_digits(&mut self, max_significant_digits: OptionUsize) { self.max_significant_digits = max_significant_digits } /// Set the minimum number of significant digits to write. - /// Unsafe, use the builder API for option validation. - /// - /// # Safety - /// - /// Always safe, just marked as unsafe for API compatibility. #[inline(always)] - pub unsafe fn set_min_significant_digits(&mut self, min_significant_digits: OptionUsize) { + pub fn set_min_significant_digits(&mut self, min_significant_digits: OptionUsize) { self.min_significant_digits = min_significant_digits } /// Set the maximum exponent prior to using scientific notation. - /// - /// # Safety - /// - /// Always safe, just marked as unsafe for API compatibility. #[inline(always)] - pub unsafe fn set_positive_exponent_break(&mut self, positive_exponent_break: OptionI32) { + pub fn set_positive_exponent_break(&mut self, positive_exponent_break: OptionI32) { self.positive_exponent_break = positive_exponent_break; } /// Set the minimum exponent prior to using scientific notation. - /// - /// # Safety - /// - /// Always safe, just marked as unsafe for API compatibility. #[inline(always)] - pub unsafe fn set_negative_exponent_break(&mut self, negative_exponent_break: OptionI32) { + pub fn set_negative_exponent_break(&mut self, negative_exponent_break: OptionI32) { self.negative_exponent_break = negative_exponent_break; } /// Set the rounding mode for writing digits with precision control. - /// - /// # Safety - /// - /// Always safe, just marked as unsafe for API compatibility. #[inline(always)] - pub unsafe fn set_round_mode(&mut self, round_mode: RoundMode) { + pub fn set_round_mode(&mut self, round_mode: RoundMode) { self.round_mode = round_mode; } /// Set if we should trim a trailing `".0"` from floats. - /// Unsafe, use the builder API for option validation. - /// - /// # Safety - /// - /// Always safe, just marked as unsafe for API compatibility. #[inline(always)] - pub unsafe fn set_trim_floats(&mut self, trim_floats: bool) { + pub fn set_trim_floats(&mut self, trim_floats: bool) { self.trim_floats = trim_floats; } @@ -570,7 +555,7 @@ impl Options { /// Always safe, but may produce invalid output if the exponent /// is not a valid ASCII character. #[inline(always)] - pub unsafe fn set_exponent(&mut self, exponent: u8) { + pub fn set_exponent(&mut self, exponent: u8) { self.exponent = exponent; } @@ -581,33 +566,33 @@ impl Options { /// Always safe, but may produce invalid output if the decimal point /// is not a valid ASCII character. #[inline(always)] - pub unsafe fn set_decimal_point(&mut self, decimal_point: u8) { + pub fn set_decimal_point(&mut self, decimal_point: u8) { self.decimal_point = decimal_point; } /// Set the string representation for `NaN`. - /// Unsafe, use the builder API for option validation. /// - /// # Safety + /// Panics /// - /// Unsafe if `nan_string.len() > MAX_SPECIAL_STRING_LENGTH`. This might - /// cause a special string larger than the buffer length to be written, - /// causing a buffer overflow, potentially a severe security vulnerability. + /// Setting a value too large may cause a panic even if [FORMATTED_SIZE] + /// elements are provided. + /// + /// [FORMATTED_SIZE]: lexical_util::constants::FormattedSize::FORMATTED_SIZE #[inline(always)] - pub unsafe fn set_nan_string(&mut self, nan_string: Option<&'static [u8]>) { + pub fn set_nan_string(&mut self, nan_string: Option<&'static [u8]>) { self.nan_string = nan_string } /// Set the short string representation for `Infinity` - /// Unsafe, use the builder API for option validation. /// - /// # Safety + /// Panics + /// + /// Setting a value too large may cause a panic even if [FORMATTED_SIZE] + /// elements are provided. /// - /// Unsafe if `nan_string.len() > MAX_SPECIAL_STRING_LENGTH`. This might - /// cause a special string larger than the buffer length to be written, - /// causing a buffer overflow, potentially a severe security vulnerability. + /// [FORMATTED_SIZE]: lexical_util::constants::FormattedSize::FORMATTED_SIZE #[inline(always)] - pub unsafe fn set_inf_string(&mut self, inf_string: Option<&'static [u8]>) { + pub fn set_inf_string(&mut self, inf_string: Option<&'static [u8]>) { self.inf_string = inf_string } @@ -754,10 +739,6 @@ const fn unwrap_str(option: Option<&'static [u8]>) -> &'static [u8] { // --------------------- // Only constants that differ from the standard version are included. -// SAFETY: all of these are safe, since they are checked to be valid -// after calling `build_unchecked`. Furthermore, even though the methods -// are marked as `unsafe`, none of the produced options can cause memory -// safety issues since the special strings are smaller than the buffer size. /// Standard number format. #[rustfmt::skip] @@ -767,576 +748,458 @@ const_assert!(STANDARD.is_valid()); /// Numerical format with a decimal comma. /// This is the standard numerical format for most of the world. #[rustfmt::skip] -pub const DECIMAL_COMMA: Options = unsafe { - Options::builder() +pub const DECIMAL_COMMA: Options = Options::builder() .decimal_point(b',') - .build_unchecked() -}; + .build_unchecked(); const_assert!(DECIMAL_COMMA.is_valid()); /// Numerical format for hexadecimal floats, which use a `p` exponent. #[rustfmt::skip] -pub const HEX_FLOAT: Options = unsafe { - Options::builder() +pub const HEX_FLOAT: Options = Options::builder() .exponent(b'p') - .build_unchecked() -}; + .build_unchecked(); const_assert!(HEX_FLOAT.is_valid()); /// Numerical format where `^` is used as the exponent notation character. /// This isn't very common, but is useful when `e` or `p` are valid digits. #[rustfmt::skip] -pub const CARAT_EXPONENT: Options = unsafe { - Options::builder() +pub const CARAT_EXPONENT: Options = Options::builder() .exponent(b'^') - .build_unchecked() -}; + .build_unchecked(); const_assert!(CARAT_EXPONENT.is_valid()); /// Number format for a Rust literal floating-point number. #[rustfmt::skip] -pub const RUST_LITERAL: Options = unsafe { - Options::builder() +pub const RUST_LITERAL: Options = Options::builder() .nan_string(options::RUST_LITERAL) .inf_string(options::RUST_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(RUST_LITERAL.is_valid()); /// Number format for a Python literal floating-point number. #[rustfmt::skip] -pub const PYTHON_LITERAL: Options = unsafe { - Options::builder() +pub const PYTHON_LITERAL: Options = Options::builder() .nan_string(options::PYTHON_LITERAL) .inf_string(options::PYTHON_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(PYTHON_LITERAL.is_valid()); /// Number format for a C++ literal floating-point number. #[rustfmt::skip] -pub const CXX_LITERAL: Options = unsafe { - Options::builder() +pub const CXX_LITERAL: Options = Options::builder() .nan_string(options::CXX_LITERAL_NAN) .inf_string(options::CXX_LITERAL_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(CXX_LITERAL.is_valid()); /// Number format for a C literal floating-point number. #[rustfmt::skip] -pub const C_LITERAL: Options = unsafe { - Options::builder() +pub const C_LITERAL: Options = Options::builder() .nan_string(options::C_LITERAL_NAN) .inf_string(options::C_LITERAL_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(CXX_LITERAL.is_valid()); /// Number format for a Ruby literal floating-point number. #[rustfmt::skip] -pub const RUBY_LITERAL: Options = unsafe { - Options::builder() +pub const RUBY_LITERAL: Options = Options::builder() .positive_exponent_break(num::NonZeroI32::new(14)) .negative_exponent_break(num::NonZeroI32::new(-4)) .nan_string(options::RUBY_LITERAL_NAN) .inf_string(options::RUBY_LITERAL_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(RUBY_LITERAL.is_valid()); /// Number format to parse a Ruby float from string. #[rustfmt::skip] -pub const RUBY_STRING: Options = unsafe { - Options::builder() +pub const RUBY_STRING: Options = Options::builder() .nan_string(options::RUBY_LITERAL_NAN) .inf_string(options::RUBY_LITERAL_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(RUBY_STRING.is_valid()); /// Number format for a Swift literal floating-point number. #[rustfmt::skip] -pub const SWIFT_LITERAL: Options = unsafe { - Options::builder() +pub const SWIFT_LITERAL: Options = Options::builder() .nan_string(options::SWIFT_LITERAL) .inf_string(options::SWIFT_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(SWIFT_LITERAL.is_valid()); /// Number format for a Go literal floating-point number. #[rustfmt::skip] -pub const GO_LITERAL: Options = unsafe { - Options::builder() +pub const GO_LITERAL: Options = Options::builder() .nan_string(options::GO_LITERAL) .inf_string(options::GO_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(GO_LITERAL.is_valid()); /// Number format for a Haskell literal floating-point number. #[rustfmt::skip] -pub const HASKELL_LITERAL: Options = unsafe { - Options::builder() +pub const HASKELL_LITERAL: Options = Options::builder() .nan_string(options::HASKELL_LITERAL) .inf_string(options::HASKELL_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(HASKELL_LITERAL.is_valid()); /// Number format to parse a Haskell float from string. #[rustfmt::skip] -pub const HASKELL_STRING: Options = unsafe { - Options::builder() +pub const HASKELL_STRING: Options = Options::builder() .inf_string(options::HASKELL_STRING_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(HASKELL_STRING.is_valid()); /// Number format for a Javascript literal floating-point number. #[rustfmt::skip] -pub const JAVASCRIPT_LITERAL: Options = unsafe { - Options::builder() +pub const JAVASCRIPT_LITERAL: Options = Options::builder() .inf_string(options::JAVASCRIPT_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(JAVASCRIPT_LITERAL.is_valid()); /// Number format to parse a Javascript float from string. #[rustfmt::skip] -pub const JAVASCRIPT_STRING: Options = unsafe { - Options::builder() +pub const JAVASCRIPT_STRING: Options = Options::builder() .inf_string(options::JAVASCRIPT_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(JAVASCRIPT_STRING.is_valid()); /// Number format for a Perl literal floating-point number. #[rustfmt::skip] -pub const PERL_LITERAL: Options = unsafe { - Options::builder() +pub const PERL_LITERAL: Options = Options::builder() .nan_string(options::PERL_LITERAL) .inf_string(options::PERL_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(PERL_LITERAL.is_valid()); /// Number format for a PHP literal floating-point number. #[rustfmt::skip] -pub const PHP_LITERAL: Options = unsafe { - Options::builder() +pub const PHP_LITERAL: Options = Options::builder() .nan_string(options::PHP_LITERAL_NAN) .inf_string(options::PHP_LITERAL_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(PHP_LITERAL.is_valid()); /// Number format for a Java literal floating-point number. #[rustfmt::skip] -pub const JAVA_LITERAL: Options = unsafe { - Options::builder() +pub const JAVA_LITERAL: Options = Options::builder() .nan_string(options::JAVA_LITERAL) .inf_string(options::JAVA_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(JAVA_LITERAL.is_valid()); /// Number format to parse a Java float from string. #[rustfmt::skip] -pub const JAVA_STRING: Options = unsafe { - Options::builder() +pub const JAVA_STRING: Options = Options::builder() .inf_string(options::JAVA_STRING_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(JAVA_STRING.is_valid()); /// Number format for an R literal floating-point number. #[rustfmt::skip] -pub const R_LITERAL: Options = unsafe { - Options::builder() +pub const R_LITERAL: Options = Options::builder() .inf_string(options::R_LITERAL_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(R_LITERAL.is_valid()); /// Number format for a Kotlin literal floating-point number. #[rustfmt::skip] -pub const KOTLIN_LITERAL: Options = unsafe { - Options::builder() +pub const KOTLIN_LITERAL: Options = Options::builder() .nan_string(options::KOTLIN_LITERAL) .inf_string(options::KOTLIN_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(KOTLIN_LITERAL.is_valid()); /// Number format to parse a Kotlin float from string. #[rustfmt::skip] -pub const KOTLIN_STRING: Options = unsafe { - Options::builder() +pub const KOTLIN_STRING: Options = Options::builder() .inf_string(options::KOTLIN_STRING_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(KOTLIN_STRING.is_valid()); /// Number format for a Julia literal floating-point number. #[rustfmt::skip] -pub const JULIA_LITERAL: Options = unsafe { - Options::builder() +pub const JULIA_LITERAL: Options = Options::builder() .inf_string(options::JULIA_LITERAL_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(JULIA_LITERAL.is_valid()); /// Number format for a C# literal floating-point number. #[rustfmt::skip] -pub const CSHARP_LITERAL: Options = unsafe { - Options::builder() +pub const CSHARP_LITERAL: Options = Options::builder() .nan_string(options::CSHARP_LITERAL) .inf_string(options::CSHARP_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(CSHARP_LITERAL.is_valid()); /// Number format to parse a C# float from string. #[rustfmt::skip] -pub const CSHARP_STRING: Options = unsafe { - Options::builder() +pub const CSHARP_STRING: Options = Options::builder() .inf_string(options::CSHARP_STRING_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(CSHARP_STRING.is_valid()); /// Number format for a Kawa literal floating-point number. #[rustfmt::skip] -pub const KAWA_LITERAL: Options = unsafe { - Options::builder() +pub const KAWA_LITERAL: Options = Options::builder() .nan_string(options::KAWA) .inf_string(options::KAWA) - .build_unchecked() -}; + .build_unchecked(); const_assert!(KAWA_LITERAL.is_valid()); /// Number format to parse a Kawa float from string. #[rustfmt::skip] -pub const KAWA_STRING: Options = unsafe { - Options::builder() +pub const KAWA_STRING: Options = Options::builder() .nan_string(options::KAWA) .inf_string(options::KAWA) - .build_unchecked() -}; + .build_unchecked(); const_assert!(KAWA_STRING.is_valid()); /// Number format for a Gambit-C literal floating-point number. #[rustfmt::skip] -pub const GAMBITC_LITERAL: Options = unsafe { - Options::builder() +pub const GAMBITC_LITERAL: Options = Options::builder() .nan_string(options::GAMBITC) .inf_string(options::GAMBITC) - .build_unchecked() -}; + .build_unchecked(); const_assert!(GAMBITC_LITERAL.is_valid()); /// Number format to parse a Gambit-C float from string. #[rustfmt::skip] -pub const GAMBITC_STRING: Options = unsafe { - Options::builder() +pub const GAMBITC_STRING: Options = Options::builder() .nan_string(options::GAMBITC) .inf_string(options::GAMBITC) - .build_unchecked() -}; + .build_unchecked(); const_assert!(GAMBITC_STRING.is_valid()); /// Number format for a Guile literal floating-point number. #[rustfmt::skip] -pub const GUILE_LITERAL: Options = unsafe { - Options::builder() +pub const GUILE_LITERAL: Options = Options::builder() .nan_string(options::GUILE) .inf_string(options::GUILE) - .build_unchecked() -}; + .build_unchecked(); const_assert!(GUILE_LITERAL.is_valid()); /// Number format to parse a Guile float from string. #[rustfmt::skip] -pub const GUILE_STRING: Options = unsafe { - Options::builder() +pub const GUILE_STRING: Options = Options::builder() .nan_string(options::GUILE) .inf_string(options::GUILE) - .build_unchecked() -}; + .build_unchecked(); const_assert!(GUILE_STRING.is_valid()); /// Number format for a Clojure literal floating-point number. #[rustfmt::skip] -pub const CLOJURE_LITERAL: Options = unsafe { - Options::builder() +pub const CLOJURE_LITERAL: Options = Options::builder() .nan_string(options::CLOJURE_LITERAL) .inf_string(options::CLOJURE_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(CLOJURE_LITERAL.is_valid()); /// Number format to parse a Clojure float from string. #[rustfmt::skip] -pub const CLOJURE_STRING: Options = unsafe { - Options::builder() +pub const CLOJURE_STRING: Options = Options::builder() .inf_string(options::CLOJURE_STRING_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(CLOJURE_STRING.is_valid()); /// Number format for an Erlang literal floating-point number. #[rustfmt::skip] -pub const ERLANG_LITERAL: Options = unsafe { - Options::builder() +pub const ERLANG_LITERAL: Options = Options::builder() .nan_string(options::ERLANG_LITERAL_NAN) - .build_unchecked() -}; + .build_unchecked(); const_assert!(ERLANG_LITERAL.is_valid()); /// Number format to parse an Erlang float from string. #[rustfmt::skip] -pub const ERLANG_STRING: Options = unsafe { - Options::builder() +pub const ERLANG_STRING: Options = Options::builder() .nan_string(options::ERLANG_STRING) .inf_string(options::ERLANG_STRING) - .build_unchecked() -}; + .build_unchecked(); const_assert!(ERLANG_STRING.is_valid()); /// Number format for an Elm literal floating-point number. #[rustfmt::skip] -pub const ELM_LITERAL: Options = unsafe { - Options::builder() +pub const ELM_LITERAL: Options = Options::builder() .nan_string(options::ELM_LITERAL) .inf_string(options::ELM_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(ELM_LITERAL.is_valid()); /// Number format to parse an Elm float from string. #[rustfmt::skip] -pub const ELM_STRING: Options = unsafe { - Options::builder() +pub const ELM_STRING: Options = Options::builder() .nan_string(options::ELM_STRING_NAN) .inf_string(options::ELM_STRING_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(ELM_STRING.is_valid()); /// Number format for a Scala literal floating-point number. #[rustfmt::skip] -pub const SCALA_LITERAL: Options = unsafe { - Options::builder() +pub const SCALA_LITERAL: Options = Options::builder() .nan_string(options::SCALA_LITERAL) .inf_string(options::SCALA_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(SCALA_LITERAL.is_valid()); /// Number format to parse a Scala float from string. #[rustfmt::skip] -pub const SCALA_STRING: Options = unsafe { - Options::builder() +pub const SCALA_STRING: Options = Options::builder() .inf_string(options::SCALA_STRING_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(SCALA_STRING.is_valid()); /// Number format for an Elixir literal floating-point number. #[rustfmt::skip] -pub const ELIXIR_LITERAL: Options = unsafe { - Options::builder() +pub const ELIXIR_LITERAL: Options = Options::builder() .nan_string(options::ELIXIR) .inf_string(options::ELIXIR) - .build_unchecked() -}; + .build_unchecked(); const_assert!(ELIXIR_LITERAL.is_valid()); /// Number format to parse an Elixir float from string. #[rustfmt::skip] -pub const ELIXIR_STRING: Options = unsafe { - Options::builder() +pub const ELIXIR_STRING: Options = Options::builder() .nan_string(options::ELIXIR) .inf_string(options::ELIXIR) - .build_unchecked() -}; + .build_unchecked(); const_assert!(ELIXIR_STRING.is_valid()); /// Number format for a FORTRAN literal floating-point number. #[rustfmt::skip] -pub const FORTRAN_LITERAL: Options = unsafe { - Options::builder() +pub const FORTRAN_LITERAL: Options = Options::builder() .nan_string(options::FORTRAN_LITERAL) .inf_string(options::FORTRAN_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(FORTRAN_LITERAL.is_valid()); /// Number format for a D literal floating-point number. #[rustfmt::skip] -pub const D_LITERAL: Options = unsafe { - Options::builder() +pub const D_LITERAL: Options = Options::builder() .nan_string(options::D_LITERAL) .inf_string(options::D_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(D_LITERAL.is_valid()); /// Number format for a Coffeescript literal floating-point number. #[rustfmt::skip] -pub const COFFEESCRIPT_LITERAL: Options = unsafe { - Options::builder() +pub const COFFEESCRIPT_LITERAL: Options = Options::builder() .inf_string(options::COFFEESCRIPT_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(COFFEESCRIPT_LITERAL.is_valid()); /// Number format to parse a Coffeescript float from string. #[rustfmt::skip] -pub const COFFEESCRIPT_STRING: Options = unsafe { - Options::builder() +pub const COFFEESCRIPT_STRING: Options = Options::builder() .inf_string(options::COFFEESCRIPT_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(COFFEESCRIPT_STRING.is_valid()); /// Number format for a COBOL literal floating-point number. #[rustfmt::skip] -pub const COBOL_LITERAL: Options = unsafe { - Options::builder() +pub const COBOL_LITERAL: Options = Options::builder() .nan_string(options::COBOL) .inf_string(options::COBOL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(COBOL_LITERAL.is_valid()); /// Number format to parse a COBOL float from string. #[rustfmt::skip] -pub const COBOL_STRING: Options = unsafe { - Options::builder() +pub const COBOL_STRING: Options = Options::builder() .nan_string(options::COBOL) .inf_string(options::COBOL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(COBOL_STRING.is_valid()); /// Number format for an F# literal floating-point number. #[rustfmt::skip] -pub const FSHARP_LITERAL: Options = unsafe { - Options::builder() +pub const FSHARP_LITERAL: Options = Options::builder() .nan_string(options::FSHARP_LITERAL_NAN) .inf_string(options::FSHARP_LITERAL_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(FSHARP_LITERAL.is_valid()); /// Number format for a Visual Basic literal floating-point number. #[rustfmt::skip] -pub const VB_LITERAL: Options = unsafe { - Options::builder() +pub const VB_LITERAL: Options = Options::builder() .nan_string(options::VB_LITERAL) .inf_string(options::VB_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(VB_LITERAL.is_valid()); /// Number format to parse a Visual Basic float from string. #[rustfmt::skip] -pub const VB_STRING: Options = unsafe { - Options::builder() +pub const VB_STRING: Options = Options::builder() .inf_string(options::VB_STRING_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(VB_STRING.is_valid()); /// Number format for an OCaml literal floating-point number. #[rustfmt::skip] -pub const OCAML_LITERAL: Options = unsafe { - Options::builder() +pub const OCAML_LITERAL: Options = Options::builder() .nan_string(options::OCAML_LITERAL_NAN) .inf_string(options::OCAML_LITERAL_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(OCAML_LITERAL.is_valid()); /// Number format for an Objective-C literal floating-point number. #[rustfmt::skip] -pub const OBJECTIVEC_LITERAL: Options = unsafe { - Options::builder() +pub const OBJECTIVEC_LITERAL: Options = Options::builder() .nan_string(options::OBJECTIVEC) .inf_string(options::OBJECTIVEC) - .build_unchecked() -}; + .build_unchecked(); const_assert!(OBJECTIVEC_LITERAL.is_valid()); /// Number format to parse an Objective-C float from string. #[rustfmt::skip] -pub const OBJECTIVEC_STRING: Options = unsafe { - Options::builder() +pub const OBJECTIVEC_STRING: Options = Options::builder() .nan_string(options::OBJECTIVEC) .inf_string(options::OBJECTIVEC) - .build_unchecked() -}; + .build_unchecked(); const_assert!(OBJECTIVEC_STRING.is_valid()); /// Number format for an ReasonML literal floating-point number. #[rustfmt::skip] -pub const REASONML_LITERAL: Options = unsafe { - Options::builder() +pub const REASONML_LITERAL: Options = Options::builder() .nan_string(options::REASONML_LITERAL_NAN) .inf_string(options::REASONML_LITERAL_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(REASONML_LITERAL.is_valid()); /// Number format for a MATLAB literal floating-point number. #[rustfmt::skip] -pub const MATLAB_LITERAL: Options = unsafe { - Options::builder() +pub const MATLAB_LITERAL: Options = Options::builder() .inf_string(options::MATLAB_LITERAL_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(MATLAB_LITERAL.is_valid()); /// Number format for a Zig literal floating-point number. #[rustfmt::skip] -pub const ZIG_LITERAL: Options = unsafe { - Options::builder() +pub const ZIG_LITERAL: Options = Options::builder() .nan_string(options::ZIG_LITERAL) .inf_string(options::ZIG_LITERAL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(ZIG_LITERAL.is_valid()); /// Number format for a Safe literal floating-point number. #[rustfmt::skip] -pub const SAGE_LITERAL: Options = unsafe { - Options::builder() +pub const SAGE_LITERAL: Options = Options::builder() .inf_string(options::SAGE_LITERAL_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(SAGE_LITERAL.is_valid()); /// Number format for a JSON literal floating-point number. #[rustfmt::skip] -pub const JSON: Options = unsafe { - Options::builder() +pub const JSON: Options = Options::builder() .nan_string(options::JSON) .inf_string(options::JSON) - .build_unchecked() -}; + .build_unchecked(); const_assert!(JSON.is_valid()); /// Number format for a TOML literal floating-point number. #[rustfmt::skip] -pub const TOML: Options = unsafe { - Options::builder() +pub const TOML: Options = Options::builder() .nan_string(options::TOML) .inf_string(options::TOML) - .build_unchecked() -}; + .build_unchecked(); const_assert!(TOML.is_valid()); /// Number format for a YAML literal floating-point number. @@ -1345,48 +1208,38 @@ pub const YAML: Options = JSON; /// Number format for an XML literal floating-point number. #[rustfmt::skip] -pub const XML: Options = unsafe { - Options::builder() +pub const XML: Options = Options::builder() .inf_string(options::XML_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(XML.is_valid()); /// Number format for a SQLite literal floating-point number. #[rustfmt::skip] -pub const SQLITE: Options = unsafe { - Options::builder() +pub const SQLITE: Options = Options::builder() .nan_string(options::SQLITE) .inf_string(options::SQLITE) - .build_unchecked() -}; + .build_unchecked(); const_assert!(SQLITE.is_valid()); /// Number format for a PostgreSQL literal floating-point number. #[rustfmt::skip] -pub const POSTGRESQL: Options = unsafe { - Options::builder() +pub const POSTGRESQL: Options = Options::builder() .nan_string(options::POSTGRESQL) .inf_string(options::POSTGRESQL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(POSTGRESQL.is_valid()); /// Number format for a MySQL literal floating-point number. #[rustfmt::skip] -pub const MYSQL: Options = unsafe { - Options::builder() +pub const MYSQL: Options = Options::builder() .nan_string(options::MYSQL) .inf_string(options::MYSQL) - .build_unchecked() -}; + .build_unchecked(); const_assert!(MYSQL.is_valid()); /// Number format for a MongoDB literal floating-point number. #[rustfmt::skip] -pub const MONGODB: Options = unsafe { - Options::builder() +pub const MONGODB: Options = Options::builder() .inf_string(options::MONGODB_INF) - .build_unchecked() -}; + .build_unchecked(); const_assert!(MONGODB.is_valid()); diff --git a/lexical-write-float/tests/api_tests.rs b/lexical-write-float/tests/api_tests.rs index 3e2a4ee0..1e73e104 100644 --- a/lexical-write-float/tests/api_tests.rs +++ b/lexical-write-float/tests/api_tests.rs @@ -80,7 +80,7 @@ fn hex_test() { .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(10)) .build(); - const HEX_OPTIONS: Options = unsafe { Options::builder().exponent(b'^').build_unchecked() }; + const HEX_OPTIONS: Options = Options::builder().exponent(b'^').build_unchecked(); let mut buffer = [b'\x00'; BUFFER_SIZE]; let float = 12345.0f64; diff --git a/lexical-write-float/tests/binary_tests.rs b/lexical-write-float/tests/binary_tests.rs index 520daafa..c5f0b506 100644 --- a/lexical-write-float/tests/binary_tests.rs +++ b/lexical-write-float/tests/binary_tests.rs @@ -46,7 +46,7 @@ const BASE32_2_32: u128 = NumberFormatBuilder::new() .exponent_base(num::NonZeroU8::new(2)) .exponent_radix(num::NonZeroU8::new(32)) .build(); -const HEX_OPTIONS: Options = unsafe { Options::builder().exponent(b'^').build_unchecked() }; +const HEX_OPTIONS: Options = Options::builder().exponent(b'^').build_unchecked(); #[test] fn fast_log2_test() { diff --git a/lexical-write-float/tests/hex_tests.rs b/lexical-write-float/tests/hex_tests.rs index da6eac67..042db6b0 100644 --- a/lexical-write-float/tests/hex_tests.rs +++ b/lexical-write-float/tests/hex_tests.rs @@ -33,7 +33,7 @@ const BASE16_4_10: u128 = NumberFormatBuilder::new() .exponent_base(num::NonZeroU8::new(4)) .exponent_radix(num::NonZeroU8::new(10)) .build(); -const HEX_OPTIONS: Options = unsafe { Options::builder().exponent(b'^').build_unchecked() }; +const HEX_OPTIONS: Options = Options::builder().exponent(b'^').build_unchecked(); // NOTE: This doesn't handle float rounding or truncation. // It assumes this has already been done. diff --git a/lexical-write-float/tests/options_tests.rs b/lexical-write-float/tests/options_tests.rs index 5bd36fb1..68805713 100644 --- a/lexical-write-float/tests/options_tests.rs +++ b/lexical-write-float/tests/options_tests.rs @@ -89,25 +89,23 @@ fn builder_test() { assert_eq!(builder.get_inf_string(), Some("Infinity".as_bytes())); assert!(builder.is_valid()); - assert_eq!(builder.build(), Ok(unsafe { builder.build_unchecked() })); + assert_eq!(builder.build(), Ok(builder.build_unchecked())); } #[test] fn options_test() { let mut opts = Options::new(); - unsafe { - opts.set_max_significant_digits(num::NonZeroUsize::new(10)); - opts.set_min_significant_digits(num::NonZeroUsize::new(5)); - opts.set_positive_exponent_break(num::NonZeroI32::new(9)); - opts.set_negative_exponent_break(num::NonZeroI32::new(-9)); - opts.set_round_mode(options::RoundMode::Truncate); - opts.set_trim_floats(true); - opts.set_exponent(b'^'); - opts.set_decimal_point(b','); - opts.set_nan_string(Some(b"nan")); - opts.set_inf_string(Some(b"Infinity")); - } + opts.set_max_significant_digits(num::NonZeroUsize::new(10)); + opts.set_min_significant_digits(num::NonZeroUsize::new(5)); + opts.set_positive_exponent_break(num::NonZeroI32::new(9)); + opts.set_negative_exponent_break(num::NonZeroI32::new(-9)); + opts.set_round_mode(options::RoundMode::Truncate); + opts.set_trim_floats(true); + opts.set_exponent(b'^'); + opts.set_decimal_point(b','); + opts.set_nan_string(Some(b"nan")); + opts.set_inf_string(Some(b"Infinity")); assert_eq!(opts.max_significant_digits().unwrap().get(), 10); assert_eq!(opts.min_significant_digits().unwrap().get(), 5); diff --git a/lexical-write-integer/src/options.rs b/lexical-write-integer/src/options.rs index 0fa1f6d8..b3ff7cd6 100644 --- a/lexical-write-integer/src/options.rs +++ b/lexical-write-integer/src/options.rs @@ -27,20 +27,15 @@ impl OptionsBuilder { } /// Build the Options struct with bounds validation. - /// - /// # Safety - /// - /// Safe as long as `is_valid` is true. #[inline(always)] - pub const unsafe fn build_unchecked(&self) -> Options { + pub const fn build_unchecked(&self) -> Options { Options {} } /// Build the Options struct. #[inline(always)] pub const fn build(&self) -> Result { - // SAFETY: always safe, since it must be valid. - Ok(unsafe { self.build_unchecked() }) + Ok(self.build_unchecked()) } }