/src/rust-lexical/lexical-parse-integer/src/options.rs
Line | Count | Source |
1 | | //! Configuration options for parsing integers. |
2 | | //! |
3 | | //! # Pre-Defined Formats |
4 | | //! |
5 | | //! This contains pre-defined options optimized for either the parsing of large |
6 | | //! or small numbers. |
7 | | //! - [`SMALL_NUMBERS`][`SMALL_NUMBERS`]: Optimize the parsing of small |
8 | | //! integers, at a major performance cost to larger values. |
9 | | //! - [`LARGE_NUMBERS`][`LARGE_NUMBERS`]: Optimize the parsing of large |
10 | | //! integers, at a slight performance cost to smaller values. |
11 | | //! |
12 | | //! # Examples |
13 | | //! |
14 | | //! ```rust |
15 | | //! use lexical_parse_integer::{FromLexicalWithOptions, Options}; |
16 | | //! use lexical_parse_integer::format::STANDARD; |
17 | | //! |
18 | | //! const OPTIONS: Options = Options::builder() |
19 | | //! .no_multi_digit(true) |
20 | | //! .build_strict(); |
21 | | //! |
22 | | //! let value = "1234"; |
23 | | //! let result = u64::from_lexical_with_options::<STANDARD>(value.as_bytes(), &OPTIONS); |
24 | | //! assert_eq!(result, Ok(1234)); |
25 | | //! ``` |
26 | | |
27 | | use lexical_util::options::ParseOptions; |
28 | | use lexical_util::result::Result; |
29 | | |
30 | | /// Builder for [`Options`]. |
31 | | /// |
32 | | /// # Examples |
33 | | /// |
34 | | /// ```rust |
35 | | /// use lexical_parse_integer::{FromLexicalWithOptions, Options}; |
36 | | /// use lexical_parse_integer::format::STANDARD; |
37 | | /// |
38 | | /// const OPTIONS: Options = Options::builder() |
39 | | /// .no_multi_digit(true) |
40 | | /// .build_strict(); |
41 | | /// |
42 | | /// let value = "1234"; |
43 | | /// let result = u64::from_lexical_with_options::<STANDARD>(value.as_bytes(), &OPTIONS); |
44 | | /// assert_eq!(result, Ok(1234)); |
45 | | /// ``` |
46 | | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] |
47 | | pub struct OptionsBuilder { |
48 | | /// Disable multi-digit optimizations. |
49 | | /// |
50 | | /// Using multi-digit optimizations allows parsing many digits |
51 | | /// from longer input strings at once which can dramatically |
52 | | /// improve performance (>70%) for long strings, but the |
53 | | /// increased branching can decrease performance for simple |
54 | | /// strings by 5-20%. Choose based on your inputs. |
55 | | no_multi_digit: bool, |
56 | | } |
57 | | |
58 | | impl OptionsBuilder { |
59 | | /// Create new options builder with default options. |
60 | | #[inline(always)] |
61 | | pub const fn new() -> Self { |
62 | | Self { |
63 | | no_multi_digit: true, |
64 | | } |
65 | | } |
66 | | |
67 | | // GETTERS |
68 | | |
69 | | /// Get if we disable the use of multi-digit optimizations. |
70 | | /// |
71 | | /// Defaults to [`true`]. |
72 | | /// |
73 | | /// # Examples |
74 | | /// |
75 | | /// ```rust |
76 | | /// use lexical_parse_integer::Options; |
77 | | /// |
78 | | /// let builder = Options::builder(); |
79 | | /// assert_eq!(builder.get_no_multi_digit(), true); |
80 | | /// ``` |
81 | | #[inline(always)] |
82 | | pub const fn get_no_multi_digit(&self) -> bool { |
83 | | self.no_multi_digit |
84 | | } |
85 | | |
86 | | // SETTERS |
87 | | |
88 | | /// Set if we disable the use of multi-digit optimizations. |
89 | | /// |
90 | | /// Defaults to [`true`]. |
91 | | /// |
92 | | /// # Examples |
93 | | /// |
94 | | /// ```rust |
95 | | /// use lexical_parse_integer::Options; |
96 | | /// |
97 | | /// const OPTIONS: Options = Options::builder() |
98 | | /// .no_multi_digit(false) |
99 | | /// .build_strict(); |
100 | | /// assert_eq!(OPTIONS.get_no_multi_digit(), false); |
101 | | /// ``` |
102 | | #[inline(always)] |
103 | | pub const fn no_multi_digit(mut self, no_multi_digit: bool) -> Self { |
104 | | self.no_multi_digit = no_multi_digit; |
105 | | self |
106 | | } |
107 | | |
108 | | // BUILDERS |
109 | | |
110 | | /// Check if the builder state is valid (always [`true`]). |
111 | | #[inline(always)] |
112 | | pub const fn is_valid(&self) -> bool { |
113 | | true |
114 | | } |
115 | | |
116 | | /// Build the [`Options`] struct without validation. |
117 | | /// |
118 | | /// <div class="warning"> |
119 | | /// |
120 | | /// This is completely safe, however, misusing this could cause panics at |
121 | | /// runtime. Always check if [`is_valid`] prior to using the built |
122 | | /// options. |
123 | | /// |
124 | | /// </div> |
125 | | /// |
126 | | /// [`is_valid`]: Self::is_valid |
127 | | #[inline(always)] |
128 | | pub const fn build_unchecked(&self) -> Options { |
129 | | Options { |
130 | | no_multi_digit: self.no_multi_digit, |
131 | | } |
132 | | } |
133 | | |
134 | | /// Build the [`Options`] struct. |
135 | | /// |
136 | | /// This can never panic. |
137 | | /// |
138 | | /// <!-- # Panics |
139 | | /// |
140 | | /// If the built options are not valid. This should always |
141 | | /// be used within a const context to avoid panics at runtime. |
142 | | /// --> |
143 | | #[inline(always)] |
144 | | pub const fn build_strict(&self) -> Options { |
145 | | match self.build() { |
146 | | Ok(value) => value, |
147 | | Err(error) => core::panic!("{}", error.description()), |
148 | | } |
149 | | } |
150 | | |
151 | | /// Build the [`Options`] struct. Always [`Ok`]. |
152 | | #[inline(always)] |
153 | | pub const fn build(&self) -> Result<Options> { |
154 | | Ok(self.build_unchecked()) |
155 | | } |
156 | | } |
157 | | |
158 | | impl Default for OptionsBuilder { |
159 | | #[inline(always)] |
160 | | fn default() -> Self { |
161 | | Self::new() |
162 | | } |
163 | | } |
164 | | |
165 | | /// Options to customize the parsing integers. |
166 | | /// |
167 | | /// # Examples |
168 | | /// |
169 | | /// ```rust |
170 | | /// use lexical_parse_integer::{FromLexicalWithOptions, Options}; |
171 | | /// use lexical_parse_integer::format::STANDARD; |
172 | | /// |
173 | | /// const OPTIONS: Options = Options::builder() |
174 | | /// .no_multi_digit(true) |
175 | | /// .build_strict(); |
176 | | /// |
177 | | /// let value = "1234"; |
178 | | /// let result = u64::from_lexical_with_options::<STANDARD>(value.as_bytes(), &OPTIONS); |
179 | | /// assert_eq!(result, Ok(1234)); |
180 | | /// ``` |
181 | | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] |
182 | | pub struct Options { |
183 | | /// Disable multi-digit optimizations. |
184 | | /// |
185 | | /// Using multi-digit optimizations allows parsing many digits |
186 | | /// from longer input strings at once which can dramatically |
187 | | /// improve performance (>70%) for long strings, but the |
188 | | /// increased branching can decrease performance for simple |
189 | | /// strings by 5-20%. Choose based on your inputs. |
190 | | no_multi_digit: bool, |
191 | | } |
192 | | |
193 | | impl Options { |
194 | | /// Create [`Options`] with default values. |
195 | | #[must_use] |
196 | | #[inline(always)] |
197 | | pub const fn new() -> Self { |
198 | | Self::builder().build_unchecked() |
199 | | } |
200 | | |
201 | | /// Create the default options for a given radix. |
202 | | #[inline(always)] |
203 | | #[cfg(feature = "power-of-two")] |
204 | | pub const fn from_radix(_: u8) -> Self { |
205 | | Self::new() |
206 | | } |
207 | | |
208 | | // GETTERS |
209 | | |
210 | | /// Check if the builder state is valid (always [`true`]). |
211 | | #[inline(always)] |
212 | | pub const fn is_valid(&self) -> bool { |
213 | | self.rebuild().is_valid() |
214 | | } |
215 | | |
216 | | /// Get if we disable the use of multi-digit optimizations. |
217 | | /// |
218 | | /// Defaults to [`true`]. |
219 | | /// |
220 | | /// # Examples |
221 | | /// |
222 | | /// ```rust |
223 | | /// use lexical_parse_integer::options::Options; |
224 | | /// |
225 | | /// const OPTIONS: Options = Options::builder() |
226 | | /// .no_multi_digit(true) |
227 | | /// .build_strict(); |
228 | | /// assert_eq!(OPTIONS.get_no_multi_digit(), true); |
229 | | /// ``` |
230 | | #[inline(always)] |
231 | 251 | pub const fn get_no_multi_digit(&self) -> bool { |
232 | 251 | self.no_multi_digit |
233 | 251 | } |
234 | | |
235 | | // SETTERS |
236 | | |
237 | | /// Set if we disable the use of multi-digit optimizations. |
238 | | #[deprecated = "Setters should have a `set_` prefix. Use `set_no_multi_digit` instead. Will be removed in 2.0."] |
239 | | #[inline(always)] |
240 | | pub fn no_multi_digit(&mut self, no_multi_digit: bool) { |
241 | | self.no_multi_digit = no_multi_digit; |
242 | | } |
243 | | |
244 | | /// Set if we disable the use of multi-digit optimizations. |
245 | | #[deprecated = "Options should be treated as immutable, use `OptionsBuilder` instead. Will be removed in 2.0."] |
246 | | #[inline(always)] |
247 | | pub fn set_no_multi_digit(&mut self, no_multi_digit: bool) { |
248 | | self.no_multi_digit = no_multi_digit; |
249 | | } |
250 | | |
251 | | // BUILDERS |
252 | | |
253 | | /// Get [`OptionsBuilder`] as a static function. |
254 | | #[inline(always)] |
255 | | pub const fn builder() -> OptionsBuilder { |
256 | | OptionsBuilder::new() |
257 | | } |
258 | | |
259 | | /// Create [`OptionsBuilder`] using existing values. |
260 | | #[inline(always)] |
261 | | pub const fn rebuild(&self) -> OptionsBuilder { |
262 | | OptionsBuilder { |
263 | | no_multi_digit: self.no_multi_digit, |
264 | | } |
265 | | } |
266 | | } |
267 | | |
268 | | impl Default for Options { |
269 | | #[inline(always)] |
270 | | fn default() -> Self { |
271 | | Self::new() |
272 | | } |
273 | | } |
274 | | |
275 | | impl ParseOptions for Options { |
276 | | #[inline(always)] |
277 | | fn is_valid(&self) -> bool { |
278 | | Self::is_valid(self) |
279 | | } |
280 | | } |
281 | | |
282 | | // PRE-DEFINED CONSTANTS |
283 | | // --------------------- |
284 | | |
285 | | /// Standard number format. |
286 | | #[rustfmt::skip] |
287 | | pub const STANDARD: Options = Options::new(); |
288 | | |
289 | | /// Options optimized for small numbers. |
290 | | #[rustfmt::skip] |
291 | | pub const SMALL_NUMBERS: Options = Options::builder() |
292 | | .no_multi_digit(true) |
293 | | .build_strict(); |
294 | | |
295 | | /// Options optimized for large numbers and long strings. |
296 | | #[rustfmt::skip] |
297 | | pub const LARGE_NUMBERS: Options = Options::builder() |
298 | | .no_multi_digit(false) |
299 | | .build_strict(); |