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}