lexical_write_float/
lib.rs

1//! Fast and compact float-to-string conversions.
2//!
3//! # Features
4//!
5//! Each float formatter contains extensive formatting control, including
6//! a maximum number of significant digits written, a minimum number of
7//! significant digits remaining, the positive and negative exponent break
8//! points (at what exponent, in scientific-notation, to force scientific
9//! notation), whether to force or disable scientific notation, and the
10//! rounding mode for truncated float strings.
11//!
12//! # Algorithms
13//!
14//! There's currently 5 algorithms used, depending on the requirements.
15//!
16//! 1. Compact for decimal strings uses the Grisu algorithm.
17//! 2. An optimized algorithm based on the Dragonbox algorithm.
18//! 3. An optimized algorithm for formatting to string with power-of-two
19//!    radixes.
20//! 4. An optimized algorithm for hexadecimal floats.
21//! 5. A fallback algorithm for all other radixes.
22//!
23//! The Grisu algorithm is based on "Printing Floating-Point Numbers Quickly
24//! and Accurately with Integers", by Florian Loitsch, available online
25//! [here](https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf).
26//! The dragonbox algorithm is based on the reference C++ implementation,
27//! hosted [here](https://github.com/jk-jeon/dragonbox/), and the algorithm
28//! is described in depth
29//! [here](https://github.com/jk-jeon/dragonbox/blob/master/other_files/Dragonbox.pdf).
30//! The radix algorithm is adapted from the V8 codebase, and may be found
31//! [here](https://github.com/v8/v8).
32//!
33//! # Features
34//!
35//! * `std` - Use the standard library.
36//! * `power-of-two` - Add support for wring power-of-two float strings.
37//! * `radix` - Add support for strings of any radix.
38//! * `compact` - Reduce code size at the cost of performance.
39//! * `safe` - Ensure only memory-safe indexing is used.
40//!
41//! # Note
42//!
43//! Only documented functionality is considered part of the public API:
44//! any of the modules, internal functions, or structs may change
45//! release-to-release without major or minor version changes. Use
46//! internal implementation details at your own risk.
47//!
48//! lexical-write-float mainly exists as an implementation detail for
49//! lexical-core, although its API is stable. If you would like to use
50//! a high-level API that writes to and parses from `String` and `&str`,
51//! respectively, please look at [lexical](https://crates.io/crates/lexical)
52//! instead. If you would like an API that supports multiple numeric
53//! conversions, please look at [lexical-core](https://crates.io/crates/lexical-core)
54//! instead.
55//!
56//! # Version Support
57//!
58//! The minimum, standard, required version is 1.63.0, for const generic
59//! support. Older versions of lexical support older Rust versions.
60//!
61//! # Safety
62//!
63//! The `unsafe` usage in the options does not actually have any actual safety
64//! concerns unless the format is not validated: the float formatters assume
65//! NaN and Infinite strings are <= 50 characters. Creating custom format
66//! specification with longer special strings and not validating the :
67//! incorrectly using the API however can cause incorrect floating
68//! point specifications due to conflicting requirements.
69//!
70//! # Design
71//!
72//! - [Algorithm Approach](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-float/docs/Algorithm.md)
73//! - [Benchmarks](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-float/docs/Benchmarks.md)
74//! - [Comprehensive Benchmarks](https://github.com/Alexhuszagh/lexical-benchmarks)
75
76// We want to have the same safety guarantees as Rust core,
77// so we allow unused unsafe to clearly document safety guarantees.
78#![allow(unused_unsafe)]
79#![cfg_attr(feature = "lint", warn(unsafe_op_in_unsafe_fn))]
80#![cfg_attr(not(feature = "std"), no_std)]
81#![deny(
82    clippy::doc_markdown,
83    clippy::unnecessary_safety_comment,
84    clippy::semicolon_if_nothing_returned,
85    clippy::unwrap_used,
86    clippy::as_underscore,
87    clippy::doc_markdown
88)]
89#![allow(
90    // used when concepts are logically separate
91    clippy::match_same_arms,
92    // loss of precision is intentional
93    clippy::integer_division,
94    // mathematical names use 1-character identifiers
95    clippy::min_ident_chars,
96    // these are not cryptographically secure contexts
97    clippy::integer_division_remainder_used,
98    // this can be intentional
99    clippy::module_name_repetitions,
100    // this is intentional: already passing a pointer and need performance
101    clippy::needless_pass_by_value,
102    // we use this for inline formatting for unsafe blocks
103    clippy::semicolon_inside_block,
104)]
105
106#[macro_use]
107mod index;
108#[macro_use]
109mod shared;
110
111pub mod algorithm;
112pub mod binary;
113pub mod compact;
114pub mod float;
115pub mod hex;
116pub mod options;
117pub mod radix;
118pub mod table;
119pub mod write;
120
121mod api;
122mod table_dragonbox;
123mod table_grisu;
124
125// Re-exports
126#[cfg(feature = "f16")]
127pub use lexical_util::bf16::bf16;
128pub use lexical_util::constants::{FormattedSize, BUFFER_SIZE};
129#[cfg(feature = "f16")]
130pub use lexical_util::f16::f16;
131pub use lexical_util::format::{self, NumberFormatBuilder};
132pub use lexical_util::options::WriteOptions;
133
134pub use self::api::{ToLexical, ToLexicalWithOptions};
135#[doc(inline)]
136pub use self::options::{Options, OptionsBuilder, RoundMode};