lexical_core/lib.rs
1//! Fast lexical conversion routines for a no_std environment.
2//!
3//! lexical-core is a low-level API for number-to-string and
4//! string-to-number conversions, without requiring a system
5//! allocator. If you would like to use a high-level API that
6//! writes to and parses from `String` and `&str`, respectively,
7//! please look at [lexical](https://crates.io/crates/lexical)
8//! instead.
9//!
10//! Despite the low-level API and focus on performance, lexical-core
11//! strives to be simple and yet configurable: despite supporting nearly
12//! every float and integer format available, it only exports 4 write
13//! functions and 4 parse functions.
14//!
15//! lexical-core is well-tested, and has been downloaded more than 5 million
16//! times and currently has no known errors in correctness. lexical-core
17//! prioritizes performance above all else, and aims to be competitive
18//! or faster than any other float or integer parser and writer.
19//!
20//! In addition, despite having a large number of features, configurability,
21//! and a focus on performance, we also strive for fast compile times.
22//! Recent versions also add support for smaller binary sizes, as well
23//! ideal for embedded or web environments, where executable bloat can
24//! be much more detrimental than performance.
25//!
26//! # Getting Started
27//!
28//! ```rust
29//! # #[cfg(all(
30//! # feature = "parse-floats",
31//! # feature = "parse-integers",
32//! # feature = "write-floats",
33//! # feature = "write-integers",
34//! # ))]
35//! # {
36//!
37//! // String to number using Rust slices.
38//! // The argument is the byte string parsed.
39//! let f: f32 = lexical_core::parse(b"3.5").unwrap(); // 3.5
40//! let i: i32 = lexical_core::parse(b"15").unwrap(); // 15
41//!
42//! // All lexical_core parsers are checked, they validate the
43//! // input data is entirely correct, and stop parsing when invalid data
44//! // is found, or upon numerical overflow.
45//! let r = lexical_core::parse::<u8>(b"256"); // Err(ErrorCode::Overflow.into())
46//! let r = lexical_core::parse::<u8>(b"1a5"); // Err(ErrorCode::InvalidDigit.into())
47//!
48//! // In order to extract and parse a number from a substring of the input
49//! // data, use `parse_partial`. These functions return the parsed value and
50//! // the number of processed digits, allowing you to extract and parse the
51//! // number in a single pass.
52//! let r = lexical_core::parse_partial::<i8>(b"3a5"); // Ok((3, 1))
53//!
54//! // If an insufficiently long buffer is passed, the serializer will panic.
55//!
56//! // PANICS
57//! let mut buf = [b'0'; 1];
58//! //let slc = lexical_core::write::<i64>(15, &mut buf);
59//!
60//! // In order to guarantee the buffer is long enough, always ensure there
61//! // are at least `T::FORMATTED_SIZE` bytes, which requires the
62//! // `lexical_core::FormattedSize` trait to be in scope.
63//! use lexical_core::FormattedSize;
64//! let mut buf = [b'0'; f64::FORMATTED_SIZE];
65//! let slc = lexical_core::write::<f64>(15.1, &mut buf);
66//! assert_eq!(slc, b"15.1");
67//!
68//! // When the `radix` feature is enabled, for decimal floats, using
69//! // `T::FORMATTED_SIZE` may significantly overestimate the space
70//! // required to format the number. Therefore, the
71//! // `T::FORMATTED_SIZE_DECIMAL` constants allow you to get a much
72//! // tighter bound on the space required.
73//! let mut buf = [b'0'; f64::FORMATTED_SIZE_DECIMAL];
74//! let slc = lexical_core::write::<f64>(15.1, &mut buf);
75//! assert_eq!(slc, b"15.1");
76//! # }
77//! ```
78//!
79//! # Conversion API
80//!
81#![cfg_attr(feature = "write", doc = " **Write**")]
82#![cfg_attr(feature = "write", doc = "")]
83#![cfg_attr(feature = "write", doc = " - [`write`]")]
84#![cfg_attr(feature = "write", doc = " - [`write_unchecked`]")]
85#![cfg_attr(feature = "write", doc = " - [`write_with_options`]")]
86#![cfg_attr(feature = "write", doc = " - [`write_with_options_unchecked`]")]
87//!
88#![cfg_attr(feature = "write", doc = " **From String**")]
89#![cfg_attr(feature = "write", doc = "")]
90#![cfg_attr(feature = "parse", doc = " - [`parse`]")]
91#![cfg_attr(feature = "parse", doc = " - [`parse_partial`]")]
92#![cfg_attr(feature = "parse", doc = " - [`parse_with_options`]")]
93#![cfg_attr(feature = "parse", doc = " - [`parse_partial_with_options`]")]
94//!
95//! # Features
96//!
97//! In accordance with the Rust ethos, all features are additive: the crate
98//! may be build with `--all-features` without issue. The following features are enabled
99//! by default:
100//!
101//! * `std`
102//! * `write-integers`
103//! * `write-floats`
104//! * `parse-integers`
105//! * `parse-floats`
106//!
107//! A complete description of supported features includes:
108//!
109//! ### std
110//!
111//! Enable use of the standard library. Currently, the standard library
112//! is not used for any functionality, and may be disabled without any
113//! change in functionality on stable.
114//!
115//! ### write-integers
116//!
117//! Enable support for writing integers to string.
118//!
119//! ### write-floats
120//!
121//! Enable support for writing floating-point numbers to string.
122//!
123//! ### parse-integers
124//!
125//! Enable support for parsing integers from string.
126//!
127//! ### parsing-floats
128//!
129//! Enable support for parsing floating-point numbers from string.
130//!
131//! ### format
132//!
133//! Adds support for the entire format API (using [`NumberFormatBuilder`]).
134//! This allows extensive configurability for parsing and writing numbers
135//! in custom formats, with different valid syntax requirements.
136//!
137//! For example, in JSON, the following floats are valid or invalid:
138//!
139//! ```text
140//! -1 // valid
141//! +1 // invalid
142//! 1 // valid
143//! 1. // invalid
144//! .1 // invalid
145//! 0.1 // valid
146//! nan // invalid
147//! inf // invalid
148//! Infinity // invalid
149//! ```
150//!
151//! All of the finite numbers are valid in Rust, and Rust provides constants
152//! for non-finite floats. In order to parse standard-conforming JSON floats
153//! using lexical, you may use the following approach:
154//!
155//! ```rust
156//! # #[cfg(all(feature = "parse-floats", feature = "format"))] {
157//! use lexical_core::{format, parse_with_options, ParseFloatOptions, Result};
158//!
159//! fn parse_json_float<Bytes: AsRef<[u8]>>(bytes: Bytes) -> Result<f64> {
160//! let options = ParseFloatOptions::new();
161//! parse_with_options::<_, { format::JSON }>(bytes.as_ref(), &options)
162//! }
163//! # }
164//! ```
165//!
166//! See the [Number Format](#number-format) section below for more information.
167//!
168//! ### power-of-two
169//!
170//! Enable doing numeric conversions to and from strings with power-of-two
171//! radixes. This avoids most of the overhead and binary bloat of the radix
172//! feature, while enabling support for the most commonly-used radixes.
173//!
174//! ### radix
175//!
176//! Enable doing numeric conversions to and from strings for all radixes.
177//! This requires substantially more static storage than `power-of-two`,
178//! and increases compile times by a fair amount, but can be quite useful
179//! for esoteric programming languages which use duodecimal floats, for
180//! example.
181//!
182//! ### compact
183//!
184//! Reduce the generated code size at the cost of performance. This minimizes
185//! the number of static tables, inlining, and generics used, drastically
186//! reducing the size of the generated binaries.
187//!
188//! ### safe
189//!
190//! All numeric parsers are memory-safe by default, since parsing complex
191//! input is a major source of memory vulnerabilities. However, numeric
192//! writers often opt-in for unchecked writes, for major performance
193//! improvements. This may be disabled entirely by enabling the `safe`
194//! feature. In addition, to simplify memory safety guarantees, extensive
195//! edge-cases, property-based tests, and fuzzing is done with both the
196//! safe feature enabled and disabled, with the tests verified by Miri
197//! and Valgrind.
198//!
199//! # Configuration API
200//!
201//! Lexical provides two main levels of configuration:
202//! - The [`NumberFormatBuilder`], creating a packed struct with custom
203//! formatting options.
204//! - The Options API.
205//!
206//! ## Number Format
207//!
208//! The number format class provides numerous flags to specify
209//! number parsing or writing. When the `power-of-two` feature is
210//! enabled, additional flags are added:
211//! - The radix for the significant digits (default `10`).
212//! - The radix for the exponent base (default `10`).
213//! - The radix for the exponent digits (default `10`).
214//!
215//! When the `format` feature is enabled, numerous other syntax and
216//! digit separator flags are enabled, including:
217//! - A digit separator character, to group digits for increased legibility.
218//! - Whether leading, trailing, internal, and consecutive digit separators are allowed.
219//! - Toggling required float components, such as digits before the decimal point.
220//! - Toggling whether special floats are allowed or are case-sensitive.
221//!
222//! Many pre-defined constants therefore exist to simplify common use-cases,
223//! including:
224//! - JSON, XML, TOML, YAML, SQLite, and many more.
225//! - Rust, Python, C#, FORTRAN, COBOL literals and strings, and many more.
226//!
227//! ## Options API
228//!
229//! The Options API provides high-level options to specify number parsing
230//! or writing, options not intrinsically tied to a number format.
231//! For example, the Options API provides:
232//! - The exponent character (default `b'e'`, or `b'^'`).
233//! - The decimal point character (default `b'.'`).
234//! - Custom `NaN`, `Infinity` string representations.
235//! - Whether to trim the fraction component from integral floats.
236//! - The exponent break point for scientific notation.
237//! - The maximum and minimum number of significant digits to write.
238//! - The rounding mode when truncating significant digits while writing.
239//!
240//! The available options are:
241//!
242#![cfg_attr(feature = "parse-floats", doc = " - [`ParseFloatOptions`]")]
243#![cfg_attr(feature = "parse-integers", doc = " - [`ParseIntegerOptions`]")]
244#![cfg_attr(feature = "write-floats", doc = " - [`WriteFloatOptions`]")]
245#![cfg_attr(feature = "write-integers", doc = " - [`WriteIntegerOptions`]")]
246//!
247//! In addition, pre-defined constants for each category of options may
248//! be found in their respective modules.
249//!
250//! ## Example
251//!
252//! An example of creating your own options to parse European-style
253//! numbers (which use commas as decimal points, and periods as digit
254//! separators) is as follows:
255//!
256//! ```
257//! # pub fn main() {
258//! # #[cfg(all(feature = "parse_floats", feature = "format"))] {
259//! // This creates a format to parse a European-style float number.
260//! // The decimal point is a comma, and the digit separators (optional)
261//! // are periods.
262//! const EUROPEAN: u128 = lexical_core::NumberFormatBuilder::new()
263//! .digit_separator(b'.')
264//! .build();
265//! let options = lexical_core::ParseFloatOptions::builder()
266//! .decimal_point(b',')
267//! .build()
268//! .unwrap();
269//! assert_eq!(
270//! lexical_core::parse_with_options::<f32, EUROPEAN>(b"300,10", &options),
271//! Ok(300.10)
272//! );
273//!
274//! // Another example, using a pre-defined constant for JSON.
275//! const JSON: u128 = lexical_core::format::JSON;
276//! let options = lexical_core::ParseFloatOptions::new();
277//! assert_eq!(
278//! lexical_core::parse_with_options::<f32, JSON>(b"0e1", &options),
279//! Ok(0.0)
280//! );
281//! assert_eq!(
282//! lexical_core::parse_with_options::<f32, JSON>(b"1E+2", &options),
283//! Ok(100.0)
284//! );
285//! # }
286//! # }
287//! ```
288//!
289//! # Algorithms
290//!
291//! - [Parsing Floats](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-float/docs/Algorithm.md)
292//! - [Parsing Integers](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-integer/docs/Algorithm.md)
293//! - [Writing Floats](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-float/docs/Algorithm.md)
294//! - [Writing Integers](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-integer/docs/Algorithm.md)
295//!
296//! # Benchmarks
297//!
298//! - [Parsing Floats](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-float/docs/Benchmarks.md)
299//! - [Parsing Integers](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-integer/docs/Benchmarks.md)
300//! - [Writing Floats](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-float/docs/Benchmarks.md)
301//! - [Writing Integers](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-integer/docs/Benchmarks.md)
302//!
303//! # Design
304//!
305//! - [Binary Size](https://github.com/Alexhuszagh/rust-lexical/blob/main/docs/BinarySize.md)
306//! - [Build Timings](https://github.com/Alexhuszagh/rust-lexical/blob/main/docs/BuildTimings.md)
307//! - [Digit Separators](https://github.com/Alexhuszagh/rust-lexical/blob/main/docs/DigitSeparators.md)
308//!
309//! # Version Support
310//!
311//! The minimum, standard, required version is 1.51.0, for const generic
312//! support. Older versions of lexical support older Rust versions.
313//!
314//! [`write`]: crate::write
315//! [`write_unchecked`]: crate::write_unchecked
316//! [`write_with_options`]: crate::write_with_options
317//! [`write_with_options_unchecked`]: crate::write_with_options_unchecked
318//! [`parse`]: crate::parse
319//! [`parse_partial`]: crate::parse_partial
320//! [`parse_with_options`]: crate::parse_with_options
321//! [`parse_partial_with_options`]: crate::parse_partial_with_options
322//!
323//! [`NumberFormatBuilder`]: crate::NumberFormatBuilder
324//! [`ParseFloatOptions`]: crate::ParseFloatOptions
325//! [`ParseIntegerOptions`]: crate::ParseIntegerOptions
326//! [`WriteFloatOptions`]: crate::WriteFloatOptions
327//! [`WriteIntegerOptions`]: crate::WriteIntegerOptions
328
329// We want to have the same safety guarantees as Rust core,
330// so we allow unused unsafe to clearly document safety guarantees.
331#![allow(unused_unsafe)]
332#![cfg_attr(feature = "lint", warn(unsafe_op_in_unsafe_fn))]
333#![cfg_attr(not(feature = "std"), no_std)]
334
335#[cfg(feature = "parse-floats")]
336use lexical_parse_float::{
337 FromLexical as FromFloat,
338 FromLexicalWithOptions as FromFloatWithOptions,
339};
340#[cfg(feature = "parse-integers")]
341use lexical_parse_integer::{
342 FromLexical as FromInteger,
343 FromLexicalWithOptions as FromIntegerWithOptions,
344};
345#[cfg(feature = "parse")]
346use lexical_util::{from_lexical, from_lexical_with_options};
347#[cfg(feature = "write")]
348use lexical_util::{to_lexical, to_lexical_with_options};
349#[cfg(feature = "write-floats")]
350use lexical_write_float::{ToLexical as ToFloat, ToLexicalWithOptions as ToFloatWithOptions};
351#[cfg(feature = "write-integers")]
352use lexical_write_integer::{ToLexical as ToInteger, ToLexicalWithOptions as ToIntegerWithOptions};
353
354// Re-exports
355#[cfg(feature = "parse-floats")]
356pub use lexical_parse_float::{
357 options as parse_float_options,
358 Options as ParseFloatOptions,
359 OptionsBuilder as ParseFloatOptionsBuilder,
360};
361#[cfg(feature = "parse-integers")]
362pub use lexical_parse_integer::{
363 options as parse_integer_options,
364 Options as ParseIntegerOptions,
365 OptionsBuilder as ParseIntegerOptionsBuilder,
366};
367#[cfg(feature = "f16")]
368pub use lexical_util::bf16::bf16;
369#[cfg(feature = "write")]
370pub use lexical_util::constants::{FormattedSize, BUFFER_SIZE};
371#[cfg(feature = "parse")]
372pub use lexical_util::error::Error;
373#[cfg(feature = "f16")]
374pub use lexical_util::f16::f16;
375pub use lexical_util::format::{self, format_error, format_is_valid, NumberFormatBuilder};
376#[cfg(feature = "parse")]
377pub use lexical_util::options::ParseOptions;
378#[cfg(feature = "write")]
379pub use lexical_util::options::WriteOptions;
380#[cfg(feature = "parse")]
381pub use lexical_util::result::Result;
382#[cfg(feature = "write-floats")]
383pub use lexical_write_float::{
384 options as write_float_options,
385 Options as WriteFloatOptions,
386 OptionsBuilder as WriteFloatOptionsBuilder,
387};
388#[cfg(feature = "write-integers")]
389pub use lexical_write_integer::{
390 options as write_integer_options,
391 Options as WriteIntegerOptions,
392 OptionsBuilder as WriteIntegerOptionsBuilder,
393};
394
395// API
396// ---
397
398#[cfg(feature = "parse")]
399from_lexical!();
400#[cfg(feature = "parse")]
401from_lexical_with_options!();
402#[cfg(feature = "write")]
403to_lexical!();
404#[cfg(feature = "write")]
405to_lexical_with_options!();
406
407/// Implement `FromLexical` and `FromLexicalWithOptions` for numeric type.
408#[cfg(feature = "parse")]
409macro_rules! from_lexical_impl {
410 ($t:ident, $from:ident, $from_options:ident, $options:ident) => {
411 impl FromLexical for $t {
412 #[cfg_attr(not(feature = "compact"), inline)]
413 fn from_lexical(bytes: &[u8]) -> Result<Self> {
414 <Self as $from>::from_lexical(bytes)
415 }
416
417 #[cfg_attr(not(feature = "compact"), inline)]
418 fn from_lexical_partial(bytes: &[u8]) -> Result<(Self, usize)> {
419 <Self as $from>::from_lexical_partial(bytes)
420 }
421 }
422
423 impl FromLexicalWithOptions for $t {
424 type Options = $options;
425
426 #[cfg_attr(not(feature = "compact"), inline)]
427 fn from_lexical_with_options<const FORMAT: u128>(
428 bytes: &[u8],
429 options: &Self::Options,
430 ) -> Result<Self> {
431 <Self as $from_options>::from_lexical_with_options::<FORMAT>(bytes, options)
432 }
433
434 #[cfg_attr(not(feature = "compact"), inline)]
435 fn from_lexical_partial_with_options<const FORMAT: u128>(
436 bytes: &[u8],
437 options: &Self::Options,
438 ) -> Result<(Self, usize)> {
439 <Self as $from_options>::from_lexical_partial_with_options::<FORMAT>(bytes, options)
440 }
441 }
442 };
443}
444
445/// Implement `FromLexical` and `FromLexicalWithOptions` for integers.
446#[cfg(feature = "parse-integers")]
447macro_rules! integer_from_lexical {
448 ($($t:ident)*) => ($(
449 from_lexical_impl!($t, FromInteger, FromIntegerWithOptions, ParseIntegerOptions);
450 )*);
451}
452
453#[cfg(feature = "parse-integers")]
454integer_from_lexical! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
455
456/// Implement `FromLexical` and `FromLexicalWithOptions` for floats.
457#[cfg(feature = "parse-floats")]
458macro_rules! float_from_lexical {
459 ($($t:ident)*) => ($(
460 from_lexical_impl!($t, FromFloat, FromFloatWithOptions, ParseFloatOptions);
461 )*);
462}
463
464#[cfg(feature = "parse-floats")]
465float_from_lexical! { f32 f64 }
466
467// Implement ToLexical for numeric type.
468#[cfg(feature = "write")]
469macro_rules! to_lexical_impl {
470 ($t:ident, $to:ident, $to_options:ident, $options:ident) => {
471 impl ToLexical for $t {
472 #[cfg_attr(not(feature = "compact"), inline)]
473 unsafe fn to_lexical_unchecked<'a>(self, bytes: &'a mut [u8]) -> &'a mut [u8] {
474 // SAFETY: safe as long as `bytes` is large enough to hold the significant digits.
475 unsafe { <Self as $to>::to_lexical_unchecked(self, bytes) }
476 }
477
478 #[cfg_attr(not(feature = "compact"), inline)]
479 fn to_lexical<'a>(self, bytes: &'a mut [u8]) -> &'a mut [u8] {
480 <Self as $to>::to_lexical(self, bytes)
481 }
482 }
483
484 impl ToLexicalWithOptions for $t {
485 type Options = $options;
486
487 #[cfg_attr(not(feature = "compact"), inline)]
488 unsafe fn to_lexical_with_options_unchecked<'a, const FORMAT: u128>(
489 self,
490 bytes: &'a mut [u8],
491 options: &Self::Options,
492 ) -> &'a mut [u8] {
493 // SAFETY: safe as long as `bytes` is large enough to hold the significant digits.
494 unsafe {
495 <Self as $to_options>::to_lexical_with_options_unchecked::<FORMAT>(
496 self, bytes, options,
497 )
498 }
499 }
500
501 #[cfg_attr(not(feature = "compact"), inline)]
502 fn to_lexical_with_options<'a, const FORMAT: u128>(
503 self,
504 bytes: &'a mut [u8],
505 options: &Self::Options,
506 ) -> &'a mut [u8] {
507 <Self as $to_options>::to_lexical_with_options::<FORMAT>(self, bytes, options)
508 }
509 }
510 };
511}
512
513/// Implement `ToLexical` and `ToLexicalWithOptions` for integers.
514#[cfg(feature = "write-integers")]
515macro_rules! integer_to_lexical {
516 ($($t:ident)*) => ($(
517 to_lexical_impl!($t, ToInteger, ToIntegerWithOptions, WriteIntegerOptions);
518 )*);
519}
520
521#[cfg(feature = "write-integers")]
522integer_to_lexical! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
523
524/// Implement `ToLexical` and `ToLexicalWithOptions` for floats.
525#[cfg(feature = "write-floats")]
526macro_rules! float_to_lexical {
527 ($($t:ident)*) => ($(
528 to_lexical_impl!($t, ToFloat, ToFloatWithOptions, WriteFloatOptions);
529 )*);
530}
531
532#[cfg(feature = "write-floats")]
533float_to_lexical! { f32 f64 }
534
535/// Write number to string.
536///
537/// Returns a subslice of the input buffer containing the written bytes,
538/// starting from the same address in memory as the input slice.
539///
540/// * `value` - Number to serialize.
541/// * `bytes` - Buffer to write number to.
542///
543/// # Panics
544///
545/// Panics if the buffer may not be large enough to hold the serialized
546/// number. In order to ensure the function will not panic, provide a
547/// buffer with at least `{integer}::FORMATTED_SIZE` elements.
548///
549/// # Example
550///
551/// ```
552/// # pub fn main() {
553/// #[cfg(feature = "write-floats")] {
554/// // import `BUFFER_SIZE` to get the maximum bytes written by the number.
555/// use lexical_core::BUFFER_SIZE;
556///
557/// let mut buffer = [0u8; BUFFER_SIZE];
558/// let float = 3.14159265359_f32;
559///
560/// lexical_core::write(float, &mut buffer);
561///
562/// assert_eq!(&buffer[0..9], b"3.1415927");
563/// # }
564/// # }
565/// ```
566///
567/// This will panic, because the buffer is not large enough:
568///
569/// ```should_panic
570/// # #[cfg(feature = "write-floats")] {
571/// // note: the buffer is only one byte large
572/// let mut buffer = [0u8; 1];
573/// let float = 3.14159265359_f32;
574///
575/// lexical_core::write(float, &mut buffer);
576/// # }
577/// # #[cfg(not(feature = "write-floats"))] {
578/// # panic!("");
579/// # }
580/// ```
581#[inline]
582#[cfg(feature = "write")]
583pub fn write<N: ToLexical>(n: N, bytes: &mut [u8]) -> &mut [u8] {
584 n.to_lexical(bytes)
585}
586
587/// Write number to string, without bounds checking the buffer.
588///
589/// Returns a subslice of the input buffer containing the written bytes,
590/// starting from the same address in memory as the input slice.
591///
592/// * `value` - Number to serialize.
593/// * `bytes` - Buffer to write number to.
594///
595/// # Safety
596///
597/// If the buffer is not be large enough to hold the serialized number,
598/// it will overflow the buffer unless the `safe` feature is enabled.
599/// Buffer overflows are severe security vulnerabilities, and therefore
600/// to ensure the function will not overwrite the buffer, provide a
601/// buffer with at least `{integer}::FORMATTED_SIZE` elements.
602///
603/// # Example
604///
605/// ```
606/// # pub fn main() {
607/// #[cfg(feature = "write-floats")] {
608/// // import `BUFFER_SIZE` to get the maximum bytes written by the number.
609/// use lexical_core::BUFFER_SIZE;
610///
611/// let mut buffer = [0u8; BUFFER_SIZE];
612/// let float = 3.14159265359_f32;
613///
614/// unsafe {
615/// lexical_core::write_unchecked(float, &mut buffer);
616/// }
617///
618/// assert_eq!(&buffer[0..9], b"3.1415927");
619/// # }
620/// # }
621/// ```
622#[inline]
623#[cfg(feature = "write")]
624pub unsafe fn write_unchecked<N: ToLexical>(n: N, bytes: &mut [u8]) -> &mut [u8] {
625 // SAFETY: safe if the provided buffer is large enough for the numerical string
626 unsafe { n.to_lexical_unchecked(bytes) }
627}
628
629/// Write number to string with custom options.
630///
631/// Returns a subslice of the input buffer containing the written bytes,
632/// starting from the same address in memory as the input slice.
633///
634/// * `FORMAT` - Packed struct containing the number format.
635/// * `value` - Number to serialize.
636/// * `bytes` - Buffer to write number to.
637/// * `options` - Options to customize number parsing.
638///
639/// # Panics
640///
641/// Panics if the buffer may not be large enough to hold the serialized
642/// number. In order to ensure the function will not panic, provide a
643/// buffer with at least `{integer}::FORMATTED_SIZE` elements. If you
644/// are using custom digit precision control or exponent break points
645/// for writing floats, these constants may be insufficient to store
646/// the serialized number, and up to 1200 bytes may be required with
647/// radix support.
648///
649/// If the provided `FORMAT` is not valid, the function may panic. Please
650/// ensure `is_valid()` is called prior to using the format, or checking
651/// its validity using a static assertion.
652///
653/// # Example
654///
655/// ```
656/// # pub fn main() {
657/// #[cfg(feature = "write-floats")] {
658/// // import `BUFFER_SIZE` to get the maximum bytes written by the number.
659/// use lexical_core::BUFFER_SIZE;
660///
661/// let mut buffer = [0u8; BUFFER_SIZE];
662/// let float = 3.14159265359_f32;
663///
664/// const FORMAT: u128 = lexical_core::format::STANDARD;
665/// let options = lexical_core::WriteFloatOptions::new();
666/// lexical_core::write_with_options::<_, FORMAT>(float, &mut buffer, &options);
667///
668/// assert_eq!(&buffer[0..9], b"3.1415927");
669/// # }
670/// # }
671/// ```
672///
673/// This will panic, because the buffer is not large enough:
674///
675/// ```should_panic
676/// # #[cfg(feature = "write-floats")] {
677/// // note: the buffer is only one byte large
678/// let mut buffer = [0u8; 1];
679/// let float = 3.14159265359_f32;
680///
681/// const FORMAT: u128 = lexical_core::format::STANDARD;
682/// let options = lexical_core::WriteFloatOptions::new();
683/// lexical_core::write_with_options::<_, FORMAT>(float, &mut buffer, &options);
684/// # }
685/// # #[cfg(not(feature = "write-floats"))] {
686/// # panic!("");
687/// # }
688/// ```
689#[inline]
690#[cfg(feature = "write")]
691pub fn write_with_options<'a, N: ToLexicalWithOptions, const FORMAT: u128>(
692 n: N,
693 bytes: &'a mut [u8],
694 options: &N::Options,
695) -> &'a mut [u8] {
696 n.to_lexical_with_options::<FORMAT>(bytes, options)
697}
698
699/// Write number to string with custom options.
700///
701/// Returns a subslice of the input buffer containing the written bytes,
702/// starting from the same address in memory as the input slice.
703///
704/// * `FORMAT` - Packed struct containing the number format.
705/// * `value` - Number to serialize.
706/// * `bytes` - Buffer to write number to.
707/// * `options` - Options to customize number parsing.
708///
709/// # Safety
710///
711/// If the buffer is not be large enough to hold the serialized number,
712/// it will overflow the buffer unless the `safe` feature is enabled.
713/// Buffer overflows are severe security vulnerabilities, and therefore
714/// to ensure the function will not overwrite the buffer, provide a
715/// buffer with at least `{integer}::FORMATTED_SIZE` elements. If you
716/// are using custom digit precision control or exponent break points
717/// for writing floats, these constants may be insufficient to store
718/// the serialized number, and up to 1200 bytes may be required with
719/// radix support.
720///
721/// # Panics
722///
723/// If the provided `FORMAT` is not valid, the function may panic. Please
724/// ensure `is_valid()` is called prior to using the format, or checking
725/// its validity using a static assertion.
726///
727/// # Example
728///
729/// ```
730/// # pub fn main() {
731/// #[cfg(feature = "write-floats")] {
732/// // import `BUFFER_SIZE` to get the maximum bytes written by the number.
733/// use lexical_core::BUFFER_SIZE;
734///
735/// let mut buffer = [0u8; BUFFER_SIZE];
736/// let float = 3.14159265359_f32;
737///
738/// const FORMAT: u128 = lexical_core::format::STANDARD;
739/// let options = lexical_core::WriteFloatOptions::new();
740/// unsafe {
741/// lexical_core::write_with_options_unchecked::<_, FORMAT>(float, &mut buffer, &options);
742/// }
743///
744/// assert_eq!(&buffer[0..9], b"3.1415927");
745/// # }
746/// # }
747/// ```
748#[inline]
749#[cfg(feature = "write")]
750pub unsafe fn write_with_options_unchecked<'a, N: ToLexicalWithOptions, const FORMAT: u128>(
751 n: N,
752 bytes: &'a mut [u8],
753 options: &N::Options,
754) -> &'a mut [u8] {
755 // SAFETY: safe if the provided buffer is large enough for the numerical string
756 unsafe { n.to_lexical_with_options_unchecked::<FORMAT>(bytes, options) }
757}
758
759/// Parse complete number from string.
760///
761/// This method parses the entire string, returning an error if
762/// any invalid digits are found during parsing.
763///
764/// * `bytes` - Byte slice containing a numeric string.
765///
766/// # Example
767///
768/// ```
769/// # pub fn main() {
770/// #[cfg(feature = "parse-floats")] {
771/// let string = "3.14159265359";
772/// let result = lexical_core::parse::<f32>(string.as_bytes());
773/// assert_eq!(result, Ok(3.14159265359_f32));
774/// # }
775/// # }
776/// ```
777#[inline]
778#[cfg(feature = "parse")]
779pub fn parse<N: FromLexical>(bytes: &[u8]) -> Result<N> {
780 N::from_lexical(bytes)
781}
782
783/// Parse partial number from string.
784///
785/// This method parses until an invalid digit is found (or the end
786/// of the string), returning the number of processed digits
787/// and the parsed value until that point.
788///
789/// * `bytes` - Byte slice containing a numeric string.
790///
791/// # Example
792///
793/// ```
794/// # pub fn main() {
795/// #[cfg(feature = "parse-floats")] {
796/// let string = "3.14159265359 hello";
797/// let result = lexical_core::parse_partial::<f32>(string.as_bytes());
798/// assert_eq!(result, Ok((3.14159265359_f32, 13)));
799/// # }
800/// # }
801/// ```
802#[inline]
803#[cfg(feature = "parse")]
804pub fn parse_partial<N: FromLexical>(bytes: &[u8]) -> Result<(N, usize)> {
805 N::from_lexical_partial(bytes)
806}
807
808/// Parse complete number from string with custom parsing options.
809///
810/// This method parses the entire string, returning an error if
811/// any invalid digits are found during parsing.
812///
813/// * `FORMAT` - Packed struct containing the number format.
814/// * `bytes` - Byte slice containing a numeric string.
815/// * `options` - Options to customize number parsing.
816///
817/// # Example
818///
819/// ```
820/// # pub fn main() {
821/// #[cfg(all(feature = "parse-floats", feature = "format"))] {
822/// const JSON: u128 = lexical_core::format::JSON;
823/// let options = lexical_core::ParseFloatOptions::new();
824/// let string = "3.14159265359";
825/// let result = lexical_core::parse_with_options::<f32, JSON>(string.as_bytes(), &options);
826/// assert_eq!(result, Ok(3.14159265359_f32));
827/// # }
828/// # }
829/// ```
830#[inline]
831#[cfg(feature = "parse")]
832pub fn parse_with_options<N: FromLexicalWithOptions, const FORMAT: u128>(
833 bytes: &[u8],
834 options: &N::Options,
835) -> Result<N> {
836 N::from_lexical_with_options::<FORMAT>(bytes, options)
837}
838
839/// Parse partial number from string with custom parsing options.
840///
841/// This method parses until an invalid digit is found (or the end
842/// of the string), returning the number of processed digits
843/// and the parsed value until that point.
844///
845/// * `FORMAT` - Packed struct containing the number format.
846/// * `bytes` - Byte slice containing a numeric string.
847/// * `options` - Options to customize number parsing.
848///
849/// # Example
850///
851/// ```
852/// # pub fn main() {
853/// #[cfg(all(feature = "parse-floats", feature = "format"))] {
854/// const JSON: u128 = lexical_core::format::JSON;
855/// let options = lexical_core::ParseFloatOptions::new();
856/// let string = "3.14159265359 hello";
857/// let result = lexical_core::parse_partial_with_options::<f32, JSON>(string.as_bytes(), &options);
858/// assert_eq!(result, Ok((3.14159265359_f32, 13)));
859/// # }
860/// # }
861/// ```
862#[inline]
863#[cfg(feature = "parse")]
864pub fn parse_partial_with_options<N: FromLexicalWithOptions, const FORMAT: u128>(
865 bytes: &[u8],
866 options: &N::Options,
867) -> Result<(N, usize)> {
868 N::from_lexical_partial_with_options::<FORMAT>(bytes, options)
869}