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 /// # Panics
136 ///
137 /// Panics if the buffer is not of sufficient size. The caller
138 /// must provide a slice of sufficient size. In order to ensure
139 /// the function will not panic, ensure the buffer has at least
140 /// [`FORMATTED_SIZE_DECIMAL`] elements.
141 ///
142 /// [`FORMATTED_SIZE_DECIMAL`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE_DECIMAL
143 fn to_lexical<'a>(self, bytes: &'a mut [u8]) -> &'a mut [u8];
144 }
145 };
146}
147
148/// Define `ToLexicalWithOptions` trait.
149#[macro_export]
150#[cfg(feature = "write")]
151macro_rules! to_lexical_with_options {
152 () => {
153 /// Trait for numerical types that can be serialized to bytes with custom
154 /// options.
155 ///
156 /// To determine the number of bytes required to serialize a value to
157 /// string, check the associated constants from a required trait:
158 /// - [`FORMATTED_SIZE`]
159 /// - [`FORMATTED_SIZE_DECIMAL`]
160 ///
161 /// The `Options` type specifies the configurable options to provide.
162 ///
163 /// [`FORMATTED_SIZE`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE
164 /// [`FORMATTED_SIZE_DECIMAL`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE_DECIMAL
165 pub trait ToLexicalWithOptions:
166 lexical_util::constants::FormattedSize + lexical_util::num::Number
167 {
168 /// Custom formatting options for writing a number.
169 type Options: lexical_util::options::WriteOptions;
170
171 /// Serializer for a number-to-string conversion.
172 ///
173 /// Returns a subslice of the input buffer containing the written bytes,
174 /// starting from the same address in memory as the input slice.
175 ///
176 /// * `FORMAT` - Flags and characters designating the number grammar.
177 /// * `value` - Number to serialize.
178 /// * `bytes` - Buffer to write number to.
179 /// * `options` - Options for number formatting.
180 ///
181 /// # Panics
182 ///
183 /// Panics if the buffer is not of sufficient size. The caller
184 /// must provide a slice of sufficient size. In order to ensure
185 /// the function will not panic, ensure the buffer has at least
186 /// [`FORMATTED_SIZE`] elements. If you are changing the
187 /// number significant digits written, the exponent break points,
188 /// or disabling scientific notation, you will need a larger buffer
189 /// than the one provided. An upper limit on the buffer size can
190 /// then be determined using [`WriteOptions::buffer_size`]. If you
191 /// are not using `min_significant_digits`, 1200 bytes is always
192 /// enough to hold the the output for a custom radix, and `400`
193 /// is always enough for decimal strings.
194 ///
195 /// **Floats Only**
196 ///
197 /// These panics are only when using uncommon features for float
198 /// writing, represent configuration errors, so runtime error
199 /// handling is not provided.
200 ///
201 /// Also panics if the provided number format is invalid, or
202 /// if the mantissa radix is not equal to the exponent base
203 /// and the mantissa radix/exponent base combinations are
204 /// not in the following list:
205 ///
206 /// - `4, 2`
207 /// - `8, 2`
208 /// - `16, 2`
209 /// - `32, 2`
210 /// - `16, 4`
211 ///
212 /// Panics as well if the NaN or Inf string provided to the writer
213 /// is disabled, but the value provided is NaN or Inf, respectively.
214 ///
215 /// [`WriteOptions::buffer_size`]: lexical_util::options::WriteOptions::buffer_size
216 /// [`FORMATTED_SIZE`]: lexical_util::constants::FormattedSize::FORMATTED_SIZE
217 fn to_lexical_with_options<'a, const FORMAT: u128>(
218 self,
219 bytes: &'a mut [u8],
220 options: &Self::Options,
221 ) -> &'a mut [u8];
222 }
223 };
224}