lexical_write_float/options.rs
1//! Configuration options for writing floats.
2//!
3//! This enables extensive control over how the float is written, from
4//! control characters like the decimal point, to the use of exponent
5//! notation, and the number of significant digits.
6//!
7//! # Examples
8//!
9//! For example, to customize the writing of numbers for new exponent
10//! and decimal point characters, you would use [`Options`] to create
11//! a custom format and write the integer using the format.
12//!
13//! ```rust
14//! # use core::{num, str};
15//! use lexical_write_float::{FormattedSize, Options, ToLexicalWithOptions};
16//! use lexical_write_float::format::STANDARD;
17//!
18//! let value = 1.234e45f64;
19//!
20//! const CUSTOM: Options = Options::builder()
21//! // write exponents as "1.2^10" and not "1.2e10"
22//! .exponent(b'^')
23//! // use the European decimal point, so "1,2" and not "1.2"
24//! .decimal_point(b',')
25//! .build_strict();
26//!
27//! const BUFFER_SIZE: usize = CUSTOM.buffer_size_const::<f64, STANDARD>();
28//! let mut buffer = [0u8; BUFFER_SIZE];
29//! let digits = value.to_lexical_with_options::<STANDARD>(&mut buffer, &CUSTOM);
30//! assert_eq!(str::from_utf8(digits), Ok("1,234^45"));
31//! ```
32//!
33//! # Pre-Defined Formats
34//!
35//! These are the pre-defined formats for parsing numbers from various
36//! programming, markup, and data languages.
37//!
38//! - [`STANDARD`]: Standard number format.
39//! - [`DECIMAL_COMMA`]: Numerical format with a decimal comma.
40//! - [`HEX_FLOAT`]: Numerical format for hexadecimal floats, which use a `p`
41//! exponent.
42//! - [`CARAT_EXPONENT`]: Numerical format where `^` is used as the exponent
43//! notation character.
44//! - [`RUST_LITERAL`]: Number format for a [`Rust`] literal floating-point
45//! number.
46//! - [`PYTHON_LITERAL`]: Number format for a [`Python`] literal floating-point
47//! number.
48//! - [`CXX_LITERAL`]: Number format for a [`C++`] literal floating-point
49//! number.
50//! - [`C_LITERAL`]: Number format for a [`C`] literal floating-point number.
51//! - [`RUBY_LITERAL`]: Number format for a [`Ruby`] literal floating-point
52//! number.
53//! - [`RUBY_STRING`]: Number format to parse a [`Ruby`] float from string.
54//! - [`SWIFT_LITERAL`]: Number format for a [`Swift`] literal floating-point
55//! number.
56//! - [`GO_LITERAL`]: Number format for a [`Golang`] literal floating-point
57//! number.
58//! - [`HASKELL_LITERAL`]: Number format for a [`Haskell`] literal
59//! floating-point number.
60//! - [`HASKELL_STRING`]: Number format to parse a [`Haskell`] float from
61//! string.
62//! - [`JAVASCRIPT_LITERAL`]: Number format for a [`Javascript`] literal
63//! floating-point number.
64//! - [`JAVASCRIPT_STRING`]: Number format to parse a [`Javascript`] float from
65//! string.
66//! - [`PERL_LITERAL`]: Number format for a [`Perl`] literal floating-point
67//! number.
68//! - [`PHP_LITERAL`]: Number format for a [`PHP`] literal floating-point
69//! number.
70//! - [`JAVA_LITERAL`]: Number format for a [`Java`] literal floating-point
71//! number.
72//! - [`JAVA_STRING`]: Number format to parse a [`Java`] float from string.
73//! - [`R_LITERAL`]: Number format for an [`R`] literal floating-point number.
74//! - [`KOTLIN_LITERAL`]: Number format for a [`Kotlin`] literal floating-point
75//! number.
76//! - [`KOTLIN_STRING`]: Number format to parse a [`Kotlin`] float from string.
77//! - [`JULIA_LITERAL`]: Number format for a [`Julia`] literal floating-point
78//! number.
79//! - [`CSHARP_LITERAL`]: Number format for a [`C#`] literal floating-point
80//! number.
81//! - [`CSHARP_STRING`]: Number format to parse a [`C#`] float from string.
82//! - [`KAWA_LITERAL`]: Number format for a [`Kawa`] literal floating-point
83//! number.
84//! - [`KAWA_STRING`]: Number format to parse a [`Kawa`] float from string.
85//! - [`GAMBITC_LITERAL`]: Number format for a [`Gambit-C`] literal
86//! floating-point number.
87//! - [`GAMBITC_STRING`]: Number format to parse a [`Gambit-C`] float from
88//! string.
89//! - [`GUILE_LITERAL`]: Number format for a [`Guile`] literal floating-point
90//! number.
91//! - [`GUILE_STRING`]: Number format to parse a [`Guile`] float from string.
92//! - [`CLOJURE_LITERAL`]: Number format for a [`Clojure`] literal
93//! floating-point number.
94//! - [`CLOJURE_STRING`]: Number format to parse a [`Clojure`] float from
95//! string.
96//! - [`ERLANG_LITERAL`]: Number format for an [`Erlang`] literal floating-point
97//! number.
98//! - [`ERLANG_STRING`]: Number format to parse an [`Erlang`] float from string.
99//! - [`ELM_LITERAL`]: Number format for an [`Elm`] literal floating-point
100//! number.
101//! - [`ELM_STRING`]: Number format to parse an [`Elm`] float from string.
102//! - [`SCALA_LITERAL`]: Number format for a [`Scala`] literal floating-point
103//! number.
104//! - [`SCALA_STRING`]: Number format to parse a [`Scala`] float from string.
105//! - [`ELIXIR_LITERAL`]: Number format for an [`Elixir`] literal floating-point
106//! number.
107//! - [`ELIXIR_STRING`]: Number format to parse an [`Elixir`] float from string.
108//! - [`FORTRAN_LITERAL`]: Number format for a [`FORTRAN`] literal
109//! floating-point number.
110//! - [`D_LITERAL`]: Number format for a [`D`] literal floating-point number.
111//! - [`COFFEESCRIPT_LITERAL`]: Number format for a [`Coffeescript`] literal
112//! floating-point number.
113//! - [`COFFEESCRIPT_STRING`]: Number format to parse a [`Coffeescript`] float
114//! from string.
115//! - [`COBOL_LITERAL`]: Number format for a [`COBOL`] literal floating-point
116//! number.
117//! - [`COBOL_STRING`]: Number format to parse a [`COBOL`] float from string.
118//! - [`FSHARP_LITERAL`]: Number format for an [`F#`] literal floating-point
119//! number.
120//! - [`VB_LITERAL`]: Number format for a [`Visual Basic`] literal
121//! floating-point number.
122//! - [`VB_STRING`]: Number format to parse a [`Visual Basic`] float from
123//! string.
124//! - [`OCAML_LITERAL`]: Number format for an [`OCaml`] literal floating-point
125//! number.
126//! - [`OBJECTIVEC_LITERAL`]: Number format for an [`Objective-C`] literal
127//! floating-point number.
128//! - [`OBJECTIVEC_STRING`]: Number format to parse an [`Objective-C`] float
129//! from string.
130//! - [`REASONML_LITERAL`]: Number format for an [`ReasonML`] literal
131//! floating-point number.
132//! - [`MATLAB_LITERAL`]: Number format for a [`MATLAB`] literal floating-point
133//! number.
134//! - [`ZIG_LITERAL`]: Number format for a [`Zig`] literal floating-point
135//! number.
136//! - [`SAGE_LITERAL`]: Number format for a [`Sage`] literal floating-point
137//! number.
138//! - [`JSON`]: Number format for a [`JSON`][`JSON-REF`] literal floating-point
139//! number.
140//! - [`TOML`]: Number format for a [`TOML`][`TOML-REF`] literal floating-point
141//! number.
142//! - [`YAML`]: Number format for a [`YAML`][`YAML-REF`] literal floating-point
143//! number.
144//! - [`XML`]: Number format for an [`XML`][`XML-REF`] literal floating-point
145//! number.
146//! - [`SQLITE`]: Number format for a [`SQLite`] literal floating-point number.
147//! - [`POSTGRESQL`]: Number format for a [`PostgreSQL`] literal floating-point
148//! number.
149//! - [`MYSQL`]: Number format for a [`MySQL`] literal floating-point number.
150//! - [`MONGODB`]: Number format for a [`MongoDB`] literal floating-point
151//! number.
152//!
153//! <!-- References -->
154//!
155//! [`Rust`]: https://www.rust-lang.org/
156//! [`Python`]: https://www.python.org/
157//! [`C++`]: https://en.cppreference.com/w/
158//! [`C`]: https://en.cppreference.com/w/c
159//! [`Ruby`]: https://www.ruby-lang.org/en/
160//! [`Swift`]: https://developer.apple.com/swift/
161//! [`Golang`]: https://go.dev/
162//! [`Haskell`]: https://www.haskell.org/
163//! [`Javascript`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript
164//! [`Perl`]: https://www.perl.org/
165//! [`PHP`]: https://www.php.net/
166//! [`Java`]: https://www.java.com/en/
167//! [`R`]: https://www.r-project.org/
168//! [`Kotlin`]: https://kotlinlang.org/
169//! [`Julia`]: https://julialang.org/
170//! [`C#`]: https://learn.microsoft.com/en-us/dotnet/csharp/
171//! [`Kawa`]: https://www.gnu.org/software/kawa/
172//! [`Gambit-C`]: https://gambitscheme.org/
173//! [`Guile`]: https://www.gnu.org/software/guile/
174//! [`Clojure`]: https://clojure.org/
175//! [`Erlang`]: https://www.erlang.org/
176//! [`Elm`]: https://elm-lang.org/
177//! [`Scala`]: https://www.scala-lang.org/
178//! [`Elixir`]: https://elixir-lang.org/
179//! [`FORTRAN`]: https://fortran-lang.org/
180//! [`D`]: https://dlang.org/
181//! [`Coffeescript`]: https://coffeescript.org/
182//! [`Cobol`]: https://www.ibm.com/think/topics/cobol
183//! [`F#`]: https://fsharp.org/
184//! [`Visual Basic`]: https://learn.microsoft.com/en-us/dotnet/visual-basic/
185//! [`OCaml`]: https://ocaml.org/
186//! [`Objective-C`]: https://en.wikipedia.org/wiki/Objective-C
187//! [`ReasonML`]: https://reasonml.github.io/
188//! [`Matlab`]: https://www.mathworks.com/products/matlab.html
189//! [`Zig`]: https://ziglang.org/
190//! [`Sage`]: https://www.sagemath.org/
191//! [`JSON-REF`]: https://www.json.org/json-en.html
192//! [`TOML-REF`]: https://toml.io/en/
193//! [`YAML-REF`]: https://yaml.org/
194//! [`XML-REF`]: https://en.wikipedia.org/wiki/XML
195//! [`SQLite`]: https://www.sqlite.org/
196//! [`PostgreSQL`]: https://www.postgresql.org/
197//! [`MySQL`]: https://www.mysql.com/
198//! [`MongoDB`]: https://www.mongodb.com/
199
200use core::num;
201
202use lexical_util::ascii::{is_valid_ascii, is_valid_letter_slice};
203use lexical_util::constants::FormattedSize;
204use lexical_util::error::Error;
205use lexical_util::format::NumberFormat;
206use lexical_util::options::{self, WriteOptions};
207use lexical_util::result::Result;
208
209// NOTE: Rust guarantees the sizes are the same:
210// https://doc.rust-lang.org/std/num/struct.NonZero.html
211
212/// Type with the exact same size as a `usize`.
213#[doc(hidden)]
214pub type OptionUsize = Option<num::NonZeroUsize>;
215
216/// Type with the exact same size as a `i32`.
217#[doc(hidden)]
218pub type OptionI32 = Option<num::NonZeroI32>;
219
220/// Const evaluation of `max` for integers.
221macro_rules! max {
222 ($x:expr, $y:expr) => {{
223 let x = $x;
224 let y = $y;
225 if x >= y {
226 x
227 } else {
228 y
229 }
230 }};
231}
232
233/// Const evaluation of `min` for integers.
234macro_rules! min {
235 ($x:expr, $y:expr) => {{
236 let x = $x;
237 let y = $y;
238 if x <= y {
239 x
240 } else {
241 y
242 }
243 }};
244}
245
246/// Enumeration for how to round floats with precision control.
247///
248/// For example, using [`Round`][RoundMode::Round], `1.2345` rounded
249/// to 4 digits would be `1.235`, while [`Truncate`][RoundMode::Truncate]
250/// would be `1.234`.
251#[derive(Debug, Copy, Clone, PartialEq, Eq)]
252pub enum RoundMode {
253 /// Round to the nearest float string with the given number of significant
254 /// digits.
255 Round,
256
257 /// Truncate the float string with the given number of significant digits.
258 Truncate,
259}
260
261/// Maximum length for a special string.
262pub const MAX_SPECIAL_STRING_LENGTH: usize = 50;
263
264/// Builder for [`Options`].
265///
266/// This enables extensive control over how the float is written, from
267/// control characters like the decimal point, to the use of exponent
268/// notation, and the number of significant digits.
269///
270/// # Examples
271///
272/// For example, to customize the writing of numbers for new exponent
273/// and decimal point characters, you would use:
274///
275/// ```rust
276/// # use core::{num, str};
277/// use lexical_write_float::{FormattedSize, Options, ToLexicalWithOptions};
278/// use lexical_write_float::format::STANDARD;
279///
280/// let value = 1.234e45f64;
281///
282/// const CUSTOM: Options = Options::builder()
283/// // write exponents as "1.2^10" and not "1.2e10"
284/// .exponent(b'^')
285/// // use the European decimal point, so "1,2" and not "1.2"
286/// .decimal_point(b',')
287/// .build_strict();
288///
289/// const BUFFER_SIZE: usize = CUSTOM.buffer_size_const::<f64, STANDARD>();
290/// let mut buffer = [0u8; BUFFER_SIZE];
291/// let digits = value.to_lexical_with_options::<STANDARD>(&mut buffer, &CUSTOM);
292/// assert_eq!(str::from_utf8(digits), Ok("1,234^45"));
293/// ```
294#[derive(Debug, Clone, PartialEq, Eq)]
295pub struct OptionsBuilder {
296 /// Maximum number of significant digits to write.
297 ///
298 /// If not set, it defaults to the algorithm's default.
299 max_significant_digits: OptionUsize,
300
301 /// Minimum number of significant digits to write.
302 ///
303 /// If not set, it defaults to the algorithm's default.
304 /// Note that this isn't fully respected: if you wish to format
305 /// `0.1` with 25 significant digits, the correct result **should**
306 /// be `0.100000000000000005551115`. However, we would output
307 /// `0.100000000000000000000000`, which is still the nearest float.
308 min_significant_digits: OptionUsize,
309
310 /// Maximum exponent prior to using scientific notation.
311 ///
312 /// This is ignored if the exponent base is not the same as the mantissa
313 /// radix. If not provided, use the algorithm's default.
314 positive_exponent_break: OptionI32,
315
316 /// Minimum exponent prior to using scientific notation.
317 ///
318 /// This is ignored if the exponent base is not the same as the mantissa
319 /// radix. If not provided, use the algorithm's default.
320 negative_exponent_break: OptionI32,
321
322 /// Rounding mode for writing digits with precision control.
323 round_mode: RoundMode,
324
325 /// Trim the trailing ".0" from integral float strings.
326 ///
327 /// If used in conjunction with [`min_significant_digits`],
328 /// this will still trim all the significant digits if an integral
329 /// value is provided.
330 ///
331 /// [`min_significant_digits`]: Self::min_significant_digits
332 trim_floats: bool,
333
334 /// Character to designate the exponent component of a float.
335 exponent: u8,
336
337 /// Character to separate the integer from the fraction components.
338 decimal_point: u8,
339
340 /// String representation of Not A Number, aka `NaN`.
341 nan_string: Option<&'static [u8]>,
342
343 /// String representation of `Infinity`.
344 inf_string: Option<&'static [u8]>,
345}
346
347impl OptionsBuilder {
348 // CONSTRUCTORS
349
350 #[inline(always)]
351 pub const fn new() -> Self {
352 Self {
353 max_significant_digits: None,
354 min_significant_digits: None,
355 positive_exponent_break: None,
356 negative_exponent_break: None,
357 round_mode: RoundMode::Round,
358 trim_floats: false,
359 exponent: b'e',
360 decimal_point: b'.',
361 nan_string: Some(b"NaN"),
362 inf_string: Some(b"inf"),
363 }
364 }
365
366 // GETTERS
367
368 /// Get the maximum number of significant digits to write.
369 ///
370 /// This limits the total number of written digits, truncating based
371 /// on the [`round_mode`] if more digits would normally be written. If
372 /// no value is provided, then it writes as many digits as required to
373 /// create an unambiguous representation of the float.
374 ///
375 /// # Examples
376 ///
377 /// ```rust
378 /// use lexical_write_float::Options;
379 ///
380 /// let builder = Options::builder();
381 /// assert_eq!(builder.get_max_significant_digits(), None);
382 /// ```
383 ///
384 /// [`round_mode`]: Self::round_mode
385 #[inline(always)]
386 pub const fn get_max_significant_digits(&self) -> OptionUsize {
387 self.max_significant_digits
388 }
389
390 /// Get the minimum number of significant digits to write.
391 ///
392 /// If more digits exist, such as writing "1.2" with a minimum of 5
393 /// significant digits, then `0`s are appended to the end of the digits. If
394 /// no value is provided, then it writes as few digits as required to
395 /// create an unambiguous representation of the float.
396 ///
397 /// # Examples
398 ///
399 /// ```rust
400 /// use lexical_write_float::Options;
401 ///
402 /// let builder = Options::builder();
403 /// assert_eq!(builder.get_min_significant_digits(), None);
404 /// ```
405 #[inline(always)]
406 pub const fn get_min_significant_digits(&self) -> OptionUsize {
407 self.min_significant_digits
408 }
409
410 /// Get the maximum exponent prior to using scientific notation.
411 ///
412 /// If the value is set to `300`, then any value with magnitude `>= 1e300`
413 /// (for base 10) will be writen in exponent notation, while any lower
414 /// value will be written in decimal form. If no value is provided, for
415 /// decimal floats, this defaults to `9`.
416 ///
417 /// # Examples
418 ///
419 /// ```rust
420 /// use lexical_write_float::Options;
421 ///
422 /// let builder = Options::builder();
423 /// assert_eq!(builder.get_positive_exponent_break(), None);
424 /// ```
425 #[inline(always)]
426 pub const fn get_positive_exponent_break(&self) -> OptionI32 {
427 self.positive_exponent_break
428 }
429
430 /// Get the minimum exponent prior to using scientific notation.
431 ///
432 /// If the value is set to `-300`, then any value with magnitude `< 1e-300`
433 /// (for base 10) will be writen in exponent notation, while any larger
434 /// value will be written in decimal form. If no value is provided, for
435 /// decimal floats, this defaults to `-5`.
436 ///
437 /// # Examples
438 ///
439 /// ```rust
440 /// use lexical_write_float::Options;
441 ///
442 /// let builder = Options::builder();
443 /// assert_eq!(builder.get_negative_exponent_break(), None);
444 /// ```
445 #[inline(always)]
446 pub const fn get_negative_exponent_break(&self) -> OptionI32 {
447 self.negative_exponent_break
448 }
449
450 /// Get the rounding mode for writing digits with precision control.
451 ///
452 /// For example, writing `1.23456` with 5 significant digits with
453 /// [`RoundMode::Round`] would produce `"1.2346"` while
454 /// [`RoundMode::Truncate`] would produce `"1.2345"`. Defaults to
455 /// [`RoundMode::Round`].
456 ///
457 /// # Examples
458 ///
459 /// ```rust
460 /// use lexical_write_float::{Options, RoundMode};
461 ///
462 /// let builder = Options::builder();
463 /// assert_eq!(builder.get_round_mode(), RoundMode::Round);
464 /// ```
465 #[inline(always)]
466 pub const fn get_round_mode(&self) -> RoundMode {
467 self.round_mode
468 }
469
470 /// Get if we should trim a trailing `".0"` from integral floats.
471 ///
472 /// If used in conjunction with [`min_significant_digits`],
473 /// this will still trim all the significant digits if an integral
474 /// value is provided. Defaults to [`false`].
475 ///
476 /// # Examples
477 ///
478 /// ```rust
479 /// use lexical_write_float::Options;
480 ///
481 /// let builder = Options::builder();
482 /// assert_eq!(builder.get_trim_floats(), false);
483 /// ```
484 ///
485 /// [`min_significant_digits`]: Self::min_significant_digits
486 #[inline(always)]
487 pub const fn get_trim_floats(&self) -> bool {
488 self.trim_floats
489 }
490
491 /// Get the character to designate the exponent component of a float.
492 ///
493 /// Any non-control character is valid, but `\t` to `\r` are also valid.
494 /// The full range is `[0x09, 0x0D]` and `[0x20, 0x7F]`. Defaults to `e`.
495 ///
496 /// # Examples
497 ///
498 /// ```rust
499 /// use lexical_write_float::Options;
500 ///
501 /// let builder = Options::builder();
502 /// assert_eq!(builder.get_exponent(), b'e');
503 /// ```
504 #[inline(always)]
505 pub const fn get_exponent(&self) -> u8 {
506 self.exponent
507 }
508
509 /// Get the character to separate the integer from the fraction components.
510 ///
511 /// Any non-control character is valid, but `\t` to `\r` are also valid.
512 /// The full range is `[0x09, 0x0D]` and `[0x20, 0x7F]`. Defaults to `.`.
513 ///
514 /// # Examples
515 ///
516 /// ```rust
517 /// use lexical_write_float::Options;
518 ///
519 /// let builder = Options::builder();
520 /// assert_eq!(builder.get_decimal_point(), b'.');
521 /// ```
522 #[inline(always)]
523 pub const fn get_decimal_point(&self) -> u8 {
524 self.decimal_point
525 }
526
527 /// Get the string representation for `NaN`.
528 ///
529 /// The first character must start with `N` or `n` and all characters must
530 /// be valid ASCII letters (`A-Z` or `a-z`). If set to `None`, then writing
531 /// [`NaN`][f64::NAN] leads to an error. Defaults to `NaN`.
532 ///
533 /// # Examples
534 ///
535 /// ```rust
536 /// use lexical_write_float::Options;
537 ///
538 /// let builder = Options::builder();
539 /// assert_eq!(builder.get_nan_string(), Some("NaN".as_bytes()));
540 /// ```
541 #[inline(always)]
542 pub const fn get_nan_string(&self) -> Option<&'static [u8]> {
543 self.nan_string
544 }
545
546 /// Get the string representation for `Infinity`.
547 ///
548 /// The first character must start with `I` or `i` and all characters must
549 /// be valid ASCII letters (`A-Z` or `a-z`). If set to `None`, then writing
550 /// [`Infinity`][f64::INFINITY] returns an error. Defaults to `inf`.
551 ///
552 /// # Examples
553 ///
554 /// ```rust
555 /// use lexical_write_float::Options;
556 ///
557 /// let builder = Options::builder();
558 /// assert_eq!(builder.get_inf_string(), Some("inf".as_bytes()));
559 /// ```
560 #[inline(always)]
561 pub const fn get_inf_string(&self) -> Option<&'static [u8]> {
562 self.inf_string
563 }
564
565 /// Get the string representation for `Infinity`. Alias for
566 /// [`get_inf_string`].
567 ///
568 /// The first character must start with `I` or `i` and all characters must
569 /// be valid ASCII letters (`A-Z` or `a-z`). If set to `None`, then writing
570 /// [`Infinity`][f64::INFINITY] returns an error. Defaults to `inf`.
571 ///
572 /// [`get_inf_string`]: Self::get_inf_string
573 ///
574 /// # Examples
575 ///
576 /// ```rust
577 /// use lexical_write_float::Options;
578 ///
579 /// let builder = Options::builder();
580 /// assert_eq!(builder.get_infinity_string(), Some("inf".as_bytes()));
581 /// ```
582 #[inline(always)]
583 pub const fn get_infinity_string(&self) -> Option<&'static [u8]> {
584 self.inf_string
585 }
586
587 // SETTERS
588
589 /// Set the maximum number of significant digits to write.
590 ///
591 /// This limits the total number of written digits, truncating based
592 /// on the [`round_mode`] if more digits would normally be written. If
593 /// no value is provided, then it writes as many digits as required to
594 /// create an unambiguous representation of the float.
595 ///
596 /// # Examples
597 ///
598 /// ```rust
599 /// use core::num::NonZeroUsize;
600 ///
601 /// use lexical_write_float::Options;
602 ///
603 /// let max_digits = NonZeroUsize::new(300);
604 /// let builder = Options::builder()
605 /// .max_significant_digits(max_digits);
606 /// assert_eq!(builder.get_max_significant_digits(), max_digits);
607 /// ```
608 ///
609 /// # Panics
610 ///
611 /// This will panic when building the options or writing the float if the
612 /// value is smaller than [`min_significant_digits`].
613 ///
614 /// [`round_mode`]: Self::round_mode
615 /// [`min_significant_digits`]: Self::min_significant_digits
616 #[inline(always)]
617 pub const fn max_significant_digits(mut self, max_significant_digits: OptionUsize) -> Self {
618 self.max_significant_digits = max_significant_digits;
619 self
620 }
621
622 /// Set the minimum number of significant digits to write.
623 ///
624 /// If more digits exist, such as writing "1.2" with a minimum of 5
625 /// significant digits, then `0`s are appended to the end of the digits.
626 /// If no value is provided, then it writes as few digits as required to
627 /// create an unambiguous representation of the float.
628 ///
629 /// # Examples
630 ///
631 /// ```rust
632 /// use core::num::NonZeroUsize;
633 ///
634 /// use lexical_write_float::Options;
635 ///
636 /// let min_digits = NonZeroUsize::new(10);
637 /// let builder = Options::builder()
638 /// .min_significant_digits(min_digits);
639 /// assert_eq!(builder.get_min_significant_digits(), min_digits);
640 /// ```
641 ///
642 /// # Panics
643 ///
644 /// This will panic when building the options or writing the float if the
645 /// value is larger than [`max_significant_digits`].
646 ///
647 /// [`max_significant_digits`]: Self::max_significant_digits
648 #[inline(always)]
649 pub const fn min_significant_digits(mut self, min_significant_digits: OptionUsize) -> Self {
650 self.min_significant_digits = min_significant_digits;
651 self
652 }
653
654 /// Set the maximum exponent prior to using scientific notation.
655 ///
656 /// If the value is set to `300`, then any value with magnitude `>= 1e300`
657 /// (for base 10) will be writen in exponent notation, while any lower
658 /// value will be written in decimal form. If no value is provided, for
659 /// decimal floats, this defaults to `9`.
660 ///
661 /// # Examples
662 ///
663 /// ```rust
664 /// use core::num::NonZeroI32;
665 ///
666 /// use lexical_write_float::Options;
667 ///
668 /// let pos_break = NonZeroI32::new(3);
669 /// let builder = Options::builder()
670 /// .positive_exponent_break(pos_break);
671 /// assert_eq!(builder.get_positive_exponent_break(), pos_break);
672 /// ```
673 ///
674 /// # Panics
675 ///
676 /// Panics if the value is `<= 0`.
677 #[inline(always)]
678 pub const fn positive_exponent_break(mut self, positive_exponent_break: OptionI32) -> Self {
679 self.positive_exponent_break = positive_exponent_break;
680 self
681 }
682
683 /// Set the minimum exponent prior to using scientific notation.
684 ///
685 /// If the value is set to `-300`, then any value with magnitude `< 1e-300`
686 /// (for base 10) will be writen in exponent notation, while any larger
687 /// value will be written in decimal form. If no value is provided, for
688 /// decimal floats, this defaults to `-5`.
689 ///
690 /// # Examples
691 ///
692 /// ```rust
693 /// use core::num::NonZeroI32;
694 ///
695 /// use lexical_write_float::Options;
696 ///
697 /// let neg_break = NonZeroI32::new(-3);
698 /// let builder = Options::builder()
699 /// .negative_exponent_break(neg_break);
700 /// assert_eq!(builder.get_negative_exponent_break(), neg_break);
701 /// ```
702 ///
703 /// # Panics
704 ///
705 /// Panics if the value is `>= 0`.
706 #[inline(always)]
707 pub const fn negative_exponent_break(mut self, negative_exponent_break: OptionI32) -> Self {
708 self.negative_exponent_break = negative_exponent_break;
709 self
710 }
711
712 /// Set the rounding mode for writing digits with precision control.
713 ///
714 /// For example, writing `1.23456` with 5 significant digits with
715 /// [`RoundMode::Round`] would produce `"1.2346"` while
716 /// [`RoundMode::Truncate`] would produce `"1.2345"`. Defaults to
717 /// [`RoundMode::Round`].
718 ///
719 /// # Examples
720 ///
721 /// ```rust
722 /// # #[cfg(all(feature = "format", feature = "radix"))] {
723 /// use core::{num, str};
724 ///
725 /// use lexical_write_float::{RoundMode, Options, ToLexicalWithOptions};
726 /// use lexical_write_float::format::STANDARD;
727 ///
728 /// let value = 1.23456f64;
729 ///
730 /// // truncating
731 /// const TRUNCATE: Options = Options::builder()
732 /// // truncate numbers when writing less digits than present, rather than round
733 /// .round_mode(RoundMode::Truncate)
734 /// // the maximum number of significant digits to write
735 /// .max_significant_digits(num::NonZeroUsize::new(5))
736 /// // build the options, panicking if they're invalid
737 /// .build_strict();
738 /// const TRUNCATE_SIZE: usize = TRUNCATE.buffer_size_const::<f64, STANDARD>();
739 /// let mut buffer = [0u8; TRUNCATE_SIZE];
740 /// let digits = value.to_lexical_with_options::<STANDARD>(&mut buffer, &TRUNCATE);
741 /// assert_eq!(str::from_utf8(digits), Ok("1.2345"));
742 ///
743 /// // rounding
744 /// const ROUND: Options = Options::builder()
745 /// // round to the nearest number when writing less digits than present
746 /// .round_mode(RoundMode::Round)
747 /// // the maximum number of significant digits to write
748 /// .max_significant_digits(num::NonZeroUsize::new(5))
749 /// // build the options, panicking if they're invalid
750 /// .build_strict();
751 /// const ROUND_SIZE: usize = ROUND.buffer_size_const::<f64, STANDARD>();
752 /// let mut buffer = [0u8; ROUND_SIZE];
753 /// let digits = value.to_lexical_with_options::<STANDARD>(&mut buffer, &ROUND);
754 /// assert_eq!(str::from_utf8(digits), Ok("1.2346"));
755 /// # }
756 /// ```
757 #[inline(always)]
758 pub const fn round_mode(mut self, round_mode: RoundMode) -> Self {
759 self.round_mode = round_mode;
760 self
761 }
762
763 /// Set if we should trim a trailing `".0"` from integral floats.
764 ///
765 /// If used in conjunction with [`min_significant_digits`],
766 /// this will still trim all the significant digits if an integral
767 /// value is provided. Defaults to [`false`].
768 ///
769 /// # Examples
770 ///
771 /// ```rust
772 /// use lexical_write_float::Options;
773 ///
774 /// let builder = Options::builder()
775 /// .trim_floats(true);
776 /// assert_eq!(builder.get_trim_floats(), true);
777 /// ```
778 ///
779 /// [`min_significant_digits`]: Self::min_significant_digits
780 #[inline(always)]
781 pub const fn trim_floats(mut self, trim_floats: bool) -> Self {
782 self.trim_floats = trim_floats;
783 self
784 }
785
786 /// Set the character to designate the exponent component of a float.
787 ///
788 /// Any non-control character is valid, but `\t` to `\r` are also valid.
789 /// The full range is `[0x09, 0x0D]` and `[0x20, 0x7F]`. Defaults to `e`.
790 ///
791 /// # Examples
792 ///
793 /// ```rust
794 /// use lexical_write_float::Options;
795 ///
796 /// let builder = Options::builder()
797 /// .exponent(b'^');
798 /// assert_eq!(builder.get_exponent(), b'^');
799 /// ```
800 #[inline(always)]
801 pub const fn exponent(mut self, exponent: u8) -> Self {
802 self.exponent = exponent;
803 self
804 }
805
806 /// Set the character to separate the integer from the fraction components.
807 ///
808 /// Any non-control character is valid, but `\t` to `\r` are also valid.
809 /// The full range is `[0x09, 0x0D]` and `[0x20, 0x7F]`. Defaults to `.`.
810 ///
811 /// # Examples
812 ///
813 /// ```rust
814 /// use lexical_write_float::Options;
815 ///
816 /// let builder = Options::builder()
817 /// .decimal_point(b'^');
818 /// assert_eq!(builder.get_decimal_point(), b'^');
819 /// ```
820 #[inline(always)]
821 pub const fn decimal_point(mut self, decimal_point: u8) -> Self {
822 self.decimal_point = decimal_point;
823 self
824 }
825
826 /// Set the string representation for `NaN`.
827 ///
828 /// The first character must start with `N` or `n` and all characters must
829 /// be valid ASCII letters (`A-Z` or `a-z`). If set to `None`, then writing
830 /// [`NaN`][f64::NAN] returns an error. Defaults to `NaN`.
831 ///
832 /// # Examples
833 ///
834 /// ```rust
835 /// use lexical_write_float::Options;
836 ///
837 /// let builder = Options::builder()
838 /// .nan_string(Some(b"nan"));
839 /// assert_eq!(builder.get_nan_string(), Some(b"nan".as_ref()));
840 /// ```
841 ///
842 /// Panics
843 ///
844 /// Setting a value with more than 50 elements will panic at runtime. You
845 /// should always build the format using [`build_strict`] or checking
846 /// [`is_valid`] prior to using the format, to avoid unexpected panics.
847 ///
848 /// [`FORMATTED_SIZE`]: `lexical_util::constants::FormattedSize::FORMATTED_SIZE`
849 /// [`build_strict`]: Self::build_strict
850 /// [`is_valid`]: Self::is_valid
851 #[inline(always)]
852 pub const fn nan_string(mut self, nan_string: Option<&'static [u8]>) -> Self {
853 self.nan_string = nan_string;
854 self
855 }
856
857 /// Set the string representation for `Infinity`.
858 ///
859 /// The first character must start with `I` or `i` and all characters must
860 /// be valid ASCII letters (`A-Z` or `a-z`). If set to `None`, then writing
861 /// [`Infinity`][f64::INFINITY] returns an error. Defaults to `inf`.
862 ///
863 /// # Examples
864 ///
865 /// ```rust
866 /// use lexical_write_float::Options;
867 ///
868 /// let builder = Options::builder()
869 /// .inf_string(Some(b"infinity"));
870 /// assert_eq!(builder.get_inf_string(), Some(b"infinity".as_ref()));
871 /// ```
872 ///
873 /// Panics
874 ///
875 /// Setting a value with more than 50 elements will panic at runtime. You
876 /// should always build the format using [`build_strict`] or checking
877 /// [`is_valid`] prior to using the format, to avoid unexpected panics.
878 ///
879 /// [`FORMATTED_SIZE`]: `lexical_util::constants::FormattedSize::FORMATTED_SIZE`
880 /// [`build_strict`]: Self::build_strict
881 /// [`is_valid`]: Self::is_valid
882 #[inline(always)]
883 pub const fn inf_string(mut self, inf_string: Option<&'static [u8]>) -> Self {
884 self.inf_string = inf_string;
885 self
886 }
887
888 /// Set the string representation for `Infinity`. Alias for [`inf_string`].
889 ///
890 /// The first character must start with `I` or `i` and all characters must
891 /// be valid ASCII letters (`A-Z` or `a-z`). If set to `None`, then writing
892 /// [`Infinity`][f64::INFINITY] returns an error. Defaults to `inf`.
893 ///
894 /// [`inf_string`]: Self::inf_string
895 ///
896 /// # Examples
897 ///
898 /// ```rust
899 /// use lexical_write_float::Options;
900 ///
901 /// let builder = Options::builder()
902 /// .infinity_string(Some(b"infinity"));
903 /// assert_eq!(builder.get_infinity_string(), Some(b"infinity".as_ref()));
904 /// ```
905 ///
906 /// Panics
907 ///
908 /// Setting a value with more than 50 elements will panic at runtime. You
909 /// should always build the format using [`build_strict`] or checking
910 /// [`is_valid`] prior to using the format, to avoid unexpected panics.
911 ///
912 /// [`FORMATTED_SIZE`]: `lexical_util::constants::FormattedSize::FORMATTED_SIZE`
913 /// [`build_strict`]: Self::build_strict
914 /// [`is_valid`]: Self::is_valid
915 #[inline(always)]
916 pub const fn infinity_string(self, inf_string: Option<&'static [u8]>) -> Self {
917 self.inf_string(inf_string)
918 }
919
920 // BUILDERS
921
922 /// Determine if [`nan_string`][`Self::nan_string`] is valid.
923 #[doc(hidden)]
924 #[inline(always)]
925 #[allow(clippy::if_same_then_else, clippy::needless_bool)] // reason="more logical"
926 pub const fn nan_str_is_valid(&self) -> bool {
927 if self.nan_string.is_none() {
928 return true;
929 }
930
931 let nan = unwrap_str(self.nan_string);
932 let length = nan.len();
933 if length == 0 || length > MAX_SPECIAL_STRING_LENGTH {
934 false
935 } else if !matches!(nan[0], b'N' | b'n') {
936 false
937 } else if !is_valid_letter_slice(nan) {
938 false
939 } else {
940 true
941 }
942 }
943
944 /// Determine if [`inf_string`][`Self::inf_string`] is valid.
945 #[doc(hidden)]
946 #[inline(always)]
947 #[allow(clippy::if_same_then_else, clippy::needless_bool)] // reason="more logical"
948 pub const fn inf_str_is_valid(&self) -> bool {
949 if self.inf_string.is_none() {
950 return true;
951 }
952
953 let inf = unwrap_str(self.inf_string);
954 let length = inf.len();
955 if length == 0 || length > MAX_SPECIAL_STRING_LENGTH {
956 false
957 } else if !matches!(inf[0], b'I' | b'i') {
958 false
959 } else if !is_valid_letter_slice(inf) {
960 false
961 } else {
962 true
963 }
964 }
965
966 /// Check if the builder state is valid.
967 #[inline(always)]
968 #[allow(clippy::if_same_then_else, clippy::needless_bool)] // reason="more logical"
969 pub const fn is_valid(&self) -> bool {
970 if !is_valid_ascii(self.exponent) {
971 false
972 } else if !is_valid_ascii(self.decimal_point) {
973 false
974 } else if !self.nan_str_is_valid() {
975 false
976 } else if !self.inf_str_is_valid() {
977 false
978 } else {
979 true
980 }
981 }
982
983 /// Build the [`Options`] struct without validation.
984 ///
985 /// <div class="warning">
986 ///
987 /// This is completely safe, however, misusing this, especially
988 /// the [`nan_string`] and [`inf_string`] representations could cause
989 /// panics at runtime. Always use [`is_valid`] prior to using the built
990 /// options.
991 ///
992 /// </div>
993 ///
994 /// [`inf_string`]: Self::inf_string
995 /// [`nan_string`]: Self::nan_string
996 /// [`is_valid`]: Self::is_valid
997 #[inline(always)]
998 pub const fn build_unchecked(&self) -> Options {
999 Options {
1000 max_significant_digits: self.max_significant_digits,
1001 min_significant_digits: self.min_significant_digits,
1002 positive_exponent_break: self.positive_exponent_break,
1003 negative_exponent_break: self.negative_exponent_break,
1004 round_mode: self.round_mode,
1005 trim_floats: self.trim_floats,
1006 exponent: self.exponent,
1007 decimal_point: self.decimal_point,
1008 nan_string: self.nan_string,
1009 inf_string: self.inf_string,
1010 }
1011 }
1012
1013 /// Build the [`Options`] struct, panicking if the builder is invalid.
1014 ///
1015 /// # Panics
1016 ///
1017 /// If the built options are not valid. This should always
1018 /// be used within a const context to avoid panics at runtime.
1019 #[inline(always)]
1020 pub const fn build_strict(&self) -> Options {
1021 match self.build() {
1022 Ok(value) => value,
1023 Err(error) => core::panic!("{}", error.description()),
1024 }
1025 }
1026
1027 /// Build the [`Options`] struct.
1028 ///
1029 /// If the format is not valid, than an error is returned,
1030 /// otherwise, the successful value is returned.
1031 #[inline(always)]
1032 #[allow(clippy::if_same_then_else)] // reason="more logical"
1033 pub const fn build(&self) -> Result<Options> {
1034 if self.nan_string.is_some() {
1035 let nan = unwrap_str(self.nan_string);
1036 if nan.is_empty() || !matches!(nan[0], b'N' | b'n') {
1037 return Err(Error::InvalidNanString);
1038 } else if !is_valid_letter_slice(nan) {
1039 return Err(Error::InvalidNanString);
1040 } else if nan.len() > MAX_SPECIAL_STRING_LENGTH {
1041 return Err(Error::NanStringTooLong);
1042 }
1043 }
1044
1045 if self.inf_string.is_some() {
1046 let inf = unwrap_str(self.inf_string);
1047 if inf.is_empty() || !matches!(inf[0], b'I' | b'i') {
1048 return Err(Error::InvalidInfString);
1049 } else if !is_valid_letter_slice(inf) {
1050 return Err(Error::InvalidInfString);
1051 } else if inf.len() > MAX_SPECIAL_STRING_LENGTH {
1052 return Err(Error::InfStringTooLong);
1053 }
1054 }
1055
1056 let min_digits = unwrap_or_zero_usize(self.min_significant_digits);
1057 let max_digits = unwrap_or_max_usize(self.max_significant_digits);
1058 if max_digits < min_digits {
1059 Err(Error::InvalidFloatPrecision)
1060 } else if unwrap_or_zero_i32(self.negative_exponent_break) > 0 {
1061 Err(Error::InvalidNegativeExponentBreak)
1062 } else if unwrap_or_zero_i32(self.positive_exponent_break) < 0 {
1063 Err(Error::InvalidPositiveExponentBreak)
1064 } else if !is_valid_ascii(self.exponent) {
1065 Err(Error::InvalidExponentSymbol)
1066 } else if !is_valid_ascii(self.decimal_point) {
1067 Err(Error::InvalidDecimalPoint)
1068 } else {
1069 Ok(self.build_unchecked())
1070 }
1071 }
1072}
1073
1074impl Default for OptionsBuilder {
1075 #[inline(always)]
1076 fn default() -> Self {
1077 Self::new()
1078 }
1079}
1080
1081/// Options to customize writing floats.
1082///
1083/// This enables extensive control over how the float is written, from
1084/// control characters like the decimal point, to the use of exponent
1085/// notation, and the number of significant digits.
1086///
1087/// # Examples
1088///
1089/// Writing a simple float with custom special strings and
1090/// formatting integral floats as integers can be done as:
1091///
1092/// ```rust
1093/// use core::str;
1094///
1095/// use lexical_write_float::{Options, ToLexical, ToLexicalWithOptions};
1096/// use lexical_write_float::format::STANDARD;
1097///
1098/// const OPTS: Options = Options::builder()
1099/// .trim_floats(true)
1100/// .nan_string(Some(b"NaN"))
1101/// .inf_string(Some(b"Inf"))
1102/// .build_strict();
1103///
1104/// const SIZE: usize = OPTS.buffer_size_const::<f64, STANDARD>();
1105/// let mut buffer = [0u8; SIZE];
1106///
1107/// // trim floats
1108/// let digits = 12345.0f64.to_lexical_with_options::<STANDARD>(&mut buffer, &OPTS);
1109/// assert_eq!(str::from_utf8(digits), Ok("12345"));
1110///
1111/// // don't trim floats
1112/// let digits = 12345.0f64.to_lexical(&mut buffer);
1113/// assert_eq!(str::from_utf8(digits), Ok("12345.0"));
1114/// ```
1115#[derive(Debug, Clone, PartialEq, Eq)]
1116pub struct Options {
1117 /// Maximum number of significant digits to write.
1118 /// If not set, it defaults to the algorithm's default.
1119 max_significant_digits: OptionUsize,
1120
1121 /// Minimum number of significant digits to write.
1122 /// If not set, it defaults to the algorithm's default.
1123 min_significant_digits: OptionUsize,
1124
1125 /// Maximum exponent prior to using scientific notation.
1126 /// This is ignored if the exponent base is not the same as the mantissa
1127 /// radix. If not provided, use the algorithm's default.
1128 positive_exponent_break: OptionI32,
1129
1130 /// Minimum exponent prior to using scientific notation.
1131 /// This is ignored if the exponent base is not the same as the mantissa
1132 /// radix. If not provided, use the algorithm's default.
1133 negative_exponent_break: OptionI32,
1134
1135 /// Rounding mode for writing digits with precision control.
1136 round_mode: RoundMode,
1137
1138 /// Trim the trailing ".0" from integral float strings.
1139 ///
1140 /// If used in conjunction with [`min_significant_digits`],
1141 /// this will still trim all the significant digits if an integral
1142 /// value is provided.
1143 ///
1144 /// [`min_significant_digits`]: Self::min_significant_digits
1145 trim_floats: bool,
1146
1147 /// Character to designate the exponent component of a float.
1148 exponent: u8,
1149
1150 /// Character to separate the integer from the fraction components.
1151 decimal_point: u8,
1152
1153 /// String representation of Not A Number, aka `NaN`.
1154 nan_string: Option<&'static [u8]>,
1155
1156 /// String representation of `Infinity`.
1157 inf_string: Option<&'static [u8]>,
1158}
1159
1160impl Options {
1161 // CONSTRUCTORS
1162
1163 /// Create options with default values.
1164 #[inline(always)]
1165 pub const fn new() -> Self {
1166 Self::builder().build_unchecked()
1167 }
1168
1169 /// Create the default options for a given radix.
1170 ///
1171 /// <div class="warning">
1172 ///
1173 /// This function will never fail even if the radix is invalid. It is up to
1174 /// the caller to ensure the format is valid using
1175 /// [`Options::is_valid`]. Only radixes from `2` to `36` should be used.
1176 ///
1177 /// </div>
1178 #[inline(always)]
1179 #[cfg(feature = "power-of-two")]
1180 // FIXME: When we release a major version, validate the radix.
1181 pub const fn from_radix(radix: u8) -> Self {
1182 // Need to determine the correct exponent character ('e' or '^'),
1183 // since the default character is `e` normally, but this is a valid
1184 // digit for radix >= 15.
1185 let mut builder = Self::builder();
1186 if radix >= 15 {
1187 builder = builder.exponent(b'^');
1188 }
1189 builder.build_unchecked()
1190 }
1191
1192 /// Get an upper bound on the required buffer size.
1193 ///
1194 /// This is used when custom formatting options, such as significant
1195 /// digits specifiers or custom exponent breaks, are used, which
1196 /// can lead to more or less significant digits being written than
1197 /// expected. If using the default formatting options, then this will
1198 /// always be [`FORMATTED_SIZE`][FormattedSize::FORMATTED_SIZE] or
1199 /// [`FORMATTED_SIZE_DECIMAL`][FormattedSize::FORMATTED_SIZE_DECIMAL],
1200 /// depending on the radix.
1201 ///
1202 /// # Examples
1203 ///
1204 /// ```rust
1205 /// # #[cfg(all(feature = "format", feature = "radix"))] {
1206 /// use core::{num, str};
1207 ///
1208 /// use lexical_write_float::{FormattedSize, Options, ToLexicalWithOptions};
1209 /// use lexical_write_float::format::STANDARD;
1210 ///
1211 /// const DEFAULT: Options = Options::builder()
1212 /// // require at least 3 significant digits, so `0.01` would be `"0.0100"`.
1213 /// .min_significant_digits(num::NonZeroUsize::new(3))
1214 /// // allow at most 5 significant digits, so `1.23456` would be `"1.2346"`.
1215 /// .max_significant_digits(num::NonZeroUsize::new(5))
1216 /// // build our format, erroring if it's invalid
1217 /// .build_strict();
1218 /// assert_eq!(DEFAULT.buffer_size_const::<f64, STANDARD>(), f64::FORMATTED_SIZE_DECIMAL);
1219 ///
1220 /// const CUSTOM: Options = Options::builder()
1221 /// // require at least 300 significant digits.
1222 /// .min_significant_digits(num::NonZeroUsize::new(300))
1223 /// // allow at most 500 significant digits.
1224 /// .max_significant_digits(num::NonZeroUsize::new(500))
1225 /// // only write values with magnitude above 1e300 in exponent notation
1226 /// .positive_exponent_break(num::NonZeroI32::new(300))
1227 /// // only write values with magnitude below 1e-300 in exponent notation
1228 /// .negative_exponent_break(num::NonZeroI32::new(-300))
1229 /// .build_strict();
1230 /// // 300 for the significant digits (500 is never reachable), 300 extra
1231 /// // due to the exponent breakoff, 1 for the sign, 1 for the decimal point
1232 /// // in all cases, this is enough including the exponent character and sign.
1233 /// assert_eq!(CUSTOM.buffer_size_const::<f64, STANDARD>(), 602);
1234 ///
1235 /// // now, write out value to bytes
1236 /// const SIZE: usize = CUSTOM.buffer_size_const::<f64, STANDARD>();
1237 /// let mut buffer = [0u8; SIZE];
1238 /// let value = 1.23456e-299f64;
1239 /// let digits = value.to_lexical_with_options::<STANDARD>(&mut buffer, &CUSTOM);
1240 ///
1241 /// // validate our printed digits. 600!
1242 /// assert_eq!(digits.len(), 600);
1243 /// assert!(!digits.contains(&b'e') && !digits.contains(&b'E'));
1244 /// assert!(digits.starts_with(b"0.000000000000000000000000"));
1245 ///
1246 /// // validate the round-trip
1247 /// assert_eq!(str::from_utf8(digits).unwrap().parse::<f64>(), Ok(value));
1248 ///
1249 /// // let's serialize a slightly smaller value
1250 /// let value = 1.23456e-301f64;
1251 /// let digits = value.to_lexical_with_options::<STANDARD>(&mut buffer, &CUSTOM);
1252 /// assert_eq!(digits.len(), 306);
1253 /// let digits = value.to_lexical_with_options::<STANDARD>(&mut buffer, &CUSTOM);
1254 /// # }
1255 /// ```
1256 #[inline(always)]
1257 pub const fn buffer_size_const<T: FormattedSize, const FORMAT: u128>(&self) -> usize {
1258 let format = NumberFormat::<{ FORMAT }> {};
1259
1260 // NOTE: This looks like it's off by 2 but it's not. We have only 2 as a
1261 // baseline for the mantissa sign and decimal point, but we don't
1262 // hard-code in 2 for the exponent sign and character. But we consider
1263 // those cases already when the exponent breakof >= 5 (13 for radix).
1264 // Say we have `1.2345612345612346e-300` for a breakoff of `-300` with
1265 // 300 min significant digits, which would be:
1266 // - "0." (integral + decimal point)
1267 // - "0" * 299 (leading zeros for e-300)
1268 // - "123456" * 50 (300 significant digits)
1269 //
1270 // This is exactly 601 characters, with which a sign bit is 602.
1271 // If we go any lower, we have `1.2e-301`, which then would become
1272 // `1.23456...e-301`, or would be 306 characters.
1273
1274 // quick optimizations if no custom formatting options are used
1275 // we ensure that the mantissa and exponent radix are the same.
1276 let formatted_size = if format.radix() == 10 {
1277 T::FORMATTED_SIZE_DECIMAL
1278 } else {
1279 T::FORMATTED_SIZE
1280 };
1281
1282 // At least 2 for the decimal point and sign.
1283 let mut count: usize = 2;
1284
1285 // First need to calculate maximum number of digits from leading or
1286 // trailing zeros, IE, the exponent break.
1287 if !format.no_exponent_notation() {
1288 let min_exp = match self.negative_exponent_break() {
1289 Some(v) => v.get(),
1290 None => -5,
1291 };
1292 let max_exp = match self.positive_exponent_break() {
1293 Some(v) => v.get(),
1294 None => 9,
1295 };
1296 let exp = max!(min_exp.abs(), max_exp) as usize;
1297 if cfg!(feature = "power-of-two") && exp < 13 {
1298 // 11 for the exponent digits in binary, 1 for the sign, 1 for the symbol
1299 count += 13;
1300 } else if exp < 5 {
1301 // 3 for the exponent digits in decimal, 1 for the sign, 1 for the symbol
1302 count += 5;
1303 } else {
1304 // More leading or trailing zeros than the exponent digits.
1305 count += exp;
1306 }
1307 } else if cfg!(feature = "power-of-two") {
1308 // Min is 2^-1075.
1309 count += 1075;
1310 } else {
1311 // Min is 10^-324.
1312 count += 324;
1313 }
1314
1315 // Now add the number of significant digits.
1316 let radix = format.radix();
1317 let formatted_digits = if radix == 10 {
1318 // Really should be 18, but add some extra to be cautious.
1319 28
1320 } else {
1321 // BINARY:
1322 // 53 significant mantissa bits for binary, add a few extra.
1323 // RADIX:
1324 // Our limit is `delta`. The maximum relative delta is 2.22e-16,
1325 // around 1. If we have values below 1, our delta is smaller, but
1326 // the max fraction is also a lot smaller. Above, and our fraction
1327 // must be < 1.0, so our delta is less significant. Therefore,
1328 // if our fraction is just less than 1, for a float near 2.0,
1329 // we can do at **maximum** 33 digits (for base 3). Let's just
1330 // assume it's a lot higher, and go with 64.
1331 64
1332 };
1333 let digits = if let Some(max_digits) = self.max_significant_digits() {
1334 min!(formatted_digits, max_digits.get())
1335 } else {
1336 formatted_digits
1337 };
1338 let digits = if let Some(min_digits) = self.min_significant_digits() {
1339 max!(digits, min_digits.get())
1340 } else {
1341 digits
1342 };
1343 count += digits;
1344
1345 // we need to make sure we have at least enough room for the
1346 // default formatting size, no matter what, just as a precaution.
1347 count = max!(count, formatted_size);
1348
1349 count
1350 }
1351
1352 // GETTERS
1353
1354 /// Check if the options state is valid.
1355 #[inline(always)]
1356 pub const fn is_valid(&self) -> bool {
1357 self.rebuild().is_valid()
1358 }
1359
1360 /// Get the maximum number of significant digits to write.
1361 ///
1362 /// This limits the total number of written digits, truncating based
1363 /// on the [`round_mode`] if more digits would normally be written. If
1364 /// no value is provided, then it writes as many digits as required to
1365 /// create an unambiguous representation of the float.
1366 ///
1367 /// # Examples
1368 ///
1369 /// ```rust
1370 /// use core::num::NonZeroUsize;
1371 ///
1372 /// use lexical_write_float::Options;
1373 ///
1374 /// const MAX_DIGITS: Option<NonZeroUsize> = NonZeroUsize::new(300);
1375 /// const OPTIONS: Options = Options::builder()
1376 /// .max_significant_digits(MAX_DIGITS)
1377 /// .build_strict();
1378 /// assert_eq!(OPTIONS.max_significant_digits(), MAX_DIGITS);
1379 /// ```
1380 ///
1381 /// [`round_mode`]: Self::round_mode
1382 #[inline(always)]
1383 pub const fn max_significant_digits(&self) -> OptionUsize {
1384 self.max_significant_digits
1385 }
1386
1387 /// Get the minimum number of significant digits to write.
1388 ///
1389 /// If more digits exist, such as writing "1.2" with a minimum of 5
1390 /// significant digits, then `0`s are appended to the end of the digits.
1391 /// If no value is provided, then it writes as few digits as required to
1392 /// create an unambiguous representation of the float.
1393 ///
1394 /// # Examples
1395 ///
1396 /// ```rust
1397 /// use core::num::NonZeroUsize;
1398 ///
1399 /// use lexical_write_float::Options;
1400 ///
1401 /// const MIN_DIGITS: Option<NonZeroUsize> = NonZeroUsize::new(10);
1402 /// const OPTIONS: Options = Options::builder()
1403 /// .min_significant_digits(MIN_DIGITS)
1404 /// .build_strict();
1405 /// assert_eq!(OPTIONS.min_significant_digits(), MIN_DIGITS);
1406 /// ```
1407 #[inline(always)]
1408 pub const fn min_significant_digits(&self) -> OptionUsize {
1409 self.min_significant_digits
1410 }
1411
1412 /// Get the maximum exponent prior to using scientific notation.
1413 ///
1414 /// If the value is set to `300`, then any value with magnitude `>= 1e300`
1415 /// (for base 10) will be writen in exponent notation, while any lower
1416 /// value will be written in decimal form. If no value is provided, for
1417 /// decimal floats, this defaults to `9`.
1418 ///
1419 /// # Examples
1420 ///
1421 /// ```rust
1422 /// use core::num::NonZeroI32;
1423 ///
1424 /// use lexical_write_float::Options;
1425 ///
1426 /// const POS_BREAK: Option<NonZeroI32> = NonZeroI32::new(3);
1427 /// const OPTIONS: Options = Options::builder()
1428 /// .positive_exponent_break(POS_BREAK)
1429 /// .build_strict();
1430 /// assert_eq!(OPTIONS.positive_exponent_break(), POS_BREAK);
1431 /// ```
1432 #[inline(always)]
1433 pub const fn positive_exponent_break(&self) -> OptionI32 {
1434 self.positive_exponent_break
1435 }
1436
1437 /// Get the minimum exponent prior to using scientific notation.
1438 ///
1439 /// If the value is set to `-300`, then any value with magnitude `< 1e-300`
1440 /// (for base 10) will be writen in exponent notation, while any larger
1441 /// value will be written in decimal form. If no value is provided, for
1442 /// decimal floats, this defaults to `-5`.
1443 ///
1444 /// # Examples
1445 ///
1446 /// ```rust
1447 /// use core::num::NonZeroI32;
1448 ///
1449 /// use lexical_write_float::Options;
1450 ///
1451 /// const NEG_BREAK: Option<NonZeroI32> = NonZeroI32::new(-3);
1452 /// const OPTIONS: Options = Options::builder()
1453 /// .negative_exponent_break(NEG_BREAK)
1454 /// .build_strict();
1455 /// assert_eq!(OPTIONS.negative_exponent_break(), NEG_BREAK);
1456 /// ```
1457 #[inline(always)]
1458 pub const fn negative_exponent_break(&self) -> OptionI32 {
1459 self.negative_exponent_break
1460 }
1461
1462 /// Get the rounding mode for writing digits with precision control.
1463 ///
1464 /// For example, writing `1.23456` with 5 significant digits with
1465 /// [`RoundMode::Round`] would produce `"1.2346"` while
1466 /// [`RoundMode::Truncate`] would produce `"1.2345"`. Defaults to
1467 /// [`RoundMode::Round`].
1468 ///
1469 /// # Examples
1470 ///
1471 /// ```rust
1472 /// use lexical_write_float::{Options, RoundMode};
1473 ///
1474 /// const OPTIONS: Options = Options::builder()
1475 /// .round_mode(RoundMode::Truncate)
1476 /// .build_strict();
1477 /// assert_eq!(OPTIONS.round_mode(), RoundMode::Truncate);
1478 /// ```
1479 #[inline(always)]
1480 pub const fn round_mode(&self) -> RoundMode {
1481 self.round_mode
1482 }
1483
1484 /// Get if we should trim a trailing `".0"` from integral floats.
1485 ///
1486 /// If used in conjunction with [`min_significant_digits`],
1487 /// this will still trim all the significant digits if an integral
1488 /// value is provided. Defaults to [`false`].
1489 ///
1490 /// # Examples
1491 ///
1492 /// ```rust
1493 /// use lexical_write_float::Options;
1494 ///
1495 /// const OPTIONS: Options = Options::builder()
1496 /// .trim_floats(true)
1497 /// .build_strict();
1498 /// assert_eq!(OPTIONS.trim_floats(), true);
1499 /// ```
1500 ///
1501 /// [`min_significant_digits`]: Self::min_significant_digits
1502 #[inline(always)]
1503 pub const fn trim_floats(&self) -> bool {
1504 self.trim_floats
1505 }
1506
1507 /// Get the character to designate the exponent component of a float.
1508 ///
1509 /// Any non-control character is valid, but `\t` to `\r` are also valid.
1510 /// The full range is `[0x09, 0x0D]` and `[0x20, 0x7F]`. Defaults to `e`.
1511 ///
1512 /// # Examples
1513 ///
1514 /// ```rust
1515 /// use lexical_write_float::Options;
1516 ///
1517 /// const OPTIONS: Options = Options::builder()
1518 /// .exponent(b'^')
1519 /// .build_strict();
1520 /// assert_eq!(OPTIONS.exponent(), b'^');
1521 /// ```
1522 #[inline(always)]
1523 pub const fn exponent(&self) -> u8 {
1524 self.exponent
1525 }
1526
1527 /// Get the character to separate the integer from the fraction components.
1528 ///
1529 /// Any non-control character is valid, but `\t` to `\r` are also valid.
1530 /// The full range is `[0x09, 0x0D]` and `[0x20, 0x7F]`. Defaults to `.`.
1531 ///
1532 /// # Examples
1533 ///
1534 /// ```rust
1535 /// use lexical_write_float::Options;
1536 ///
1537 /// const OPTIONS: Options = Options::builder()
1538 /// .exponent(b',')
1539 /// .build_strict();
1540 /// assert_eq!(OPTIONS.exponent(), b',');
1541 /// ```
1542 #[inline(always)]
1543 pub const fn decimal_point(&self) -> u8 {
1544 self.decimal_point
1545 }
1546
1547 /// Get the string representation for `NaN`.
1548 ///
1549 /// The first character must start with `N` or `n` and all characters must
1550 /// be valid ASCII letters (`A-Z` or `a-z`). If set to `None`, then writing
1551 /// [`NaN`][f64::NAN] returns an error. Defaults to `NaN`.
1552 ///
1553 /// # Examples
1554 ///
1555 /// ```rust
1556 /// use lexical_write_float::Options;
1557 ///
1558 /// const OPTIONS: Options = Options::builder()
1559 /// .nan_string(Some(b"nan"))
1560 /// .build_strict();
1561 /// assert_eq!(OPTIONS.nan_string(), Some(b"nan".as_ref()));
1562 /// ```
1563 #[inline(always)]
1564 pub const fn nan_string(&self) -> Option<&'static [u8]> {
1565 self.nan_string
1566 }
1567
1568 /// Get the string representation for `Infinity`.
1569 ///
1570 /// The first character must start with `I` or `i` and all characters must
1571 /// be valid ASCII letters (`A-Z` or `a-z`). If set to `None`, then writing
1572 /// [`Infinity`][f64::INFINITY] returns an error. Defaults to `inf`.
1573 ///
1574 /// # Examples
1575 ///
1576 /// ```rust
1577 /// use lexical_write_float::Options;
1578 ///
1579 /// const OPTIONS: Options = Options::builder()
1580 /// .inf_string(Some(b"infinity"))
1581 /// .build_strict();
1582 /// assert_eq!(OPTIONS.inf_string(), Some(b"infinity".as_ref()));
1583 /// ```
1584 #[inline(always)]
1585 pub const fn inf_string(&self) -> Option<&'static [u8]> {
1586 self.inf_string
1587 }
1588
1589 /// Get the string representation for `Infinity`. Alias for [`inf_string`].
1590 ///
1591 /// The first character must start with `I` or `i` and all characters must
1592 /// be valid ASCII letters (`A-Z` or `a-z`). If set to `None`, then writing
1593 /// [`Infinity`][f64::INFINITY] returns an error. Defaults to `inf`.
1594 ///
1595 /// [`inf_string`]: Self::inf_string
1596 ///
1597 /// # Examples
1598 ///
1599 /// ```rust
1600 /// use lexical_write_float::Options;
1601 ///
1602 /// const OPTIONS: Options = Options::builder()
1603 /// .infinity_string(Some(b"infinity"))
1604 /// .build_strict();
1605 /// assert_eq!(OPTIONS.infinity_string(), Some(b"infinity".as_ref()));
1606 /// ```
1607 #[inline(always)]
1608 pub const fn infinity_string(&self) -> Option<&'static [u8]> {
1609 self.inf_string
1610 }
1611
1612 // SETTERS
1613
1614 /// Set the maximum number of significant digits to write.
1615 ///
1616 /// This limits the total number of written digits, truncating based
1617 /// on the [`round_mode`] if more digits would normally be written.
1618 ///
1619 /// # Panics
1620 ///
1621 /// This will panic when writing the float if the value is smaller than
1622 /// [`min_significant_digits`].
1623 ///
1624 /// [`round_mode`]: Self::round_mode
1625 /// [`min_significant_digits`]: Self::min_significant_digits
1626 #[deprecated = "Options should be treated as immutable, use `OptionsBuilder` instead. Will be removed in 2.0."]
1627 #[inline(always)]
1628 pub fn set_max_significant_digits(&mut self, max_significant_digits: OptionUsize) {
1629 self.max_significant_digits = max_significant_digits;
1630 }
1631
1632 /// Set the minimum number of significant digits to write.
1633 ///
1634 /// If more digits exist, such as writing "1.2" with a minimum of 5
1635 /// significant digits, then `0`s are appended to the end of the digits.
1636 ///
1637 /// # Panics
1638 ///
1639 /// This will panic when writing the float if the value is larger than
1640 /// [`max_significant_digits`].
1641 ///
1642 /// [`max_significant_digits`]: Self::max_significant_digits
1643 #[inline(always)]
1644 #[deprecated = "Options should be treated as immutable, use `OptionsBuilder` instead. Will be removed in 2.0."]
1645 pub fn set_min_significant_digits(&mut self, min_significant_digits: OptionUsize) {
1646 self.min_significant_digits = min_significant_digits;
1647 }
1648
1649 /// Set the maximum exponent prior to using scientific notation.
1650 ///
1651 /// If the value is set to `300`, then any value with magnitude `>= 1e300`
1652 /// (for base 10) will be writen in exponent notation, while any lower
1653 /// value will be written in decimal form.
1654 #[inline(always)]
1655 #[deprecated = "Options should be treated as immutable, use `OptionsBuilder` instead. Will be removed in 2.0."]
1656 pub fn set_positive_exponent_break(&mut self, positive_exponent_break: OptionI32) {
1657 self.positive_exponent_break = positive_exponent_break;
1658 }
1659
1660 /// Set the minimum exponent prior to using scientific notation.
1661 ///
1662 /// If the value is set to `-300`, then any value with magnitude `< 1e-300`
1663 /// (for base 10) will be writen in exponent notation, while any larger
1664 /// value will be written in decimal form.
1665 #[inline(always)]
1666 #[deprecated = "Options should be treated as immutable, use `OptionsBuilder` instead. Will be removed in 2.0."]
1667 pub fn set_negative_exponent_break(&mut self, negative_exponent_break: OptionI32) {
1668 self.negative_exponent_break = negative_exponent_break;
1669 }
1670
1671 /// Set the rounding mode for writing digits with precision control.
1672 ///
1673 /// For example, writing `1.23456` with 5 significant digits with
1674 /// [`RoundMode::Round`] would produce `"1.2346"` while
1675 /// [`RoundMode::Truncate`] would produce `"1.2345"`.
1676 #[inline(always)]
1677 #[deprecated = "Options should be treated as immutable, use `OptionsBuilder` instead. Will be removed in 2.0."]
1678 pub fn set_round_mode(&mut self, round_mode: RoundMode) {
1679 self.round_mode = round_mode;
1680 }
1681
1682 /// Set if we should trim a trailing `".0"` from integral floats.
1683 ///
1684 /// If used in conjunction with [`min_significant_digits`],
1685 /// this will still trim all the significant digits if an integral
1686 /// value is provided.
1687 ///
1688 /// [`min_significant_digits`]: Self::min_significant_digits
1689 #[inline(always)]
1690 #[deprecated = "Options should be treated as immutable, use `OptionsBuilder` instead. Will be removed in 2.0."]
1691 pub fn set_trim_floats(&mut self, trim_floats: bool) {
1692 self.trim_floats = trim_floats;
1693 }
1694
1695 /// Set the character to designate the exponent component of a float.
1696 ///
1697 /// # Safety
1698 ///
1699 /// Always safe, but may produce invalid output if the exponent
1700 /// is not a valid ASCII character.
1701 #[inline(always)]
1702 #[deprecated = "Options should be treated as immutable, use `OptionsBuilder` instead. Will be removed in 2.0."]
1703 pub fn set_exponent(&mut self, exponent: u8) {
1704 self.exponent = exponent;
1705 }
1706
1707 /// Set the character to separate the integer from the fraction components.
1708 ///
1709 /// # Safety
1710 ///
1711 /// Always safe, but may produce invalid output if the decimal point
1712 /// is not a valid ASCII character.
1713 #[inline(always)]
1714 #[deprecated = "Options should be treated as immutable, use `OptionsBuilder` instead. Will be removed in 2.0."]
1715 pub fn set_decimal_point(&mut self, decimal_point: u8) {
1716 self.decimal_point = decimal_point;
1717 }
1718
1719 /// Set the string representation for `NaN`.
1720 ///
1721 /// Panics
1722 ///
1723 /// Setting a value too large may cause a panic even if [`FORMATTED_SIZE`]
1724 /// elements are provided.
1725 ///
1726 /// [`FORMATTED_SIZE`]: `lexical_util::constants::FormattedSize::FORMATTED_SIZE`
1727 #[inline(always)]
1728 #[deprecated = "Options should be treated as immutable, use `OptionsBuilder` instead. Will be removed in 2.0."]
1729 pub fn set_nan_string(&mut self, nan_string: Option<&'static [u8]>) {
1730 self.nan_string = nan_string;
1731 }
1732
1733 /// Set the short string representation for `Infinity`
1734 ///
1735 /// Panics
1736 ///
1737 /// Setting a value too large may cause a panic even if [`FORMATTED_SIZE`]
1738 /// elements are provided.
1739 ///
1740 /// [`FORMATTED_SIZE`]: `lexical_util::constants::FormattedSize::FORMATTED_SIZE`
1741 #[inline(always)]
1742 #[deprecated = "Options should be treated as immutable, use `OptionsBuilder` instead. Will be removed in 2.0."]
1743 pub fn set_inf_string(&mut self, inf_string: Option<&'static [u8]>) {
1744 self.inf_string = inf_string;
1745 }
1746
1747 // BUILDERS
1748
1749 /// Get [`OptionsBuilder`] as a static function.
1750 #[inline(always)]
1751 pub const fn builder() -> OptionsBuilder {
1752 OptionsBuilder::new()
1753 }
1754
1755 /// Create [`OptionsBuilder`] using existing values.
1756 #[inline(always)]
1757 pub const fn rebuild(&self) -> OptionsBuilder {
1758 OptionsBuilder {
1759 max_significant_digits: self.max_significant_digits,
1760 min_significant_digits: self.min_significant_digits,
1761 positive_exponent_break: self.positive_exponent_break,
1762 negative_exponent_break: self.negative_exponent_break,
1763 round_mode: self.round_mode,
1764 trim_floats: self.trim_floats,
1765 exponent: self.exponent,
1766 decimal_point: self.decimal_point,
1767 nan_string: self.nan_string,
1768 inf_string: self.inf_string,
1769 }
1770 }
1771}
1772
1773impl Default for Options {
1774 #[inline(always)]
1775 fn default() -> Self {
1776 Self::new()
1777 }
1778}
1779
1780impl WriteOptions for Options {
1781 #[inline(always)]
1782 fn is_valid(&self) -> bool {
1783 Self::is_valid(self)
1784 }
1785
1786 #[doc = lexical_util::write_options_doc!()]
1787 #[inline(always)]
1788 fn buffer_size<T: FormattedSize, const FORMAT: u128>(&self) -> usize {
1789 self.buffer_size_const::<T, FORMAT>()
1790 }
1791}
1792
1793/// Define `unwrap_or_zero` for a custom type.
1794macro_rules! unwrap_or_zero {
1795 ($name:ident, $opt:ident, $t:ident) => {
1796 /// Unwrap `Option` as a const fn.
1797 #[inline(always)]
1798 const fn $name(option: $opt) -> $t {
1799 match option {
1800 Some(x) => x.get(),
1801 None => 0,
1802 }
1803 }
1804 };
1805}
1806
1807unwrap_or_zero!(unwrap_or_zero_usize, OptionUsize, usize);
1808unwrap_or_zero!(unwrap_or_zero_i32, OptionI32, i32);
1809
1810/// Unwrap `Option` as a const fn.
1811#[inline(always)]
1812const fn unwrap_or_max_usize(option: OptionUsize) -> usize {
1813 match option {
1814 Some(x) => x.get(),
1815 None => usize::MAX,
1816 }
1817}
1818
1819/// Unwrap `Option` as a const fn.
1820#[inline(always)]
1821const fn unwrap_str(option: Option<&'static [u8]>) -> &'static [u8] {
1822 match option {
1823 Some(x) => x,
1824 None => &[],
1825 }
1826}
1827
1828// PRE-DEFINED CONSTANTS
1829// ---------------------
1830
1831// Only constants that differ from the standard version are included.
1832
1833/// Standard number format.
1834#[rustfmt::skip]
1835pub const STANDARD: Options = Options::new();
1836
1837/// Numerical format with a decimal comma.
1838///
1839/// This is the standard numerical format for most of the world.
1840#[rustfmt::skip]
1841pub const DECIMAL_COMMA: Options = Options::builder()
1842 .decimal_point(b',')
1843 .build_strict();
1844
1845/// Numerical format for hexadecimal floats, which use a `p` exponent.
1846#[rustfmt::skip]
1847pub const HEX_FLOAT: Options = Options::builder()
1848 .exponent(b'p')
1849 .build_strict();
1850
1851/// Numerical format where `^` is used as the exponent notation character.
1852///
1853/// This isn't very common, but is useful when `e` or `p` are valid digits.
1854#[rustfmt::skip]
1855pub const CARAT_EXPONENT: Options = Options::builder()
1856 .exponent(b'^')
1857 .build_strict();
1858
1859/// Number format for a [`Rust`] literal floating-point number.
1860///
1861/// [`Rust`]: https://www.rust-lang.org/
1862#[rustfmt::skip]
1863pub const RUST_LITERAL: Options = Options::builder()
1864 .nan_string(options::RUST_LITERAL)
1865 .inf_string(options::RUST_LITERAL)
1866 .build_strict();
1867
1868/// Number format for a [`Python`] literal floating-point number.
1869///
1870/// [`Python`]: https://www.python.org/
1871#[rustfmt::skip]
1872pub const PYTHON_LITERAL: Options = Options::builder()
1873 .nan_string(options::PYTHON_LITERAL)
1874 .inf_string(options::PYTHON_LITERAL)
1875 .build_strict();
1876
1877/// Number format for a [`C++`] literal floating-point number.
1878///
1879/// [`C++`]: https://en.cppreference.com/w/
1880#[rustfmt::skip]
1881pub const CXX_LITERAL: Options = Options::builder()
1882 .nan_string(options::CXX_LITERAL_NAN)
1883 .inf_string(options::CXX_LITERAL_INF)
1884 .build_strict();
1885
1886/// Number format for a [`C`] literal floating-point number.
1887///
1888/// [`C`]: https://en.cppreference.com/w/c
1889#[rustfmt::skip]
1890pub const C_LITERAL: Options = Options::builder()
1891 .nan_string(options::C_LITERAL_NAN)
1892 .inf_string(options::C_LITERAL_INF)
1893 .build_strict();
1894
1895/// Number format for a [`Ruby`] literal floating-point number.
1896///
1897/// [`Ruby`]: https://www.ruby-lang.org/en/
1898#[rustfmt::skip]
1899pub const RUBY_LITERAL: Options = Options::builder()
1900 .positive_exponent_break(num::NonZeroI32::new(14))
1901 .negative_exponent_break(num::NonZeroI32::new(-4))
1902 .nan_string(options::RUBY_LITERAL_NAN)
1903 .inf_string(options::RUBY_LITERAL_INF)
1904 .build_strict();
1905
1906/// Number format to parse a [`Ruby`] float from string.
1907///
1908/// [`Ruby`]: https://www.ruby-lang.org/en/
1909#[rustfmt::skip]
1910pub const RUBY_STRING: Options = Options::builder()
1911 .nan_string(options::RUBY_LITERAL_NAN)
1912 .inf_string(options::RUBY_LITERAL_INF)
1913 .build_strict();
1914
1915/// Number format for a [`Swift`] literal floating-point number.
1916///
1917/// [`Swift`]: https://developer.apple.com/swift/
1918#[rustfmt::skip]
1919pub const SWIFT_LITERAL: Options = Options::builder()
1920 .nan_string(options::SWIFT_LITERAL)
1921 .inf_string(options::SWIFT_LITERAL)
1922 .build_strict();
1923
1924/// Number format for a [`Golang`] literal floating-point number.
1925///
1926/// [`Golang`]: https://go.dev/
1927#[rustfmt::skip]
1928pub const GO_LITERAL: Options = Options::builder()
1929 .nan_string(options::GO_LITERAL)
1930 .inf_string(options::GO_LITERAL)
1931 .build_strict();
1932
1933/// Number format for a [`Haskell`] literal floating-point number.
1934///
1935/// [`Haskell`]: https://www.haskell.org/
1936#[rustfmt::skip]
1937pub const HASKELL_LITERAL: Options = Options::builder()
1938 .nan_string(options::HASKELL_LITERAL)
1939 .inf_string(options::HASKELL_LITERAL)
1940 .build_strict();
1941
1942/// Number format to parse a [`Haskell`] float from string.
1943///
1944/// [`Haskell`]: https://www.haskell.org/
1945#[rustfmt::skip]
1946pub const HASKELL_STRING: Options = Options::builder()
1947 .inf_string(options::HASKELL_STRING_INF)
1948 .build_strict();
1949
1950/// Number format for a [`Javascript`] literal floating-point number.
1951///
1952/// [`Javascript`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript
1953#[rustfmt::skip]
1954pub const JAVASCRIPT_LITERAL: Options = Options::builder()
1955 .inf_string(options::JAVASCRIPT_INF)
1956 .build_strict();
1957
1958/// Number format to parse a [`Javascript`] float from string.
1959///
1960/// [`Javascript`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript
1961#[rustfmt::skip]
1962pub const JAVASCRIPT_STRING: Options = Options::builder()
1963 .inf_string(options::JAVASCRIPT_INF)
1964 .build_strict();
1965
1966/// Number format for a [`Perl`] literal floating-point number.
1967///
1968/// [`Perl`]: https://www.perl.org/
1969#[rustfmt::skip]
1970pub const PERL_LITERAL: Options = Options::builder()
1971 .nan_string(options::PERL_LITERAL)
1972 .inf_string(options::PERL_LITERAL)
1973 .build_strict();
1974
1975/// Number format for a [`PHP`] literal floating-point number.
1976///
1977/// [`PHP`]: https://www.php.net/
1978#[rustfmt::skip]
1979pub const PHP_LITERAL: Options = Options::builder()
1980 .nan_string(options::PHP_LITERAL_NAN)
1981 .inf_string(options::PHP_LITERAL_INF)
1982 .build_strict();
1983
1984/// Number format for a [`Java`] literal floating-point number.
1985///
1986/// [`Java`]: https://www.java.com/en/
1987#[rustfmt::skip]
1988pub const JAVA_LITERAL: Options = Options::builder()
1989 .nan_string(options::JAVA_LITERAL)
1990 .inf_string(options::JAVA_LITERAL)
1991 .build_strict();
1992
1993/// Number format to parse a [`Java`] float from string.
1994///
1995/// [`Java`]: https://www.java.com/en/
1996#[rustfmt::skip]
1997pub const JAVA_STRING: Options = Options::builder()
1998 .inf_string(options::JAVA_STRING_INF)
1999 .build_strict();
2000
2001/// Number format for an [`R`] literal floating-point number.
2002///
2003/// [`R`]: https://www.r-project.org/
2004#[rustfmt::skip]
2005pub const R_LITERAL: Options = Options::builder()
2006 .inf_string(options::R_LITERAL_INF)
2007 .build_strict();
2008
2009/// Number format for a [`Kotlin`] literal floating-point number.
2010///
2011/// [`Kotlin`]: https://kotlinlang.org/
2012#[rustfmt::skip]
2013pub const KOTLIN_LITERAL: Options = Options::builder()
2014 .nan_string(options::KOTLIN_LITERAL)
2015 .inf_string(options::KOTLIN_LITERAL)
2016 .build_strict();
2017
2018/// Number format to parse a [`Kotlin`] float from string.
2019///
2020/// [`Kotlin`]: https://kotlinlang.org/
2021#[rustfmt::skip]
2022pub const KOTLIN_STRING: Options = Options::builder()
2023 .inf_string(options::KOTLIN_STRING_INF)
2024 .build_strict();
2025
2026/// Number format for a [`Julia`] literal floating-point number.
2027///
2028/// [`Julia`]: https://julialang.org/
2029#[rustfmt::skip]
2030pub const JULIA_LITERAL: Options = Options::builder()
2031 .inf_string(options::JULIA_LITERAL_INF)
2032 .build_strict();
2033
2034/// Number format for a [`C#`] literal floating-point number.
2035///
2036/// [`C#`]: https://learn.microsoft.com/en-us/dotnet/csharp/
2037#[rustfmt::skip]
2038pub const CSHARP_LITERAL: Options = Options::builder()
2039 .nan_string(options::CSHARP_LITERAL)
2040 .inf_string(options::CSHARP_LITERAL)
2041 .build_strict();
2042
2043/// Number format to parse a [`C#`] float from string.
2044///
2045/// [`C#`]: https://learn.microsoft.com/en-us/dotnet/csharp/
2046#[rustfmt::skip]
2047pub const CSHARP_STRING: Options = Options::builder()
2048 .inf_string(options::CSHARP_STRING_INF)
2049 .build_strict();
2050
2051/// Number format for a [`Kawa`] literal floating-point number.
2052///
2053/// [`Kawa`]: https://www.gnu.org/software/kawa/
2054#[rustfmt::skip]
2055pub const KAWA_LITERAL: Options = Options::builder()
2056 .nan_string(options::KAWA)
2057 .inf_string(options::KAWA)
2058 .build_strict();
2059
2060/// Number format to parse a [`Kawa`] float from string.
2061///
2062/// [`Kawa`]: https://www.gnu.org/software/kawa/
2063#[rustfmt::skip]
2064pub const KAWA_STRING: Options = Options::builder()
2065 .nan_string(options::KAWA)
2066 .inf_string(options::KAWA)
2067 .build_strict();
2068
2069/// Number format for a [`Gambit-C`] literal floating-point number.
2070///
2071/// [`Gambit-C`]: https://gambitscheme.org/
2072#[rustfmt::skip]
2073pub const GAMBITC_LITERAL: Options = Options::builder()
2074 .nan_string(options::GAMBITC)
2075 .inf_string(options::GAMBITC)
2076 .build_strict();
2077
2078/// Number format to parse a [`Gambit-C`] float from string.
2079///
2080/// [`Gambit-C`]: https://gambitscheme.org/
2081#[rustfmt::skip]
2082pub const GAMBITC_STRING: Options = Options::builder()
2083 .nan_string(options::GAMBITC)
2084 .inf_string(options::GAMBITC)
2085 .build_strict();
2086
2087/// Number format for a [`Guile`] literal floating-point number.
2088///
2089/// [`Guile`]: https://www.gnu.org/software/guile/
2090#[rustfmt::skip]
2091pub const GUILE_LITERAL: Options = Options::builder()
2092 .nan_string(options::GUILE)
2093 .inf_string(options::GUILE)
2094 .build_strict();
2095
2096/// Number format to parse a [`Guile`] float from string.
2097///
2098/// [`Guile`]: https://www.gnu.org/software/guile/
2099#[rustfmt::skip]
2100pub const GUILE_STRING: Options = Options::builder()
2101 .nan_string(options::GUILE)
2102 .inf_string(options::GUILE)
2103 .build_strict();
2104
2105/// Number format for a [`Clojure`] literal floating-point number.
2106///
2107/// [`Clojure`]: https://clojure.org/
2108#[rustfmt::skip]
2109pub const CLOJURE_LITERAL: Options = Options::builder()
2110 .nan_string(options::CLOJURE_LITERAL)
2111 .inf_string(options::CLOJURE_LITERAL)
2112 .build_strict();
2113
2114/// Number format to parse a [`Clojure`] float from string.
2115///
2116/// [`Clojure`]: https://clojure.org/
2117#[rustfmt::skip]
2118pub const CLOJURE_STRING: Options = Options::builder()
2119 .inf_string(options::CLOJURE_STRING_INF)
2120 .build_strict();
2121
2122/// Number format for an [`Erlang`] literal floating-point number.
2123///
2124/// [`Erlang`]: https://www.erlang.org/
2125#[rustfmt::skip]
2126pub const ERLANG_LITERAL: Options = Options::builder()
2127 .nan_string(options::ERLANG_LITERAL_NAN)
2128 .build_strict();
2129
2130/// Number format to parse an [`Erlang`] float from string.
2131///
2132/// [`Erlang`]: https://www.erlang.org/
2133#[rustfmt::skip]
2134pub const ERLANG_STRING: Options = Options::builder()
2135 .nan_string(options::ERLANG_STRING)
2136 .inf_string(options::ERLANG_STRING)
2137 .build_strict();
2138
2139/// Number format for an [`Elm`] literal floating-point number.
2140///
2141/// [`Elm`]: https://elm-lang.org/
2142#[rustfmt::skip]
2143pub const ELM_LITERAL: Options = Options::builder()
2144 .nan_string(options::ELM_LITERAL)
2145 .inf_string(options::ELM_LITERAL)
2146 .build_strict();
2147
2148/// Number format to parse an [`Elm`] float from string.
2149///
2150/// [`Elm`]: https://elm-lang.org/
2151#[rustfmt::skip]
2152pub const ELM_STRING: Options = Options::builder()
2153 .nan_string(options::ELM_STRING_NAN)
2154 .inf_string(options::ELM_STRING_INF)
2155 .build_strict();
2156
2157/// Number format for a [`Scala`] literal floating-point number.
2158///
2159/// [`Scala`]: https://www.scala-lang.org/
2160#[rustfmt::skip]
2161pub const SCALA_LITERAL: Options = Options::builder()
2162 .nan_string(options::SCALA_LITERAL)
2163 .inf_string(options::SCALA_LITERAL)
2164 .build_strict();
2165
2166/// Number format to parse a [`Scala`] float from string.
2167///
2168/// [`Scala`]: https://www.scala-lang.org/
2169#[rustfmt::skip]
2170pub const SCALA_STRING: Options = Options::builder()
2171 .inf_string(options::SCALA_STRING_INF)
2172 .build_strict();
2173
2174/// Number format for an [`Elixir`] literal floating-point number.
2175///
2176/// [`Elixir`]: https://elixir-lang.org/
2177#[rustfmt::skip]
2178pub const ELIXIR_LITERAL: Options = Options::builder()
2179 .nan_string(options::ELIXIR)
2180 .inf_string(options::ELIXIR)
2181 .build_strict();
2182
2183/// Number format to parse an [`Elixir`] float from string.
2184///
2185/// [`Elixir`]: https://elixir-lang.org/
2186#[rustfmt::skip]
2187pub const ELIXIR_STRING: Options = Options::builder()
2188 .nan_string(options::ELIXIR)
2189 .inf_string(options::ELIXIR)
2190 .build_strict();
2191
2192/// Number format for a [`FORTRAN`] literal floating-point number.
2193///
2194/// [`FORTRAN`]: https://fortran-lang.org/
2195#[rustfmt::skip]
2196pub const FORTRAN_LITERAL: Options = Options::builder()
2197 .nan_string(options::FORTRAN_LITERAL)
2198 .inf_string(options::FORTRAN_LITERAL)
2199 .build_strict();
2200
2201/// Number format for a [`D`] literal floating-point number.
2202///
2203/// [`D`]: https://dlang.org/
2204#[rustfmt::skip]
2205pub const D_LITERAL: Options = Options::builder()
2206 .nan_string(options::D_LITERAL)
2207 .inf_string(options::D_LITERAL)
2208 .build_strict();
2209
2210/// Number format for a [`Coffeescript`] literal floating-point number.
2211///
2212/// [`Coffeescript`]: https://coffeescript.org/
2213#[rustfmt::skip]
2214pub const COFFEESCRIPT_LITERAL: Options = Options::builder()
2215 .inf_string(options::COFFEESCRIPT_INF)
2216 .build_strict();
2217
2218/// Number format to parse a [`Coffeescript`] float from string.
2219///
2220/// [`Coffeescript`]: https://coffeescript.org/
2221#[rustfmt::skip]
2222pub const COFFEESCRIPT_STRING: Options = Options::builder()
2223 .inf_string(options::COFFEESCRIPT_INF)
2224 .build_strict();
2225
2226/// Number format for a [`COBOL`] literal floating-point number.
2227///
2228/// [`Cobol`]: https://www.ibm.com/think/topics/cobol
2229#[rustfmt::skip]
2230pub const COBOL_LITERAL: Options = Options::builder()
2231 .nan_string(options::COBOL)
2232 .inf_string(options::COBOL)
2233 .build_strict();
2234
2235/// Number format to parse a [`COBOL`] float from string.
2236///
2237/// [`Cobol`]: https://www.ibm.com/think/topics/cobol
2238#[rustfmt::skip]
2239pub const COBOL_STRING: Options = Options::builder()
2240 .nan_string(options::COBOL)
2241 .inf_string(options::COBOL)
2242 .build_strict();
2243
2244/// Number format for an [`F#`] literal floating-point number.
2245///
2246/// [`F#`]: https://fsharp.org/
2247#[rustfmt::skip]
2248pub const FSHARP_LITERAL: Options = Options::builder()
2249 .nan_string(options::FSHARP_LITERAL_NAN)
2250 .inf_string(options::FSHARP_LITERAL_INF)
2251 .build_strict();
2252
2253/// Number format for a [`Visual Basic`] literal floating-point number.
2254///
2255/// [`Visual Basic`]: https://learn.microsoft.com/en-us/dotnet/visual-basic/
2256#[rustfmt::skip]
2257pub const VB_LITERAL: Options = Options::builder()
2258 .nan_string(options::VB_LITERAL)
2259 .inf_string(options::VB_LITERAL)
2260 .build_strict();
2261
2262/// Number format to parse a [`Visual Basic`] float from string.
2263///
2264/// [`Visual Basic`]: https://learn.microsoft.com/en-us/dotnet/visual-basic/
2265#[rustfmt::skip]
2266pub const VB_STRING: Options = Options::builder()
2267 .inf_string(options::VB_STRING_INF)
2268 .build_strict();
2269
2270/// Number format for an [`OCaml`] literal floating-point number.
2271///
2272/// [`OCaml`]: https://ocaml.org/
2273#[rustfmt::skip]
2274pub const OCAML_LITERAL: Options = Options::builder()
2275 .nan_string(options::OCAML_LITERAL_NAN)
2276 .inf_string(options::OCAML_LITERAL_INF)
2277 .build_strict();
2278
2279/// Number format for an [`Objective-C`] literal floating-point number.
2280///
2281/// [`Objective-C`]: https://en.wikipedia.org/wiki/Objective-C
2282#[rustfmt::skip]
2283pub const OBJECTIVEC_LITERAL: Options = Options::builder()
2284 .nan_string(options::OBJECTIVEC)
2285 .inf_string(options::OBJECTIVEC)
2286 .build_strict();
2287
2288/// Number format to parse an [`Objective-C`] float from string.
2289///
2290/// [`Objective-C`]: https://en.wikipedia.org/wiki/Objective-C
2291#[rustfmt::skip]
2292pub const OBJECTIVEC_STRING: Options = Options::builder()
2293 .nan_string(options::OBJECTIVEC)
2294 .inf_string(options::OBJECTIVEC)
2295 .build_strict();
2296
2297/// Number format for an [`ReasonML`] literal floating-point number.
2298///
2299/// [`ReasonML`]: https://reasonml.github.io/
2300#[rustfmt::skip]
2301pub const REASONML_LITERAL: Options = Options::builder()
2302 .nan_string(options::REASONML_LITERAL_NAN)
2303 .inf_string(options::REASONML_LITERAL_INF)
2304 .build_strict();
2305
2306/// Number format for a [`MATLAB`] literal floating-point number.
2307///
2308/// [`Matlab`]: https://www.mathworks.com/products/matlab.html
2309#[rustfmt::skip]
2310pub const MATLAB_LITERAL: Options = Options::builder()
2311 .inf_string(options::MATLAB_LITERAL_INF)
2312 .build_strict();
2313
2314/// Number format for a [`Zig`] literal floating-point number.
2315///
2316/// [`Zig`]: https://ziglang.org/
2317#[rustfmt::skip]
2318pub const ZIG_LITERAL: Options = Options::builder()
2319 .nan_string(options::ZIG_LITERAL)
2320 .inf_string(options::ZIG_LITERAL)
2321 .build_strict();
2322
2323/// Number format for a [`Sage`] literal floating-point number.
2324///
2325/// [`Sage`]: https://www.sagemath.org/
2326#[rustfmt::skip]
2327pub const SAGE_LITERAL: Options = Options::builder()
2328 .inf_string(options::SAGE_LITERAL_INF)
2329 .build_strict();
2330
2331/// Number format for a [`JSON`][`JSON-REF`] literal floating-point number.
2332///
2333/// [`JSON-REF`]: https://www.json.org/json-en.html
2334#[rustfmt::skip]
2335pub const JSON: Options = Options::builder()
2336 .nan_string(options::JSON)
2337 .inf_string(options::JSON)
2338 .build_strict();
2339
2340/// Number format for a [`TOML`][`TOML-REF`] literal floating-point number.
2341///
2342/// [`TOML-REF`]: https://toml.io/en/
2343#[rustfmt::skip]
2344pub const TOML: Options = Options::builder()
2345 .nan_string(options::TOML)
2346 .inf_string(options::TOML)
2347 .build_strict();
2348
2349/// Number format for a [`YAML`][`YAML-REF`] literal floating-point number.
2350///
2351/// [`YAML-REF`]: https://yaml.org/
2352#[rustfmt::skip]
2353pub const YAML: Options = JSON;
2354
2355/// Number format for an [`XML`][`XML-REF`] literal floating-point number.
2356///
2357/// [`XML-REF`]: https://en.wikipedia.org/wiki/XML
2358#[rustfmt::skip]
2359pub const XML: Options = Options::builder()
2360 .inf_string(options::XML_INF)
2361 .build_strict();
2362
2363/// Number format for a [`SQLite`] literal floating-point number.
2364///
2365/// [`SQLite`]: https://www.sqlite.org/
2366#[rustfmt::skip]
2367pub const SQLITE: Options = Options::builder()
2368 .nan_string(options::SQLITE)
2369 .inf_string(options::SQLITE)
2370 .build_strict();
2371
2372/// Number format for a [`PostgreSQL`] literal floating-point number.
2373///
2374/// [`PostgreSQL`]: https://www.postgresql.org/
2375#[rustfmt::skip]
2376pub const POSTGRESQL: Options = Options::builder()
2377 .nan_string(options::POSTGRESQL)
2378 .inf_string(options::POSTGRESQL)
2379 .build_strict();
2380
2381/// Number format for a [`MySQL`] literal floating-point number.
2382///
2383/// [`MySQL`]: https://www.mysql.com/
2384#[rustfmt::skip]
2385pub const MYSQL: Options = Options::builder()
2386 .nan_string(options::MYSQL)
2387 .inf_string(options::MYSQL)
2388 .build_strict();
2389
2390/// Number format for a [`MongoDB`] literal floating-point number.
2391///
2392/// [`MongoDB`]: https://www.mongodb.com/
2393#[rustfmt::skip]
2394pub const MONGODB: Options = Options::builder()
2395 .inf_string(options::MONGODB_INF)
2396 .build_strict();