lexical_write_float/
options.rs

1//! Configuration options for writing floats.
2
3use core::{mem, num};
4
5use lexical_util::ascii::{is_valid_ascii, is_valid_letter_slice};
6use lexical_util::constants::FormattedSize;
7use lexical_util::error::Error;
8use lexical_util::format::NumberFormat;
9use lexical_util::options::{self, WriteOptions};
10use lexical_util::result::Result;
11use static_assertions::const_assert;
12
13/// Type with the exact same size as a `usize`.
14pub type OptionUsize = Option<num::NonZeroUsize>;
15
16/// Type with the exact same size as a `i32`.
17pub type OptionI32 = Option<num::NonZeroI32>;
18
19// Ensure the sizes are identical.
20const_assert!(mem::size_of::<OptionUsize>() == mem::size_of::<usize>());
21const_assert!(mem::size_of::<OptionI32>() == mem::size_of::<i32>());
22
23/// Enumeration for how to round floats with precision control.
24#[derive(Debug, Copy, Clone, PartialEq, Eq)]
25pub enum RoundMode {
26    /// Round to the nearest float string with the given number of significant
27    /// digits.
28    Round,
29    /// Truncate the float string with the given number of significant digits.
30    Truncate,
31}
32
33/// Maximum length for a special string.
34const MAX_SPECIAL_STRING_LENGTH: usize = 50;
35const_assert!(MAX_SPECIAL_STRING_LENGTH < f32::FORMATTED_SIZE_DECIMAL);
36
37/// Builder for `Options`.
38#[derive(Debug, Clone, PartialEq, Eq)]
39pub struct OptionsBuilder {
40    /// Maximum number of significant digits to write.
41    /// If not set, it defaults to the algorithm's default.
42    max_significant_digits: OptionUsize,
43    /// Minimum number of significant digits to write.
44    /// If not set, it defaults to the algorithm's default.
45    /// Note that this isn't fully respected: if you wish to format
46    /// `0.1` with 25 significant digits, the correct result **should**
47    /// be `0.100000000000000005551115`. However, we would output
48    /// `0.100000000000000000000000`, which is still the nearest float.
49    min_significant_digits: OptionUsize,
50    /// Maximum exponent prior to using scientific notation.
51    /// This is ignored if the exponent base is not the same as the mantissa
52    /// radix. If not provided, use the algorithm's default.
53    positive_exponent_break: OptionI32,
54    /// Minimum exponent prior to using scientific notation.
55    /// This is ignored if the exponent base is not the same as the mantissa
56    /// radix. If not provided, use the algorithm's default.
57    negative_exponent_break: OptionI32,
58    /// Rounding mode for writing digits with precision control.
59    round_mode: RoundMode,
60    /// Trim the trailing ".0" from integral float strings.
61    trim_floats: bool,
62    /// Character to designate the exponent component of a float.
63    exponent: u8,
64    /// Character to separate the integer from the fraction components.
65    decimal_point: u8,
66    /// String representation of Not A Number, aka `NaN`.
67    nan_string: Option<&'static [u8]>,
68    /// String representation of `Infinity`.
69    inf_string: Option<&'static [u8]>,
70}
71
72impl OptionsBuilder {
73    // CONSTRUCTORS
74
75    #[inline(always)]
76    pub const fn new() -> Self {
77        Self {
78            max_significant_digits: None,
79            min_significant_digits: None,
80            positive_exponent_break: None,
81            negative_exponent_break: None,
82            round_mode: RoundMode::Round,
83            trim_floats: false,
84            exponent: b'e',
85            decimal_point: b'.',
86            nan_string: Some(b"NaN"),
87            inf_string: Some(b"inf"),
88        }
89    }
90
91    // GETTERS
92
93    /// Get the maximum number of significant digits to write.
94    #[inline(always)]
95    pub const fn get_max_significant_digits(&self) -> OptionUsize {
96        self.max_significant_digits
97    }
98
99    /// Get the minimum number of significant digits to write.
100    #[inline(always)]
101    pub const fn get_min_significant_digits(&self) -> OptionUsize {
102        self.min_significant_digits
103    }
104
105    /// Get the maximum exponent prior to using scientific notation.
106    #[inline(always)]
107    pub const fn get_positive_exponent_break(&self) -> OptionI32 {
108        self.positive_exponent_break
109    }
110
111    /// Get the minimum exponent prior to using scientific notation.
112    #[inline(always)]
113    pub const fn get_negative_exponent_break(&self) -> OptionI32 {
114        self.negative_exponent_break
115    }
116
117    /// Get the rounding mode for writing digits with precision control.
118    #[inline(always)]
119    pub const fn get_round_mode(&self) -> RoundMode {
120        self.round_mode
121    }
122
123    /// Get if we should trim a trailing `".0"` from floats.
124    #[inline(always)]
125    pub const fn get_trim_floats(&self) -> bool {
126        self.trim_floats
127    }
128
129    /// Get the character to designate the exponent component of a float.
130    #[inline(always)]
131    pub const fn get_exponent(&self) -> u8 {
132        self.exponent
133    }
134
135    /// Get the character to separate the integer from the fraction components.
136    #[inline(always)]
137    pub const fn get_decimal_point(&self) -> u8 {
138        self.decimal_point
139    }
140
141    /// Get the string representation for `NaN`.
142    #[inline(always)]
143    pub const fn get_nan_string(&self) -> Option<&'static [u8]> {
144        self.nan_string
145    }
146
147    /// Get the short string representation for `Infinity`.
148    #[inline(always)]
149    pub const fn get_inf_string(&self) -> Option<&'static [u8]> {
150        self.inf_string
151    }
152
153    // SETTERS
154
155    /// Set the maximum number of significant digits to write.
156    #[inline(always)]
157    pub const fn max_significant_digits(mut self, max_significant_digits: OptionUsize) -> Self {
158        self.max_significant_digits = max_significant_digits;
159        self
160    }
161
162    /// Set the minimum number of significant digits to write.
163    #[inline(always)]
164    pub const fn min_significant_digits(mut self, min_significant_digits: OptionUsize) -> Self {
165        self.min_significant_digits = min_significant_digits;
166        self
167    }
168
169    /// Set the maximum exponent prior to using scientific notation.
170    #[inline(always)]
171    pub const fn positive_exponent_break(mut self, positive_exponent_break: OptionI32) -> Self {
172        self.positive_exponent_break = positive_exponent_break;
173        self
174    }
175
176    /// Set the minimum exponent prior to using scientific notation.
177    #[inline(always)]
178    pub const fn negative_exponent_break(mut self, negative_exponent_break: OptionI32) -> Self {
179        self.negative_exponent_break = negative_exponent_break;
180        self
181    }
182
183    /// Set the rounding mode for writing digits with precision control.
184    #[inline(always)]
185    pub const fn round_mode(mut self, round_mode: RoundMode) -> Self {
186        self.round_mode = round_mode;
187        self
188    }
189
190    /// Set if we should trim a trailing `".0"` from floats.
191    #[inline(always)]
192    pub const fn trim_floats(mut self, trim_floats: bool) -> Self {
193        self.trim_floats = trim_floats;
194        self
195    }
196
197    /// Set the character to designate the exponent component of a float.
198    #[inline(always)]
199    pub const fn exponent(mut self, exponent: u8) -> Self {
200        self.exponent = exponent;
201        self
202    }
203
204    /// Set the character to separate the integer from the fraction components.
205    #[inline(always)]
206    pub const fn decimal_point(mut self, decimal_point: u8) -> Self {
207        self.decimal_point = decimal_point;
208        self
209    }
210
211    /// Set the string representation for `NaN`.
212    ///
213    /// Panics
214    ///
215    /// Setting a value too large may cause a panic even if [`FORMATTED_SIZE`]
216    /// elements are provided.
217    ///
218    /// [`FORMATTED_SIZE`]: `lexical_util::constants::FormattedSize::FORMATTED_SIZE`
219    #[inline(always)]
220    pub const fn nan_string(mut self, nan_string: Option<&'static [u8]>) -> Self {
221        self.nan_string = nan_string;
222        self
223    }
224
225    /// Set the string representation for `Infinity`.
226    ///
227    /// Panics
228    ///
229    /// Setting a value too large may cause a panic even if [`FORMATTED_SIZE`]
230    /// elements are provided.
231    ///
232    /// [`FORMATTED_SIZE`]: `lexical_util::constants::FormattedSize::FORMATTED_SIZE`
233    #[inline(always)]
234    pub const fn inf_string(mut self, inf_string: Option<&'static [u8]>) -> Self {
235        self.inf_string = inf_string;
236        self
237    }
238
239    // BUILDERS
240
241    /// Determine if `nan_str` is valid.
242    #[inline(always)]
243    #[allow(clippy::if_same_then_else, clippy::needless_bool)] // reason="more logical"
244    pub const fn nan_str_is_valid(&self) -> bool {
245        if self.nan_string.is_none() {
246            return true;
247        }
248
249        let nan = unwrap_str(self.nan_string);
250        let length = nan.len();
251        if length == 0 || length > MAX_SPECIAL_STRING_LENGTH {
252            false
253        } else if !matches!(nan[0], b'N' | b'n') {
254            false
255        } else if !is_valid_letter_slice(nan) {
256            false
257        } else {
258            true
259        }
260    }
261
262    /// Determine if `inf_str` is valid.
263    #[inline(always)]
264    #[allow(clippy::if_same_then_else, clippy::needless_bool)] // reason="more logical"
265    pub const fn inf_str_is_valid(&self) -> bool {
266        if self.inf_string.is_none() {
267            return true;
268        }
269
270        let inf = unwrap_str(self.inf_string);
271        let length = inf.len();
272        if length == 0 || length > MAX_SPECIAL_STRING_LENGTH {
273            false
274        } else if !matches!(inf[0], b'I' | b'i') {
275            false
276        } else if !is_valid_letter_slice(inf) {
277            false
278        } else {
279            true
280        }
281    }
282
283    /// Check if the builder state is valid.
284    #[inline(always)]
285    #[allow(clippy::if_same_then_else, clippy::needless_bool)] // reason="more logical"
286    pub const fn is_valid(&self) -> bool {
287        if !is_valid_ascii(self.exponent) {
288            false
289        } else if !is_valid_ascii(self.decimal_point) {
290            false
291        } else if !self.nan_str_is_valid() {
292            false
293        } else if !self.inf_str_is_valid() {
294            false
295        } else {
296            true
297        }
298    }
299
300    /// Build the Options struct without validation.
301    ///
302    /// # Panics
303    ///
304    /// This is completely safe, however, misusing this, especially
305    /// the `nan_string` and `inf_string` representations could cause
306    /// panics at runtime. Always use [`MAX_SPECIAL_STRING_LENGTH`] and
307    /// check if [`Self::is_valid`] prior to using a created format string.
308    #[inline(always)]
309    pub const fn build_unchecked(&self) -> Options {
310        Options {
311            max_significant_digits: self.max_significant_digits,
312            min_significant_digits: self.min_significant_digits,
313            positive_exponent_break: self.positive_exponent_break,
314            negative_exponent_break: self.negative_exponent_break,
315            round_mode: self.round_mode,
316            trim_floats: self.trim_floats,
317            exponent: self.exponent,
318            decimal_point: self.decimal_point,
319            nan_string: self.nan_string,
320            inf_string: self.inf_string,
321        }
322    }
323
324    /// Build the Options struct.
325    #[inline(always)]
326    #[allow(clippy::if_same_then_else)] // reason="more logical"
327    pub const fn build(&self) -> Result<Options> {
328        if self.nan_string.is_some() {
329            let nan = unwrap_str(self.nan_string);
330            if nan.is_empty() || !matches!(nan[0], b'N' | b'n') {
331                return Err(Error::InvalidNanString);
332            } else if !is_valid_letter_slice(nan) {
333                return Err(Error::InvalidNanString);
334            } else if nan.len() > MAX_SPECIAL_STRING_LENGTH {
335                return Err(Error::NanStringTooLong);
336            }
337        }
338
339        if self.inf_string.is_some() {
340            let inf = unwrap_str(self.inf_string);
341            if inf.is_empty() || !matches!(inf[0], b'I' | b'i') {
342                return Err(Error::InvalidInfString);
343            } else if !is_valid_letter_slice(inf) {
344                return Err(Error::InvalidInfString);
345            } else if inf.len() > MAX_SPECIAL_STRING_LENGTH {
346                return Err(Error::InfStringTooLong);
347            }
348        }
349
350        let min_digits = unwrap_or_zero_usize(self.min_significant_digits);
351        let max_digits = unwrap_or_max_usize(self.max_significant_digits);
352        if max_digits < min_digits {
353            Err(Error::InvalidFloatPrecision)
354        } else if unwrap_or_zero_i32(self.negative_exponent_break) > 0 {
355            Err(Error::InvalidNegativeExponentBreak)
356        } else if unwrap_or_zero_i32(self.positive_exponent_break) < 0 {
357            Err(Error::InvalidPositiveExponentBreak)
358        } else if !is_valid_ascii(self.exponent) {
359            Err(Error::InvalidExponentSymbol)
360        } else if !is_valid_ascii(self.decimal_point) {
361            Err(Error::InvalidDecimalPoint)
362        } else {
363            Ok(self.build_unchecked())
364        }
365    }
366}
367
368impl Default for OptionsBuilder {
369    #[inline(always)]
370    fn default() -> Self {
371        Self::new()
372    }
373}
374
375/// Options to customize writing floats.
376///
377/// # Examples
378///
379/// ```rust
380/// # extern crate lexical_write_float;
381/// use lexical_write_float::Options;
382///
383/// # pub fn main() {
384/// let options = Options::builder()
385///     .trim_floats(true)
386///     .nan_string(Some(b"NaN"))
387///     .inf_string(Some(b"Inf"))
388///     .build()
389///     .unwrap();
390/// # }
391/// ```
392#[derive(Debug, Clone, PartialEq, Eq)]
393pub struct Options {
394    /// Maximum number of significant digits to write.
395    /// If not set, it defaults to the algorithm's default.
396    max_significant_digits: OptionUsize,
397    /// Minimum number of significant digits to write.
398    /// If not set, it defaults to the algorithm's default.
399    min_significant_digits: OptionUsize,
400    /// Maximum exponent prior to using scientific notation.
401    /// This is ignored if the exponent base is not the same as the mantissa
402    /// radix. If not provided, use the algorithm's default.
403    positive_exponent_break: OptionI32,
404    /// Minimum exponent prior to using scientific notation.
405    /// This is ignored if the exponent base is not the same as the mantissa
406    /// radix. If not provided, use the algorithm's default.
407    negative_exponent_break: OptionI32,
408    /// Rounding mode for writing digits with precision control.
409    round_mode: RoundMode,
410    /// Trim the trailing ".0" from integral float strings.
411    trim_floats: bool,
412    /// Character to designate the exponent component of a float.
413    exponent: u8,
414    /// Character to separate the integer from the fraction components.
415    decimal_point: u8,
416    /// String representation of Not A Number, aka `NaN`.
417    nan_string: Option<&'static [u8]>,
418    /// String representation of `Infinity`.
419    inf_string: Option<&'static [u8]>,
420}
421
422impl Options {
423    // CONSTRUCTORS
424
425    /// Create options with default values.
426    #[inline(always)]
427    pub const fn new() -> Self {
428        Self::builder().build_unchecked()
429    }
430
431    /// Create the default options for a given radix.
432    #[inline(always)]
433    #[cfg(feature = "power-of-two")]
434    pub const fn from_radix(radix: u8) -> Self {
435        // Need to determine the correct exponent character ('e' or '^'),
436        // since the default character is `e` normally, but this is a valid
437        // digit for radix >= 15.
438        let mut builder = Self::builder();
439        if radix >= 15 {
440            builder = builder.exponent(b'^');
441        }
442        builder.build_unchecked()
443    }
444
445    // GETTERS
446
447    /// Check if the options state is valid.
448    #[inline(always)]
449    pub const fn is_valid(&self) -> bool {
450        self.rebuild().is_valid()
451    }
452
453    /// Get the maximum number of significant digits to write.
454    #[inline(always)]
455    pub const fn max_significant_digits(&self) -> OptionUsize {
456        self.max_significant_digits
457    }
458
459    /// Get the minimum number of significant digits to write.
460    #[inline(always)]
461    pub const fn min_significant_digits(&self) -> OptionUsize {
462        self.min_significant_digits
463    }
464
465    /// Get the maximum exponent prior to using scientific notation.
466    #[inline(always)]
467    pub const fn positive_exponent_break(&self) -> OptionI32 {
468        self.positive_exponent_break
469    }
470
471    /// Get the minimum exponent prior to using scientific notation.
472    #[inline(always)]
473    pub const fn negative_exponent_break(&self) -> OptionI32 {
474        self.negative_exponent_break
475    }
476
477    /// Get the rounding mode for writing digits with precision control.
478    #[inline(always)]
479    pub const fn round_mode(&self) -> RoundMode {
480        self.round_mode
481    }
482
483    /// Get if we should trim a trailing `".0"` from floats.
484    #[inline(always)]
485    pub const fn trim_floats(&self) -> bool {
486        self.trim_floats
487    }
488
489    /// Get the character to designate the exponent component of a float.
490    #[inline(always)]
491    pub const fn exponent(&self) -> u8 {
492        self.exponent
493    }
494
495    /// Get the character to separate the integer from the fraction components.
496    #[inline(always)]
497    pub const fn decimal_point(&self) -> u8 {
498        self.decimal_point
499    }
500
501    /// Get the string representation for `NaN`.
502    #[inline(always)]
503    pub const fn nan_string(&self) -> Option<&'static [u8]> {
504        self.nan_string
505    }
506
507    /// Get the short string representation for `Infinity`.
508    #[inline(always)]
509    pub const fn inf_string(&self) -> Option<&'static [u8]> {
510        self.inf_string
511    }
512
513    // SETTERS
514
515    /// Set the maximum number of significant digits to write.
516    #[inline(always)]
517    pub fn set_max_significant_digits(&mut self, max_significant_digits: OptionUsize) {
518        self.max_significant_digits = max_significant_digits;
519    }
520
521    /// Set the minimum number of significant digits to write.
522    #[inline(always)]
523    pub fn set_min_significant_digits(&mut self, min_significant_digits: OptionUsize) {
524        self.min_significant_digits = min_significant_digits;
525    }
526
527    /// Set the maximum exponent prior to using scientific notation.
528    #[inline(always)]
529    pub fn set_positive_exponent_break(&mut self, positive_exponent_break: OptionI32) {
530        self.positive_exponent_break = positive_exponent_break;
531    }
532
533    /// Set the minimum exponent prior to using scientific notation.
534    #[inline(always)]
535    pub fn set_negative_exponent_break(&mut self, negative_exponent_break: OptionI32) {
536        self.negative_exponent_break = negative_exponent_break;
537    }
538
539    /// Set the rounding mode for writing digits with precision control.
540    #[inline(always)]
541    pub fn set_round_mode(&mut self, round_mode: RoundMode) {
542        self.round_mode = round_mode;
543    }
544
545    /// Set if we should trim a trailing `".0"` from floats.
546    #[inline(always)]
547    pub fn set_trim_floats(&mut self, trim_floats: bool) {
548        self.trim_floats = trim_floats;
549    }
550
551    /// Set the character to designate the exponent component of a float.
552    ///
553    /// # Safety
554    ///
555    /// Always safe, but may produce invalid output if the exponent
556    /// is not a valid ASCII character.
557    #[inline(always)]
558    pub fn set_exponent(&mut self, exponent: u8) {
559        self.exponent = exponent;
560    }
561
562    /// Set the character to separate the integer from the fraction components.
563    ///
564    /// # Safety
565    ///
566    /// Always safe, but may produce invalid output if the decimal point
567    /// is not a valid ASCII character.
568    #[inline(always)]
569    pub fn set_decimal_point(&mut self, decimal_point: u8) {
570        self.decimal_point = decimal_point;
571    }
572
573    /// Set the string representation for `NaN`.
574    ///
575    /// Panics
576    ///
577    /// Setting a value too large may cause a panic even if [`FORMATTED_SIZE`]
578    /// elements are provided.
579    ///
580    /// [`FORMATTED_SIZE`]: `lexical_util::constants::FormattedSize::FORMATTED_SIZE`
581    #[inline(always)]
582    pub fn set_nan_string(&mut self, nan_string: Option<&'static [u8]>) {
583        self.nan_string = nan_string;
584    }
585
586    /// Set the short string representation for `Infinity`
587    ///
588    /// Panics
589    ///
590    /// Setting a value too large may cause a panic even if [`FORMATTED_SIZE`]
591    /// elements are provided.
592    ///
593    /// [`FORMATTED_SIZE`]: `lexical_util::constants::FormattedSize::FORMATTED_SIZE`
594    #[inline(always)]
595    pub fn set_inf_string(&mut self, inf_string: Option<&'static [u8]>) {
596        self.inf_string = inf_string;
597    }
598
599    // BUILDERS
600
601    /// Get `WriteFloatOptionsBuilder` as a static function.
602    #[inline(always)]
603    pub const fn builder() -> OptionsBuilder {
604        OptionsBuilder::new()
605    }
606
607    /// Create `OptionsBuilder` using existing values.
608    #[inline(always)]
609    pub const fn rebuild(&self) -> OptionsBuilder {
610        OptionsBuilder {
611            max_significant_digits: self.max_significant_digits,
612            min_significant_digits: self.min_significant_digits,
613            positive_exponent_break: self.positive_exponent_break,
614            negative_exponent_break: self.negative_exponent_break,
615            round_mode: self.round_mode,
616            trim_floats: self.trim_floats,
617            exponent: self.exponent,
618            decimal_point: self.decimal_point,
619            nan_string: self.nan_string,
620            inf_string: self.inf_string,
621        }
622    }
623}
624
625impl Default for Options {
626    #[inline(always)]
627    fn default() -> Self {
628        Self::new()
629    }
630}
631
632impl WriteOptions for Options {
633    #[inline(always)]
634    fn is_valid(&self) -> bool {
635        Self::is_valid(self)
636    }
637
638    #[inline(always)]
639    fn buffer_size<T: FormattedSize, const FORMAT: u128>(&self) -> usize {
640        let format = NumberFormat::<{ FORMAT }> {};
641
642        // At least 2 for the decimal point and sign.
643        let mut count: usize = 2;
644
645        // First need to calculate maximum number of digits from leading or
646        // trailing zeros, IE, the exponent break.
647        if !format.no_exponent_notation() {
648            let min_exp = self.negative_exponent_break().map_or(-5, |x| x.get());
649            let max_exp = self.positive_exponent_break().map_or(9, |x| x.get());
650            let exp = min_exp.abs().max(max_exp) as usize;
651            if cfg!(feature = "power-of-two") && exp < 13 {
652                // 11 for the exponent digits in binary, 1 for the sign, 1 for the symbol
653                count += 13;
654            } else if exp < 5 {
655                // 3 for the exponent digits in decimal, 1 for the sign, 1 for the symbol
656                count += 5;
657            } else {
658                // More leading or trailing zeros than the exponent digits.
659                count += exp;
660            }
661        } else if cfg!(feature = "power-of-two") {
662            // Min is 2^-1075.
663            count += 1075;
664        } else {
665            // Min is 10^-324.
666            count += 324;
667        }
668
669        // Now add the number of significant digits.
670        let radix = format.radix();
671        let formatted_digits = if radix == 10 {
672            // Really should be 18, but add some extra to be cautious.
673            28
674        } else {
675            //  BINARY:
676            //      53 significant mantissa bits for binary, add a few extra.
677            //  RADIX:
678            //      Our limit is `delta`. The maximum relative delta is 2.22e-16,
679            //      around 1. If we have values below 1, our delta is smaller, but
680            //      the max fraction is also a lot smaller. Above, and our fraction
681            //      must be < 1.0, so our delta is less significant. Therefore,
682            //      if our fraction is just less than 1, for a float near 2.0,
683            //      we can do at **maximum** 33 digits (for base 3). Let's just
684            //      assume it's a lot higher, and go with 64.
685            64
686        };
687        let digits = if let Some(max_digits) = self.max_significant_digits() {
688            formatted_digits.min(max_digits.get())
689        } else {
690            formatted_digits
691        };
692        let digits = if let Some(min_digits) = self.min_significant_digits() {
693            digits.max(min_digits.get())
694        } else {
695            formatted_digits
696        };
697        count += digits;
698
699        count
700    }
701}
702
703/// Define `unwrap_or_zero` for a custom type.
704macro_rules! unwrap_or_zero {
705    ($name:ident, $opt:ident, $t:ident) => {
706        /// Unwrap `Option` as a const fn.
707        #[inline(always)]
708        const fn $name(option: $opt) -> $t {
709            match option {
710                Some(x) => x.get(),
711                None => 0,
712            }
713        }
714    };
715}
716
717unwrap_or_zero!(unwrap_or_zero_usize, OptionUsize, usize);
718unwrap_or_zero!(unwrap_or_zero_i32, OptionI32, i32);
719
720/// Unwrap `Option` as a const fn.
721#[inline(always)]
722const fn unwrap_or_max_usize(option: OptionUsize) -> usize {
723    match option {
724        Some(x) => x.get(),
725        None => usize::MAX,
726    }
727}
728
729/// Unwrap `Option` as a const fn.
730#[inline(always)]
731const fn unwrap_str(option: Option<&'static [u8]>) -> &'static [u8] {
732    match option {
733        Some(x) => x,
734        None => &[],
735    }
736}
737
738// PRE-DEFINED CONSTANTS
739// ---------------------
740
741// Only constants that differ from the standard version are included.
742
743/// Standard number format.
744#[rustfmt::skip]
745pub const STANDARD: Options = Options::new();
746const_assert!(STANDARD.is_valid());
747
748/// Numerical format with a decimal comma.
749/// This is the standard numerical format for most of the world.
750#[rustfmt::skip]
751pub const DECIMAL_COMMA: Options = Options::builder()
752        .decimal_point(b',')
753        .build_unchecked();
754const_assert!(DECIMAL_COMMA.is_valid());
755
756/// Numerical format for hexadecimal floats, which use a `p` exponent.
757#[rustfmt::skip]
758pub const HEX_FLOAT: Options = Options::builder()
759        .exponent(b'p')
760        .build_unchecked();
761const_assert!(HEX_FLOAT.is_valid());
762
763/// Numerical format where `^` is used as the exponent notation character.
764/// This isn't very common, but is useful when `e` or `p` are valid digits.
765#[rustfmt::skip]
766pub const CARAT_EXPONENT: Options = Options::builder()
767        .exponent(b'^')
768        .build_unchecked();
769const_assert!(CARAT_EXPONENT.is_valid());
770
771/// Number format for a `Rust` literal floating-point number.
772#[rustfmt::skip]
773pub const RUST_LITERAL: Options = Options::builder()
774        .nan_string(options::RUST_LITERAL)
775        .inf_string(options::RUST_LITERAL)
776        .build_unchecked();
777const_assert!(RUST_LITERAL.is_valid());
778
779/// Number format for a `Python` literal floating-point number.
780#[rustfmt::skip]
781pub const PYTHON_LITERAL: Options = Options::builder()
782        .nan_string(options::PYTHON_LITERAL)
783        .inf_string(options::PYTHON_LITERAL)
784        .build_unchecked();
785const_assert!(PYTHON_LITERAL.is_valid());
786
787/// Number format for a `C++` literal floating-point number.
788#[rustfmt::skip]
789pub const CXX_LITERAL: Options = Options::builder()
790        .nan_string(options::CXX_LITERAL_NAN)
791        .inf_string(options::CXX_LITERAL_INF)
792        .build_unchecked();
793const_assert!(CXX_LITERAL.is_valid());
794
795/// Number format for a `C` literal floating-point number.
796#[rustfmt::skip]
797pub const C_LITERAL: Options = Options::builder()
798        .nan_string(options::C_LITERAL_NAN)
799        .inf_string(options::C_LITERAL_INF)
800        .build_unchecked();
801const_assert!(CXX_LITERAL.is_valid());
802
803/// Number format for a `Ruby` literal floating-point number.
804#[rustfmt::skip]
805pub const RUBY_LITERAL: Options = Options::builder()
806        .positive_exponent_break(num::NonZeroI32::new(14))
807        .negative_exponent_break(num::NonZeroI32::new(-4))
808        .nan_string(options::RUBY_LITERAL_NAN)
809        .inf_string(options::RUBY_LITERAL_INF)
810        .build_unchecked();
811const_assert!(RUBY_LITERAL.is_valid());
812
813/// Number format to parse a `Ruby` float from string.
814#[rustfmt::skip]
815pub const RUBY_STRING: Options = Options::builder()
816        .nan_string(options::RUBY_LITERAL_NAN)
817        .inf_string(options::RUBY_LITERAL_INF)
818        .build_unchecked();
819const_assert!(RUBY_STRING.is_valid());
820
821/// Number format for a `Swift` literal floating-point number.
822#[rustfmt::skip]
823pub const SWIFT_LITERAL: Options = Options::builder()
824        .nan_string(options::SWIFT_LITERAL)
825        .inf_string(options::SWIFT_LITERAL)
826        .build_unchecked();
827const_assert!(SWIFT_LITERAL.is_valid());
828
829/// Number format for a `Go` literal floating-point number.
830#[rustfmt::skip]
831pub const GO_LITERAL: Options = Options::builder()
832        .nan_string(options::GO_LITERAL)
833        .inf_string(options::GO_LITERAL)
834        .build_unchecked();
835const_assert!(GO_LITERAL.is_valid());
836
837/// Number format for a `Haskell` literal floating-point number.
838#[rustfmt::skip]
839pub const HASKELL_LITERAL: Options = Options::builder()
840        .nan_string(options::HASKELL_LITERAL)
841        .inf_string(options::HASKELL_LITERAL)
842        .build_unchecked();
843const_assert!(HASKELL_LITERAL.is_valid());
844
845/// Number format to parse a `Haskell` float from string.
846#[rustfmt::skip]
847pub const HASKELL_STRING: Options = Options::builder()
848        .inf_string(options::HASKELL_STRING_INF)
849        .build_unchecked();
850const_assert!(HASKELL_STRING.is_valid());
851
852/// Number format for a `Javascript` literal floating-point number.
853#[rustfmt::skip]
854pub const JAVASCRIPT_LITERAL: Options = Options::builder()
855        .inf_string(options::JAVASCRIPT_INF)
856        .build_unchecked();
857const_assert!(JAVASCRIPT_LITERAL.is_valid());
858
859/// Number format to parse a `Javascript` float from string.
860#[rustfmt::skip]
861pub const JAVASCRIPT_STRING: Options = Options::builder()
862        .inf_string(options::JAVASCRIPT_INF)
863        .build_unchecked();
864const_assert!(JAVASCRIPT_STRING.is_valid());
865
866/// Number format for a `Perl` literal floating-point number.
867#[rustfmt::skip]
868pub const PERL_LITERAL: Options = Options::builder()
869        .nan_string(options::PERL_LITERAL)
870        .inf_string(options::PERL_LITERAL)
871        .build_unchecked();
872const_assert!(PERL_LITERAL.is_valid());
873
874/// Number format for a `PHP` literal floating-point number.
875#[rustfmt::skip]
876pub const PHP_LITERAL: Options = Options::builder()
877        .nan_string(options::PHP_LITERAL_NAN)
878        .inf_string(options::PHP_LITERAL_INF)
879        .build_unchecked();
880const_assert!(PHP_LITERAL.is_valid());
881
882/// Number format for a `Java` literal floating-point number.
883#[rustfmt::skip]
884pub const JAVA_LITERAL: Options = Options::builder()
885        .nan_string(options::JAVA_LITERAL)
886        .inf_string(options::JAVA_LITERAL)
887        .build_unchecked();
888const_assert!(JAVA_LITERAL.is_valid());
889
890/// Number format to parse a `Java` float from string.
891#[rustfmt::skip]
892pub const JAVA_STRING: Options = Options::builder()
893        .inf_string(options::JAVA_STRING_INF)
894        .build_unchecked();
895const_assert!(JAVA_STRING.is_valid());
896
897/// Number format for an `R` literal floating-point number.
898#[rustfmt::skip]
899pub const R_LITERAL: Options = Options::builder()
900        .inf_string(options::R_LITERAL_INF)
901        .build_unchecked();
902const_assert!(R_LITERAL.is_valid());
903
904/// Number format for a `Kotlin` literal floating-point number.
905#[rustfmt::skip]
906pub const KOTLIN_LITERAL: Options = Options::builder()
907        .nan_string(options::KOTLIN_LITERAL)
908        .inf_string(options::KOTLIN_LITERAL)
909        .build_unchecked();
910const_assert!(KOTLIN_LITERAL.is_valid());
911
912/// Number format to parse a `Kotlin` float from string.
913#[rustfmt::skip]
914pub const KOTLIN_STRING: Options = Options::builder()
915        .inf_string(options::KOTLIN_STRING_INF)
916        .build_unchecked();
917const_assert!(KOTLIN_STRING.is_valid());
918
919/// Number format for a `Julia` literal floating-point number.
920#[rustfmt::skip]
921pub const JULIA_LITERAL: Options = Options::builder()
922        .inf_string(options::JULIA_LITERAL_INF)
923        .build_unchecked();
924const_assert!(JULIA_LITERAL.is_valid());
925
926/// Number format for a `C#` literal floating-point number.
927#[rustfmt::skip]
928pub const CSHARP_LITERAL: Options = Options::builder()
929        .nan_string(options::CSHARP_LITERAL)
930        .inf_string(options::CSHARP_LITERAL)
931        .build_unchecked();
932const_assert!(CSHARP_LITERAL.is_valid());
933
934/// Number format to parse a `C#` float from string.
935#[rustfmt::skip]
936pub const CSHARP_STRING: Options = Options::builder()
937        .inf_string(options::CSHARP_STRING_INF)
938        .build_unchecked();
939const_assert!(CSHARP_STRING.is_valid());
940
941/// Number format for a `Kawa` literal floating-point number.
942#[rustfmt::skip]
943pub const KAWA_LITERAL: Options = Options::builder()
944        .nan_string(options::KAWA)
945        .inf_string(options::KAWA)
946        .build_unchecked();
947const_assert!(KAWA_LITERAL.is_valid());
948
949/// Number format to parse a `Kawa` float from string.
950#[rustfmt::skip]
951pub const KAWA_STRING: Options = Options::builder()
952        .nan_string(options::KAWA)
953        .inf_string(options::KAWA)
954        .build_unchecked();
955const_assert!(KAWA_STRING.is_valid());
956
957/// Number format for a `Gambit-C` literal floating-point number.
958#[rustfmt::skip]
959pub const GAMBITC_LITERAL: Options = Options::builder()
960        .nan_string(options::GAMBITC)
961        .inf_string(options::GAMBITC)
962        .build_unchecked();
963const_assert!(GAMBITC_LITERAL.is_valid());
964
965/// Number format to parse a `Gambit-C` float from string.
966#[rustfmt::skip]
967pub const GAMBITC_STRING: Options = Options::builder()
968        .nan_string(options::GAMBITC)
969        .inf_string(options::GAMBITC)
970        .build_unchecked();
971const_assert!(GAMBITC_STRING.is_valid());
972
973/// Number format for a `Guile` literal floating-point number.
974#[rustfmt::skip]
975pub const GUILE_LITERAL: Options = Options::builder()
976        .nan_string(options::GUILE)
977        .inf_string(options::GUILE)
978        .build_unchecked();
979const_assert!(GUILE_LITERAL.is_valid());
980
981/// Number format to parse a `Guile` float from string.
982#[rustfmt::skip]
983pub const GUILE_STRING: Options = Options::builder()
984        .nan_string(options::GUILE)
985        .inf_string(options::GUILE)
986        .build_unchecked();
987const_assert!(GUILE_STRING.is_valid());
988
989/// Number format for a `Clojure` literal floating-point number.
990#[rustfmt::skip]
991pub const CLOJURE_LITERAL: Options = Options::builder()
992        .nan_string(options::CLOJURE_LITERAL)
993        .inf_string(options::CLOJURE_LITERAL)
994        .build_unchecked();
995const_assert!(CLOJURE_LITERAL.is_valid());
996
997/// Number format to parse a `Clojure` float from string.
998#[rustfmt::skip]
999pub const CLOJURE_STRING: Options = Options::builder()
1000        .inf_string(options::CLOJURE_STRING_INF)
1001        .build_unchecked();
1002const_assert!(CLOJURE_STRING.is_valid());
1003
1004/// Number format for an `Erlang` literal floating-point number.
1005#[rustfmt::skip]
1006pub const ERLANG_LITERAL: Options = Options::builder()
1007        .nan_string(options::ERLANG_LITERAL_NAN)
1008        .build_unchecked();
1009const_assert!(ERLANG_LITERAL.is_valid());
1010
1011/// Number format to parse an `Erlang` float from string.
1012#[rustfmt::skip]
1013pub const ERLANG_STRING: Options = Options::builder()
1014        .nan_string(options::ERLANG_STRING)
1015        .inf_string(options::ERLANG_STRING)
1016        .build_unchecked();
1017const_assert!(ERLANG_STRING.is_valid());
1018
1019/// Number format for an `Elm` literal floating-point number.
1020#[rustfmt::skip]
1021pub const ELM_LITERAL: Options = Options::builder()
1022        .nan_string(options::ELM_LITERAL)
1023        .inf_string(options::ELM_LITERAL)
1024        .build_unchecked();
1025const_assert!(ELM_LITERAL.is_valid());
1026
1027/// Number format to parse an `Elm` float from string.
1028#[rustfmt::skip]
1029pub const ELM_STRING: Options = Options::builder()
1030        .nan_string(options::ELM_STRING_NAN)
1031        .inf_string(options::ELM_STRING_INF)
1032        .build_unchecked();
1033const_assert!(ELM_STRING.is_valid());
1034
1035/// Number format for a `Scala` literal floating-point number.
1036#[rustfmt::skip]
1037pub const SCALA_LITERAL: Options = Options::builder()
1038        .nan_string(options::SCALA_LITERAL)
1039        .inf_string(options::SCALA_LITERAL)
1040        .build_unchecked();
1041const_assert!(SCALA_LITERAL.is_valid());
1042
1043/// Number format to parse a `Scala` float from string.
1044#[rustfmt::skip]
1045pub const SCALA_STRING: Options = Options::builder()
1046        .inf_string(options::SCALA_STRING_INF)
1047        .build_unchecked();
1048const_assert!(SCALA_STRING.is_valid());
1049
1050/// Number format for an `Elixir` literal floating-point number.
1051#[rustfmt::skip]
1052pub const ELIXIR_LITERAL: Options = Options::builder()
1053        .nan_string(options::ELIXIR)
1054        .inf_string(options::ELIXIR)
1055        .build_unchecked();
1056const_assert!(ELIXIR_LITERAL.is_valid());
1057
1058/// Number format to parse an `Elixir` float from string.
1059#[rustfmt::skip]
1060pub const ELIXIR_STRING: Options = Options::builder()
1061        .nan_string(options::ELIXIR)
1062        .inf_string(options::ELIXIR)
1063        .build_unchecked();
1064const_assert!(ELIXIR_STRING.is_valid());
1065
1066/// Number format for a `FORTRAN` literal floating-point number.
1067#[rustfmt::skip]
1068pub const FORTRAN_LITERAL: Options = Options::builder()
1069        .nan_string(options::FORTRAN_LITERAL)
1070        .inf_string(options::FORTRAN_LITERAL)
1071        .build_unchecked();
1072const_assert!(FORTRAN_LITERAL.is_valid());
1073
1074/// Number format for a `D` literal floating-point number.
1075#[rustfmt::skip]
1076pub const D_LITERAL: Options = Options::builder()
1077        .nan_string(options::D_LITERAL)
1078        .inf_string(options::D_LITERAL)
1079        .build_unchecked();
1080const_assert!(D_LITERAL.is_valid());
1081
1082/// Number format for a `Coffeescript` literal floating-point number.
1083#[rustfmt::skip]
1084pub const COFFEESCRIPT_LITERAL: Options = Options::builder()
1085        .inf_string(options::COFFEESCRIPT_INF)
1086        .build_unchecked();
1087const_assert!(COFFEESCRIPT_LITERAL.is_valid());
1088
1089/// Number format to parse a `Coffeescript` float from string.
1090#[rustfmt::skip]
1091pub const COFFEESCRIPT_STRING: Options = Options::builder()
1092        .inf_string(options::COFFEESCRIPT_INF)
1093        .build_unchecked();
1094const_assert!(COFFEESCRIPT_STRING.is_valid());
1095
1096/// Number format for a `COBOL` literal floating-point number.
1097#[rustfmt::skip]
1098pub const COBOL_LITERAL: Options = Options::builder()
1099        .nan_string(options::COBOL)
1100        .inf_string(options::COBOL)
1101        .build_unchecked();
1102const_assert!(COBOL_LITERAL.is_valid());
1103
1104/// Number format to parse a `COBOL` float from string.
1105#[rustfmt::skip]
1106pub const COBOL_STRING: Options = Options::builder()
1107        .nan_string(options::COBOL)
1108        .inf_string(options::COBOL)
1109        .build_unchecked();
1110const_assert!(COBOL_STRING.is_valid());
1111
1112/// Number format for an `F#` literal floating-point number.
1113#[rustfmt::skip]
1114pub const FSHARP_LITERAL: Options = Options::builder()
1115        .nan_string(options::FSHARP_LITERAL_NAN)
1116        .inf_string(options::FSHARP_LITERAL_INF)
1117        .build_unchecked();
1118const_assert!(FSHARP_LITERAL.is_valid());
1119
1120/// Number format for a `Visual Basic` literal floating-point number.
1121#[rustfmt::skip]
1122pub const VB_LITERAL: Options = Options::builder()
1123        .nan_string(options::VB_LITERAL)
1124        .inf_string(options::VB_LITERAL)
1125        .build_unchecked();
1126const_assert!(VB_LITERAL.is_valid());
1127
1128/// Number format to parse a `Visual Basic` float from string.
1129#[rustfmt::skip]
1130pub const VB_STRING: Options = Options::builder()
1131        .inf_string(options::VB_STRING_INF)
1132        .build_unchecked();
1133const_assert!(VB_STRING.is_valid());
1134
1135/// Number format for an `OCaml` literal floating-point number.
1136#[rustfmt::skip]
1137pub const OCAML_LITERAL: Options = Options::builder()
1138        .nan_string(options::OCAML_LITERAL_NAN)
1139        .inf_string(options::OCAML_LITERAL_INF)
1140        .build_unchecked();
1141const_assert!(OCAML_LITERAL.is_valid());
1142
1143/// Number format for an `Objective-C` literal floating-point number.
1144#[rustfmt::skip]
1145pub const OBJECTIVEC_LITERAL: Options = Options::builder()
1146        .nan_string(options::OBJECTIVEC)
1147        .inf_string(options::OBJECTIVEC)
1148        .build_unchecked();
1149const_assert!(OBJECTIVEC_LITERAL.is_valid());
1150
1151/// Number format to parse an `Objective-C` float from string.
1152#[rustfmt::skip]
1153pub const OBJECTIVEC_STRING: Options = Options::builder()
1154        .nan_string(options::OBJECTIVEC)
1155        .inf_string(options::OBJECTIVEC)
1156        .build_unchecked();
1157const_assert!(OBJECTIVEC_STRING.is_valid());
1158
1159/// Number format for an `ReasonML` literal floating-point number.
1160#[rustfmt::skip]
1161pub const REASONML_LITERAL: Options = Options::builder()
1162        .nan_string(options::REASONML_LITERAL_NAN)
1163        .inf_string(options::REASONML_LITERAL_INF)
1164        .build_unchecked();
1165const_assert!(REASONML_LITERAL.is_valid());
1166
1167/// Number format for a `MATLAB` literal floating-point number.
1168#[rustfmt::skip]
1169pub const MATLAB_LITERAL: Options = Options::builder()
1170        .inf_string(options::MATLAB_LITERAL_INF)
1171        .build_unchecked();
1172const_assert!(MATLAB_LITERAL.is_valid());
1173
1174/// Number format for a `Zig` literal floating-point number.
1175#[rustfmt::skip]
1176pub const ZIG_LITERAL: Options = Options::builder()
1177        .nan_string(options::ZIG_LITERAL)
1178        .inf_string(options::ZIG_LITERAL)
1179        .build_unchecked();
1180const_assert!(ZIG_LITERAL.is_valid());
1181
1182/// Number format for a `Safe` literal floating-point number.
1183#[rustfmt::skip]
1184pub const SAGE_LITERAL: Options = Options::builder()
1185        .inf_string(options::SAGE_LITERAL_INF)
1186        .build_unchecked();
1187const_assert!(SAGE_LITERAL.is_valid());
1188
1189/// Number format for a `JSON` literal floating-point number.
1190#[rustfmt::skip]
1191pub const JSON: Options = Options::builder()
1192        .nan_string(options::JSON)
1193        .inf_string(options::JSON)
1194        .build_unchecked();
1195const_assert!(JSON.is_valid());
1196
1197/// Number format for a `TOML` literal floating-point number.
1198#[rustfmt::skip]
1199pub const TOML: Options = Options::builder()
1200        .nan_string(options::TOML)
1201        .inf_string(options::TOML)
1202        .build_unchecked();
1203const_assert!(TOML.is_valid());
1204
1205/// Number format for a `YAML` literal floating-point number.
1206#[rustfmt::skip]
1207pub const YAML: Options = JSON;
1208
1209/// Number format for an `XML` literal floating-point number.
1210#[rustfmt::skip]
1211pub const XML: Options = Options::builder()
1212        .inf_string(options::XML_INF)
1213        .build_unchecked();
1214const_assert!(XML.is_valid());
1215
1216/// Number format for a `SQLite` literal floating-point number.
1217#[rustfmt::skip]
1218pub const SQLITE: Options = Options::builder()
1219        .nan_string(options::SQLITE)
1220        .inf_string(options::SQLITE)
1221        .build_unchecked();
1222const_assert!(SQLITE.is_valid());
1223
1224/// Number format for a `PostgreSQL` literal floating-point number.
1225#[rustfmt::skip]
1226pub const POSTGRESQL: Options = Options::builder()
1227        .nan_string(options::POSTGRESQL)
1228        .inf_string(options::POSTGRESQL)
1229        .build_unchecked();
1230const_assert!(POSTGRESQL.is_valid());
1231
1232/// Number format for a `MySQL` literal floating-point number.
1233#[rustfmt::skip]
1234pub const MYSQL: Options = Options::builder()
1235        .nan_string(options::MYSQL)
1236        .inf_string(options::MYSQL)
1237        .build_unchecked();
1238const_assert!(MYSQL.is_valid());
1239
1240/// Number format for a `MongoDB` literal floating-point number.
1241#[rustfmt::skip]
1242pub const MONGODB: Options = Options::builder()
1243        .inf_string(options::MONGODB_INF)
1244        .build_unchecked();
1245const_assert!(MONGODB.is_valid());