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#![cfg_attr(feature = "write", doc = " **Write**")]
81#![cfg_attr(feature = "write", doc = "")]
82#![cfg_attr(feature = "write", doc = " - [`write`]")]
83#![cfg_attr(feature = "write", doc = " - [`write_with_options`]")]
84//!
85#![cfg_attr(feature = "write", doc = " **From String**")]
86#![cfg_attr(feature = "write", doc = "")]
87#![cfg_attr(feature = "parse", doc = " - [`parse`]")]
88#![cfg_attr(feature = "parse", doc = " - [`parse_partial`]")]
89#![cfg_attr(feature = "parse", doc = " - [`parse_with_options`]")]
90#![cfg_attr(feature = "parse", doc = " - [`parse_partial_with_options`]")]
91//!
92//! # Features
93//!
94//! In accordance with the Rust ethos, all features are additive: the crate
95//! may be build with `--all-features` without issue. The following features
96//! are enabled by default:
97//!
98//! * `std`
99//! * `write-integers`
100//! * `write-floats`
101//! * `parse-integers`
102//! * `parse-floats`
103//!
104//! A complete description of supported features includes:
105//!
106//! #### std
107//!
108//! Enable use of the standard library. Currently, the standard library
109//! is not used for any functionality, and may be disabled without any
110//! change in functionality on stable.
111//!
112//! #### write-integers
113//!
114//! Enable support for writing integers to string.
115//!
116//! #### write-floats
117//!
118//! Enable support for writing floating-point numbers to string.
119//!
120//! #### parse-integers
121//!
122//! Enable support for parsing integers from string.
123//!
124//! #### parsing-floats
125//!
126//! Enable support for parsing floating-point numbers from string.
127//!
128//! #### format
129//!
130//! Adds support for the entire format API (using [`NumberFormatBuilder`]).
131//! This allows extensive configurability for parsing and writing numbers
132//! in custom formats, with different valid syntax requirements.
133//!
134//! For example, in JSON, the following floats are valid or invalid:
135//!
136//! ```text
137//! -1 // valid
138//! +1 // invalid
139//! 1 // valid
140//! 1. // invalid
141//! .1 // invalid
142//! 0.1 // valid
143//! nan // invalid
144//! inf // invalid
145//! Infinity // invalid
146//! ```
147//!
148//! All of the finite numbers are valid in Rust, and Rust provides constants
149//! for non-finite floats. In order to parse standard-conforming JSON floats
150//! using lexical, you may use the following approach:
151//!
152//! ```rust
153//! # #[cfg(all(feature = "parse-floats", feature = "format"))] {
154//! use lexical_core::{format, parse_with_options, ParseFloatOptions, Result};
155//!
156//! fn parse_json_float<Bytes: AsRef<[u8]>>(bytes: Bytes) -> Result<f64> {
157//! let options = ParseFloatOptions::new();
158//! parse_with_options::<_, { format::JSON }>(bytes.as_ref(), &options)
159//! }
160//! # }
161//! ```
162//!
163//! See the [Number Format](#number-format) section below for more information.
164//!
165//! #### power-of-two
166//!
167//! Enable doing numeric conversions to and from strings with power-of-two
168//! radixes. This avoids most of the overhead and binary bloat of the radix
169//! feature, while enabling support for the most commonly-used radixes.
170//!
171//! #### radix
172//!
173//! Enable doing numeric conversions to and from strings for all radixes.
174//! This requires substantially more static storage than `power-of-two`,
175//! and increases compile times by a fair amount, but can be quite useful
176//! for esoteric programming languages which use duodecimal floats, for
177//! example.
178//!
179//! #### compact
180//!
181//! Reduce the generated code size at the cost of performance. This minimizes
182//! the number of static tables, inlining, and generics used, drastically
183//! reducing the size of the generated binaries.
184//!
185//! #### safe
186//!
187//! This replaces most unchecked indexing, required in cases where the
188//! compiler cannot elide the check, with checked indexing. However,
189//! it does not fully replace all unsafe behavior with safe behavior.
190//! To minimize the risk of undefined behavior and out-of-bounds reads/writers,
191//! extensive edge-cases, property-based tests, and fuzzing is done with both
192//! the safe feature enabled and disabled, with the tests verified by Miri
193//! and Valgrind.
194//!
195//! # Configuration API
196//!
197//! Lexical provides two main levels of configuration:
198//! - The [`NumberFormatBuilder`], creating a packed struct with custom
199//! formatting options.
200//! - The Options API.
201//!
202//! ## Number Format
203//!
204//! The number format class provides numerous flags to specify
205//! number parsing or writing. When the `power-of-two` feature is
206//! enabled, additional flags are added:
207//! - The radix for the significant digits (default `10`).
208//! - The radix for the exponent base (default `10`).
209//! - The radix for the exponent digits (default `10`).
210//!
211//! When the `format` feature is enabled, numerous other syntax and
212//! digit separator flags are enabled, including:
213//! - A digit separator character, to group digits for increased legibility.
214//! - Whether leading, trailing, internal, and consecutive digit separators are
215//! allowed.
216//! - Toggling required float components, such as digits before the decimal
217//! point.
218//! - Toggling whether special floats are allowed or are case-sensitive.
219//!
220//! Many pre-defined constants therefore exist to simplify common use-cases,
221//! including:
222//! - `JSON`, `XML`, `TOML`, `YAML`, `SQLite`, and many more.
223//! - `Rust`, `Python`, `C#`, `FORTRAN`, `COBOL` literals and strings, and many
224//! more.
225//!
226//! ## Options API
227//!
228//! The Options API provides high-level options to specify number parsing
229//! or writing, options not intrinsically tied to a number format.
230//! For example, the Options API provides:
231//! - The exponent character (default `b'e'`, or `b'^'`).
232//! - The decimal point character (default `b'.'`).
233//! - Custom `NaN`, `Infinity` string representations.
234//! - Whether to trim the fraction component from integral floats.
235//! - The exponent break point for scientific notation.
236//! - The maximum and minimum number of significant digits to write.
237//! - The rounding mode when truncating significant digits while writing.
238//!
239//! The available options are:
240#![cfg_attr(feature = "parse-floats", doc = " - [`ParseFloatOptions`]")]
241#![cfg_attr(feature = "parse-integers", doc = " - [`ParseIntegerOptions`]")]
242#![cfg_attr(feature = "write-floats", doc = " - [`WriteFloatOptions`]")]
243#![cfg_attr(feature = "write-integers", doc = " - [`WriteIntegerOptions`]")]
244//!
245//! In addition, pre-defined constants for each category of options may
246//! be found in their respective modules.
247//!
248//! ## Example
249//!
250//! An example of creating your own options to parse European-style
251//! numbers (which use commas as decimal points, and periods as digit
252//! separators) is as follows:
253//!
254//! ```
255//! # pub fn main() {
256//! # #[cfg(all(feature = "parse_floats", feature = "format"))] {
257//! // This creates a format to parse a European-style float number.
258//! // The decimal point is a comma, and the digit separators (optional)
259//! // are periods.
260//! const EUROPEAN: u128 = lexical_core::NumberFormatBuilder::new()
261//! .digit_separator(b'.')
262//! .build();
263//! let options = lexical_core::ParseFloatOptions::builder()
264//! .decimal_point(b',')
265//! .build()
266//! .unwrap();
267//! assert_eq!(
268//! lexical_core::parse_with_options::<f32, EUROPEAN>(b"300,10", &options),
269//! Ok(300.10)
270//! );
271//!
272//! // Another example, using a pre-defined constant for JSON.
273//! const JSON: u128 = lexical_core::format::JSON;
274//! let options = lexical_core::ParseFloatOptions::new();
275//! assert_eq!(
276//! lexical_core::parse_with_options::<f32, JSON>(b"0e1", &options),
277//! Ok(0.0)
278//! );
279//! assert_eq!(
280//! lexical_core::parse_with_options::<f32, JSON>(b"1E+2", &options),
281//! Ok(100.0)
282//! );
283//! # }
284//! # }
285//! ```
286//!
287//! # Algorithms
288//!
289//! - [Parsing Floats](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-float/docs/Algorithm.md)
290//! - [Parsing Integers](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-integer/docs/Algorithm.md)
291//! - [Writing Floats](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-float/docs/Algorithm.md)
292//! - [Writing Integers](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-integer/docs/Algorithm.md)
293//!
294//! # Benchmarks
295//!
296//! - [Parsing Floats](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-float/docs/Benchmarks.md)
297//! - [Parsing Integers](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-integer/docs/Benchmarks.md)
298//! - [Writing Floats](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-float/docs/Benchmarks.md)
299//! - [Writing Integers](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-integer/docs/Benchmarks.md)
300//! - [Comprehensive Benchmarks](https://github.com/Alexhuszagh/lexical-benchmarks)
301//!
302//! A comprehensive analysis of lexical commits and their performance can be
303//! found in [benchmarks].
304//!
305//! # Design
306//!
307//! - [Binary Size](https://github.com/Alexhuszagh/rust-lexical/blob/main/docs/BinarySize.md)
308//! - [Build Timings](https://github.com/Alexhuszagh/rust-lexical/blob/main/docs/BuildTimings.md)
309//! - [Digit Separators](https://github.com/Alexhuszagh/rust-lexical/blob/main/docs/DigitSeparators.md)
310//!
311//! # Version Support
312//!
313//! The minimum, standard, required version is 1.63.0, for const generic
314//! support. Older versions of lexical support older Rust versions.
315//!
316//! # Safety
317//!
318//! There is no non-trivial unsafe behavior in [lexical][crate] itself,
319//! however, any incorrect safety invariants in our parsers and writers
320//! (`lexical-parse-float`, `lexical-parse-integer`, `lexical-write-float`,
321//! and `lexical-write-integer`) could cause those safety invariants to
322//! be broken.
323//!
324//! [`write`]: crate::write
325//! [`write_with_options`]: crate::write_with_options
326//! [`parse`]: crate::parse
327//! [`parse_partial`]: crate::parse_partial
328//! [`parse_with_options`]: crate::parse_with_options
329//! [`parse_partial_with_options`]: crate::parse_partial_with_options
330//!
331//! [`NumberFormatBuilder`]: crate::NumberFormatBuilder
332//! [`ParseFloatOptions`]: crate::ParseFloatOptions
333//! [`ParseIntegerOptions`]: crate::ParseIntegerOptions
334//! [`WriteFloatOptions`]: crate::WriteFloatOptions
335//! [`WriteIntegerOptions`]: crate::WriteIntegerOptions
336//! [benchmarks]: <https://github.com/Alexhuszagh/lexical-benchmarks>
337
338// We want to have the same safety guarantees as Rust core,
339// so we allow unused unsafe to clearly document safety guarantees.
340#![allow(unused_unsafe)]
341#![cfg_attr(feature = "lint", warn(unsafe_op_in_unsafe_fn))]
342#![cfg_attr(not(feature = "std"), no_std)]
343#![deny(
344 clippy::doc_markdown,
345 clippy::unnecessary_safety_comment,
346 clippy::semicolon_if_nothing_returned,
347 clippy::unwrap_used,
348 clippy::as_underscore,
349 clippy::doc_markdown
350)]
351#![allow(
352 // used when concepts are logically separate
353 clippy::match_same_arms,
354 // loss of precision is intentional
355 clippy::integer_division,
356 // mathematical names use 1-character identifiers
357 clippy::min_ident_chars,
358 // these are not cryptographically secure contexts
359 clippy::integer_division_remainder_used,
360 // this can be intentional
361 clippy::module_name_repetitions,
362 // this is intentional: already passing a pointer and need performance
363 clippy::needless_pass_by_value,
364 // we use this for inline formatting for unsafe blocks
365 clippy::semicolon_inside_block,
366)]
367
368// Re-exports
369#[cfg(feature = "parse-floats")]
370pub use lexical_parse_float::{
371 options as parse_float_options,
372 Options as ParseFloatOptions,
373 OptionsBuilder as ParseFloatOptionsBuilder,
374};
375#[cfg(feature = "parse-floats")]
376use lexical_parse_float::{
377 FromLexical as FromFloat,
378 FromLexicalWithOptions as FromFloatWithOptions,
379};
380#[cfg(feature = "parse-integers")]
381pub use lexical_parse_integer::{
382 options as parse_integer_options,
383 Options as ParseIntegerOptions,
384 OptionsBuilder as ParseIntegerOptionsBuilder,
385};
386#[cfg(feature = "parse-integers")]
387use lexical_parse_integer::{
388 FromLexical as FromInteger,
389 FromLexicalWithOptions as FromIntegerWithOptions,
390};
391#[cfg(feature = "f16")]
392pub use lexical_util::bf16::bf16;
393#[cfg(feature = "write")]
394pub use lexical_util::constants::{FormattedSize, BUFFER_SIZE};
395#[cfg(feature = "parse")]
396pub use lexical_util::error::Error;
397#[cfg(feature = "f16")]
398pub use lexical_util::f16::f16;
399pub use lexical_util::format::{self, format_error, format_is_valid, NumberFormatBuilder};
400#[cfg(feature = "parse")]
401pub use lexical_util::options::ParseOptions;
402#[cfg(feature = "write")]
403pub use lexical_util::options::WriteOptions;
404#[cfg(feature = "parse")]
405pub use lexical_util::result::Result;
406#[cfg(feature = "parse")]
407use lexical_util::{from_lexical, from_lexical_with_options};
408#[cfg(feature = "write")]
409use lexical_util::{to_lexical, to_lexical_with_options};
410#[cfg(feature = "write-floats")]
411pub use lexical_write_float::{
412 options as write_float_options,
413 Options as WriteFloatOptions,
414 OptionsBuilder as WriteFloatOptionsBuilder,
415};
416#[cfg(feature = "write-floats")]
417use lexical_write_float::{ToLexical as ToFloat, ToLexicalWithOptions as ToFloatWithOptions};
418#[cfg(feature = "write-integers")]
419pub use lexical_write_integer::{
420 options as write_integer_options,
421 Options as WriteIntegerOptions,
422 OptionsBuilder as WriteIntegerOptionsBuilder,
423};
424#[cfg(feature = "write-integers")]
425use lexical_write_integer::{ToLexical as ToInteger, ToLexicalWithOptions as ToIntegerWithOptions};
426
427// API
428// ---
429
430#[cfg(feature = "parse")]
431from_lexical!();
432#[cfg(feature = "parse")]
433from_lexical_with_options!();
434#[cfg(feature = "write")]
435to_lexical!();
436#[cfg(feature = "write")]
437to_lexical_with_options!();
438
439/// Implement `FromLexical` and `FromLexicalWithOptions` for numeric types.
440///
441/// * `t` - The numerical type.
442/// * `from` - The internal trait that implements
443/// `from_lexical`.
444/// * `from_lexical_with_options` - The internal trait that implements
445/// `from_lexical`.
446/// * `options` - The options type to configure settings.
447#[cfg(feature = "parse")]
448macro_rules! from_lexical_impl {
449 ($t:ident, $from:ident, $from_options:ident, $options:ident) => {
450 impl FromLexical for $t {
451 #[cfg_attr(not(feature = "compact"), inline)]
452 fn from_lexical(bytes: &[u8]) -> Result<Self> {
453 <Self as $from>::from_lexical(bytes)
454 }
455
456 #[cfg_attr(not(feature = "compact"), inline)]
457 fn from_lexical_partial(bytes: &[u8]) -> Result<(Self, usize)> {
458 <Self as $from>::from_lexical_partial(bytes)
459 }
460 }
461
462 impl FromLexicalWithOptions for $t {
463 type Options = $options;
464
465 #[cfg_attr(not(feature = "compact"), inline)]
466 fn from_lexical_with_options<const FORMAT: u128>(
467 bytes: &[u8],
468 options: &Self::Options,
469 ) -> Result<Self> {
470 <Self as $from_options>::from_lexical_with_options::<FORMAT>(bytes, options)
471 }
472
473 #[cfg_attr(not(feature = "compact"), inline)]
474 fn from_lexical_partial_with_options<const FORMAT: u128>(
475 bytes: &[u8],
476 options: &Self::Options,
477 ) -> Result<(Self, usize)> {
478 <Self as $from_options>::from_lexical_partial_with_options::<FORMAT>(bytes, options)
479 }
480 }
481 };
482}
483
484/// Implement `FromLexical` and `FromLexicalWithOptions` for integers.
485#[cfg(feature = "parse-integers")]
486macro_rules! integer_from_lexical {
487 ($($t:ident)*) => ($(
488 from_lexical_impl!($t, FromInteger, FromIntegerWithOptions, ParseIntegerOptions);
489 )*);
490}
491
492#[cfg(feature = "parse-integers")]
493integer_from_lexical! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
494
495/// Implement `FromLexical` and `FromLexicalWithOptions` for floats.
496#[cfg(feature = "parse-floats")]
497macro_rules! float_from_lexical {
498 ($($t:ident)*) => ($(
499 from_lexical_impl!($t, FromFloat, FromFloatWithOptions, ParseFloatOptions);
500 )*);
501}
502
503#[cfg(feature = "parse-floats")]
504float_from_lexical! { f32 f64 }
505
506/// Implement `ToLexical` and `ToLexicalWithOptions` for numeric types.
507///
508/// * `t` - The numerical type.
509/// * `to` - The internal trait that implements
510/// `to_lexical`.
511/// * `to_lexical_with_options` - The internal trait that implements
512/// `to_lexical`.
513/// * `options` - The options type to configure settings.
514#[cfg(feature = "write")]
515macro_rules! to_lexical_impl {
516 ($t:ident, $to:ident, $to_options:ident, $options:ident) => {
517 impl ToLexical for $t {
518 #[cfg_attr(not(feature = "compact"), inline)]
519 fn to_lexical(self, bytes: &mut [u8]) -> &mut [u8] {
520 <Self as $to>::to_lexical(self, bytes)
521 }
522 }
523
524 impl ToLexicalWithOptions for $t {
525 type Options = $options;
526 #[cfg_attr(not(feature = "compact"), inline(always))]
527 fn to_lexical_with_options<'a, const FORMAT: u128>(
528 self,
529 bytes: &'a mut [u8],
530 options: &Self::Options,
531 ) -> &'a mut [u8] {
532 <Self as $to_options>::to_lexical_with_options::<FORMAT>(self, bytes, options)
533 }
534 }
535 };
536}
537
538/// Implement `ToLexical` and `ToLexicalWithOptions` for integers.
539#[cfg(feature = "write-integers")]
540macro_rules! integer_to_lexical {
541 ($($t:ident)*) => ($(
542 to_lexical_impl!($t, ToInteger, ToIntegerWithOptions, WriteIntegerOptions);
543 )*);
544}
545
546#[cfg(feature = "write-integers")]
547integer_to_lexical! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
548
549/// Implement `ToLexical` and `ToLexicalWithOptions` for floats.
550#[cfg(feature = "write-floats")]
551macro_rules! float_to_lexical {
552 ($($t:ident)*) => ($(
553 to_lexical_impl!($t, ToFloat, ToFloatWithOptions, WriteFloatOptions);
554 )*);
555}
556
557#[cfg(feature = "write-floats")]
558float_to_lexical! { f32 f64 }
559
560/// Write number to string.
561///
562/// Returns a subslice of the input buffer containing the written bytes,
563/// starting from the same address in memory as the input slice.
564///
565/// * `value` - Number to serialize.
566/// * `bytes` - Buffer to write number to.
567///
568/// # Panics
569///
570/// Panics if the buffer may not be large enough to hold the serialized
571/// number. In order to ensure the function will not panic, provide a
572/// buffer with at least `{integer}::FORMATTED_SIZE` elements.
573///
574/// # Example
575///
576/// ```
577/// # pub fn main() {
578/// #[cfg(feature = "write-floats")] {
579/// // import `BUFFER_SIZE` to get the maximum bytes written by the number.
580/// use lexical_core::BUFFER_SIZE;
581///
582/// let mut buffer = [0u8; BUFFER_SIZE];
583/// let float = 3.14159265359_f32;
584///
585/// lexical_core::write(float, &mut buffer);
586///
587/// assert_eq!(&buffer[0..9], b"3.1415927");
588/// # }
589/// # }
590/// ```
591///
592/// This will panic, because the buffer is not large enough:
593///
594/// ```should_panic
595/// # #[cfg(feature = "write-floats")] {
596/// // note: the buffer is only one byte large
597/// let mut buffer = [0u8; 1];
598/// let float = 3.14159265359_f32;
599///
600/// lexical_core::write(float, &mut buffer);
601/// # }
602/// # #[cfg(not(feature = "write-floats"))] {
603/// # panic!("");
604/// # }
605/// ```
606#[inline]
607#[cfg(feature = "write")]
608pub fn write<N: ToLexical>(n: N, bytes: &mut [u8]) -> &mut [u8] {
609 n.to_lexical(bytes)
610}
611
612/// Write number to string with custom options.
613///
614/// Returns a subslice of the input buffer containing the written bytes,
615/// starting from the same address in memory as the input slice.
616///
617/// * `FORMAT` - Packed struct containing the number format.
618/// * `value` - Number to serialize.
619/// * `bytes` - Buffer to write number to.
620/// * `options` - Options to customize number parsing.
621///
622/// # Panics
623///
624/// Panics if the buffer may not be large enough to hold the serialized
625/// number. In order to ensure the function will not panic, provide a
626/// buffer with at least `{integer}::FORMATTED_SIZE` elements. If you
627/// are using custom digit precision control or exponent break points
628/// for writing floats, these constants may be insufficient to store
629/// the serialized number, and up to 1200 bytes may be required with
630/// radix support.
631///
632/// If the provided `FORMAT` is not valid, the function may panic. Please
633/// ensure `is_valid()` is called prior to using the format, or checking
634/// its validity using a static assertion.
635///
636/// # Example
637///
638/// ```
639/// # pub fn main() {
640/// #[cfg(feature = "write-floats")] {
641/// // import `BUFFER_SIZE` to get the maximum bytes written by the number.
642/// use lexical_core::BUFFER_SIZE;
643///
644/// let mut buffer = [0u8; BUFFER_SIZE];
645/// let float = 3.14159265359_f32;
646///
647/// const FORMAT: u128 = lexical_core::format::STANDARD;
648/// let options = lexical_core::WriteFloatOptions::new();
649/// lexical_core::write_with_options::<_, FORMAT>(float, &mut buffer, &options);
650///
651/// assert_eq!(&buffer[0..9], b"3.1415927");
652/// # }
653/// # }
654/// ```
655///
656/// This will panic, because the buffer is not large enough:
657///
658/// ```should_panic
659/// # #[cfg(feature = "write-floats")] {
660/// // note: the buffer is only one byte large
661/// let mut buffer = [0u8; 1];
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/// # #[cfg(not(feature = "write-floats"))] {
669/// # panic!("");
670/// # }
671/// ```
672#[inline]
673#[cfg(feature = "write")]
674pub fn write_with_options<'a, N: ToLexicalWithOptions, const FORMAT: u128>(
675 n: N,
676 bytes: &'a mut [u8],
677 options: &N::Options,
678) -> &'a mut [u8] {
679 n.to_lexical_with_options::<FORMAT>(bytes, options)
680}
681
682/// Parse complete number from string.
683///
684/// This method parses the entire string, returning an error if
685/// any invalid digits are found during parsing.
686///
687/// * `bytes` - Byte slice containing a numeric string.
688///
689/// # Example
690///
691/// ```
692/// # pub fn main() {
693/// #[cfg(feature = "parse-floats")] {
694/// let string = "3.14159265359";
695/// let result = lexical_core::parse::<f32>(string.as_bytes());
696/// assert_eq!(result, Ok(3.14159265359_f32));
697/// # }
698/// # }
699/// ```
700#[inline]
701#[cfg(feature = "parse")]
702pub fn parse<N: FromLexical>(bytes: &[u8]) -> Result<N> {
703 N::from_lexical(bytes)
704}
705
706/// Parse partial number from string.
707///
708/// This method parses until an invalid digit is found (or the end
709/// of the string), returning the number of processed digits
710/// and the parsed value until that point.
711///
712/// * `bytes` - Byte slice containing a numeric string.
713///
714/// # Example
715///
716/// ```
717/// # pub fn main() {
718/// #[cfg(feature = "parse-floats")] {
719/// let string = "3.14159265359 hello";
720/// let result = lexical_core::parse_partial::<f32>(string.as_bytes());
721/// assert_eq!(result, Ok((3.14159265359_f32, 13)));
722/// # }
723/// # }
724/// ```
725#[inline]
726#[cfg(feature = "parse")]
727pub fn parse_partial<N: FromLexical>(bytes: &[u8]) -> Result<(N, usize)> {
728 N::from_lexical_partial(bytes)
729}
730
731/// Parse complete number from string with custom parsing options.
732///
733/// This method parses the entire string, returning an error if
734/// any invalid digits are found during parsing.
735///
736/// * `FORMAT` - Packed struct containing the number format.
737/// * `bytes` - Byte slice containing a numeric string.
738/// * `options` - Options to customize number parsing.
739///
740/// # Example
741///
742/// ```
743/// # pub fn main() {
744/// #[cfg(all(feature = "parse-floats", feature = "format"))] {
745/// const JSON: u128 = lexical_core::format::JSON;
746/// let options = lexical_core::ParseFloatOptions::new();
747/// let string = "3.14159265359";
748/// let result = lexical_core::parse_with_options::<f32, JSON>(string.as_bytes(), &options);
749/// assert_eq!(result, Ok(3.14159265359_f32));
750/// # }
751/// # }
752/// ```
753#[inline]
754#[cfg(feature = "parse")]
755pub fn parse_with_options<N: FromLexicalWithOptions, const FORMAT: u128>(
756 bytes: &[u8],
757 options: &N::Options,
758) -> Result<N> {
759 N::from_lexical_with_options::<FORMAT>(bytes, options)
760}
761
762/// Parse partial number from string with custom parsing options.
763///
764/// This method parses until an invalid digit is found (or the end
765/// of the string), returning the number of processed digits
766/// and the parsed value until that point.
767///
768/// * `FORMAT` - Packed struct containing the number format.
769/// * `bytes` - Byte slice containing a numeric string.
770/// * `options` - Options to customize number parsing.
771///
772/// # Example
773///
774/// ```
775/// # pub fn main() {
776/// #[cfg(all(feature = "parse-floats", feature = "format"))] {
777/// const JSON: u128 = lexical_core::format::JSON;
778/// let options = lexical_core::ParseFloatOptions::new();
779/// let string = "3.14159265359 hello";
780/// let result = lexical_core::parse_partial_with_options::<f32, JSON>(string.as_bytes(), &options);
781/// assert_eq!(result, Ok((3.14159265359_f32, 13)));
782/// # }
783/// # }
784/// ```
785#[inline]
786#[cfg(feature = "parse")]
787pub fn parse_partial_with_options<N: FromLexicalWithOptions, const FORMAT: u128>(
788 bytes: &[u8],
789 options: &N::Options,
790) -> Result<(N, usize)> {
791 N::from_lexical_partial_with_options::<FORMAT>(bytes, options)
792}