lexical_write_float/
options.rs

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