lexical_util/
api.rs

1//! Implement string conversion routines in a single trait.
2
3// NOTE:
4//  We use macros to define the traits, rather than implement here
5//  since we can't define traits for types when both are defined outside
6//  the current crate, including in workspaces.
7
8// FROM LEXICAL
9
10/// Define FromLexical trait.
11#[macro_export]
12#[cfg(feature = "parse")]
13macro_rules! from_lexical {
14    () => {
15        /// Trait for numerical types that can be parsed from bytes.
16        pub trait FromLexical: lexical_util::num::Number {
17            /// Checked parser for a string-to-number conversion.
18            ///
19            /// This method parses the entire string, returning an error if
20            /// any invalid digits are found during parsing. Returns a `Result`
21            /// containing either the parsed value, or an error containing
22            /// any errors that occurred during parsing.
23            ///
24            /// * `bytes`   - Slice containing a numeric string.
25            fn from_lexical(bytes: &[u8]) -> lexical_util::result::Result<Self>;
26
27            /// Checked parser for a string-to-number conversion.
28            ///
29            /// This method parses until an invalid digit is found (or the end
30            /// of the string), returning the number of processed digits
31            /// and the parsed value until that point. Returns a `Result`
32            /// containing either the parsed value and the number of processed
33            /// digits, or an error containing any errors that occurred during
34            /// parsing.
35            ///
36            /// * `bytes`   - Slice containing a numeric string.
37            fn from_lexical_partial(bytes: &[u8]) -> lexical_util::result::Result<(Self, usize)>;
38        }
39    };
40}
41
42/// Define FromLexicalWithOptions trait.
43#[macro_export]
44#[cfg(feature = "parse")]
45macro_rules! from_lexical_with_options {
46    () => {
47        /// Trait for numerical types that can be parsed from bytes with custom options.
48        ///
49        /// The `Options` type specifies the configurable options to provide.
50        pub trait FromLexicalWithOptions: lexical_util::num::Number {
51            /// Custom formatting options for parsing a number.
52            type Options: lexical_util::options::ParseOptions;
53
54            /// Checked parser for a string-to-number conversion.
55            ///
56            /// This method parses the entire string, returning an error if
57            /// any invalid digits are found during parsing. The parsing
58            /// is dictated by the options, which specifies special
59            /// float strings, required float components, digit separators,
60            /// exponent characters, and more. Returns a `Result` containing
61            /// either the parsed value, or an error containing any errors
62            /// that occurred during parsing.
63            ///
64            /// * `FORMAT`  - Flags and characters designating the number grammar.
65            /// * `bytes`   - Slice containing a numeric string.
66            /// * `options` - Options to dictate number parsing.
67            ///
68            /// The `FORMAT` packed struct is built using [`NumberFormatBuilder`].
69            /// Any invalid number format will prevent parsing, returning
70            /// the appropriate format error. If you are unsure which format
71            /// to use, use [`STANDARD`].
72            ///
73            /// [`NumberFormatBuilder`]: lexical_util::format::NumberFormatBuilder
74            /// [`STANDARD`]: lexical_util::format::STANDARD
75            fn from_lexical_with_options<const FORMAT: u128>(
76                bytes: &[u8],
77                options: &Self::Options,
78            ) -> lexical_util::result::Result<Self>;
79
80            /// Checked parser for a string-to-number conversion.
81            ///
82            /// This method parses until an invalid digit is found (or the end
83            /// of the string), returning the number of processed digits
84            /// and the parsed value until that point. Returns a `Result`
85            /// containing either the parsed value and the number of
86            /// processed digits, or an error containing any errors that
87            /// occurred during parsing.
88            ///
89            /// * `FORMAT`  - Flags and characters designating the number grammar.
90            /// * `bytes`   - Slice containing a numeric string.
91            /// * `options` - Options to dictate number parsing.
92            ///
93            /// The `FORMAT` packed struct is built using [`NumberFormatBuilder`].
94            /// Any invalid number format will prevent parsing, returning
95            /// the appropriate format error. If you are unsure which format
96            /// to use, use [`STANDARD`].
97            ///
98            /// [`NumberFormatBuilder`]: lexical_util::format::NumberFormatBuilder
99            /// [`STANDARD`]: lexical_util::format::STANDARD
100            fn from_lexical_partial_with_options<const FORMAT: u128>(
101                bytes: &[u8],
102                options: &Self::Options,
103            ) -> lexical_util::result::Result<(Self, usize)>;
104        }
105    };
106}
107
108// TO LEXICAL
109
110/// Define ToLexical trait.
111#[macro_export]
112#[cfg(feature = "write")]
113macro_rules! to_lexical {
114    () => {
115        /// Trait for numerical types that can be serialized to bytes.
116        ///
117        /// To determine the number of bytes required to serialize a value to
118        /// string, check the associated constants from a required trait:
119        /// - [`FORMATTED_SIZE`]
120        /// - [`FORMATTED_SIZE_DECIMAL`]
121        ///
122        /// [`FORMATTED_SIZE`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE
123        /// [`FORMATTED_SIZE_DECIMAL`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE_DECIMAL
124        pub trait ToLexical:
125            lexical_util::constants::FormattedSize + lexical_util::num::Number
126        {
127            /// Serializer for a number-to-string conversion.
128            ///
129            /// Returns a subslice of the input buffer containing the written bytes,
130            /// starting from the same address in memory as the input slice.
131            ///
132            /// * `value`   - Number to serialize.
133            /// * `bytes`   - Buffer to write number to.
134            ///
135            /// # Safety
136            ///
137            /// Safe as long as the caller has provided a buffer of at least
138            /// [`FORMATTED_SIZE_DECIMAL`] elements. If a smaller buffer is
139            /// provided, a buffer overflow is very likely.
140            ///
141            /// [`FORMATTED_SIZE_DECIMAL`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE_DECIMAL
142            unsafe fn to_lexical_unchecked<'a>(self, bytes: &'a mut [u8]) -> &'a mut [u8];
143
144            /// Serializer for a number-to-string conversion.
145            ///
146            /// Returns a subslice of the input buffer containing the written bytes,
147            /// starting from the same address in memory as the input slice.
148            ///
149            /// * `value`   - Number to serialize.
150            /// * `bytes`   - Buffer to write number to.
151            ///
152            /// # Panics
153            ///
154            /// Panics if the buffer is not of sufficient size. The caller
155            /// must provide a slice of sufficient size. In order to ensure
156            /// the function will not panic, ensure the buffer has at least
157            /// [`FORMATTED_SIZE_DECIMAL`] elements.
158            ///
159            /// [`FORMATTED_SIZE_DECIMAL`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE_DECIMAL
160            fn to_lexical<'a>(self, bytes: &'a mut [u8]) -> &'a mut [u8];
161        }
162    };
163}
164
165/// Define ToLexicalWithOptions trait.
166#[macro_export]
167#[cfg(feature = "write")]
168macro_rules! to_lexical_with_options {
169    () => {
170        /// Trait for numerical types that can be serialized to bytes with custom options.
171        ///
172        /// To determine the number of bytes required to serialize a value to
173        /// string, check the associated constants from a required trait:
174        /// - [`FORMATTED_SIZE`]
175        /// - [`FORMATTED_SIZE_DECIMAL`]
176        ///
177        /// The `Options` type specifies the configurable options to provide.
178        ///
179        /// [`FORMATTED_SIZE`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE
180        /// [`FORMATTED_SIZE_DECIMAL`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE_DECIMAL
181        pub trait ToLexicalWithOptions:
182            lexical_util::constants::FormattedSize + lexical_util::num::Number
183        {
184            /// Custom formatting options for writing a number.
185            type Options: lexical_util::options::WriteOptions;
186
187            /// Serializer for a number-to-string conversion.
188            ///
189            /// Returns a subslice of the input buffer containing the written bytes,
190            /// starting from the same address in memory as the input slice.
191            ///
192            /// * `FORMAT`  - Flags and characters designating the number grammar.
193            /// * `value`   - Number to serialize.
194            /// * `bytes`   - Buffer to write number to.
195            /// * `options` - Options for number formatting.
196            ///
197            /// # Safety
198            ///
199            /// Safe as long as the caller has provided a buffer of at least
200            /// [`FORMATTED_SIZE`] elements. If a smaller buffer is provided, a
201            /// buffer overflow is very likely. If you are changing the
202            /// number significant digits written, the exponent break points,
203            /// or disabling scientific notation, you will need a larger buffer
204            /// than the one provided. An upper limit on the buffer size can
205            /// then be determined using [`WriteOptions::buffer_size`]. If you
206            /// are not using `min_significant_digits`, 1200 bytes is always
207            /// enough to hold the the output for a custom radix, and `400`
208            /// is always enough for decimal strings.
209            ///
210            /// # Panics
211            ///
212            /// **Floats Only**
213            ///
214            /// These panics are only when using uncommon features for float
215            /// writing, represent configuration errors, so runtime error
216            /// handling is not provided.
217            ///
218            /// Panics if the provided number format is invalid, or if the
219            /// mantissa radix is not equal to the exponent base
220            /// and the mantissa radix/exponent base combinations are
221            /// not in the following list:
222            ///
223            /// - `4, 2`
224            /// - `8, 2`
225            /// - `16, 2`
226            /// - `32, 2`
227            /// - `16, 4`
228            ///
229            /// Panics as well if the NaN or Inf string provided to the writer
230            /// is disabled, but the value provided is NaN or Inf, respectively.
231            ///
232            /// [`WriteOptions::buffer_size`]: lexical_util::options::WriteOptions::buffer_size
233            /// [`FORMATTED_SIZE`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE
234            unsafe fn to_lexical_with_options_unchecked<'a, const FORMAT: u128>(
235                self,
236                bytes: &'a mut [u8],
237                options: &Self::Options,
238            ) -> &'a mut [u8];
239
240            /// Serializer for a number-to-string conversion.
241            ///
242            /// Returns a subslice of the input buffer containing the written bytes,
243            /// starting from the same address in memory as the input slice.
244            ///
245            /// * `FORMAT`  - Flags and characters designating the number grammar.
246            /// * `value`   - Number to serialize.
247            /// * `bytes`   - Buffer to write number to.
248            /// * `options` - Options for number formatting.
249            ///
250            /// # Panics
251            ///
252            /// Panics if the buffer is not of sufficient size. The caller
253            /// must provide a slice of sufficient size. In order to ensure
254            /// the function will not panic, ensure the buffer has at least
255            /// [`FORMATTED_SIZE`] elements. If you are changing the
256            /// number significant digits written, the exponent break points,
257            /// or disabling scientific notation, you will need a larger buffer
258            /// than the one provided. An upper limit on the buffer size can
259            /// then be determined using [`WriteOptions::buffer_size`]. If you
260            /// are not using `min_significant_digits`, 1200 bytes is always
261            /// enough to hold the the output for a custom radix, and `400`
262            /// is always enough for decimal strings.
263            ///
264            /// **Floats Only**
265            ///
266            /// These panics are only when using uncommon features for float
267            /// writing, represent configuration errors, so runtime error
268            /// handling is not provided.
269            ///
270            /// Also panics if the provided number format is invalid, or
271            /// if the mantissa radix is not equal to the exponent base
272            /// and the mantissa radix/exponent base combinations are
273            /// not in the following list:
274            ///
275            /// - `4, 2`
276            /// - `8, 2`
277            /// - `16, 2`
278            /// - `32, 2`
279            /// - `16, 4`
280            ///
281            /// Panics as well if the NaN or Inf string provided to the writer
282            /// is disabled, but the value provided is NaN or Inf, respectively.
283            ///
284            /// [`WriteOptions::buffer_size`]: lexical_util::options::WriteOptions::buffer_size
285            /// [`FORMATTED_SIZE`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE
286            fn to_lexical_with_options<'a, const FORMAT: u128>(
287                self,
288                bytes: &'a mut [u8],
289                options: &Self::Options,
290            ) -> &'a mut [u8];
291        }
292    };
293}