/src/rust-lexical/lexical-util/src/format_flags.rs
Line | Count | Source |
1 | | //! Bitmask flags and masks for numeric formats. |
2 | | //! |
3 | | //! These bitflags and masks comprise a compressed struct as a 128-bit |
4 | | //! integer, allowing its use in const generics. This comprises two parts: |
5 | | //! flags designating which numerical components are valid in a string, |
6 | | //! and masks to designate the control characters. |
7 | | //! |
8 | | //! The flags are designated in the lower 64 bits that modify |
9 | | //! the syntax of strings that are parsed by lexical. |
10 | | //! |
11 | | //! Bits 8-32 are reserved for float component flags, such |
12 | | //! as for example if base prefixes or postfixes are case-sensitive, |
13 | | //! if leading zeros in a float are valid, etc. |
14 | | //! |
15 | | //! Bits 32-64 are reserved for digit separator flags. These |
16 | | //! define which locations within a float or integer digit separators |
17 | | //! are valid, for example, before any digits in the integer component, |
18 | | //! whether consecutive digit separators are allowed, and more. |
19 | | //! |
20 | | //! ```text |
21 | | //! 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
22 | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
23 | | //! |I/R|F/R|E/R|M/R|+/M|R/M|e/e|+/E|R/E|e/F|S/S|S/C|N/I|N/F|R/e|e/C| |
24 | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
25 | | //! |
26 | | //! 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
27 | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
28 | | //! |e/P|e/S| | |
29 | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
30 | | //! |
31 | | //! 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
32 | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
33 | | //! |I/I|F/I|E/I|I/L|F/L|E/L|I/T|F/T|E/T|I/C|F/C|E/C|S/D| | |
34 | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
35 | | //! |
36 | | //! 48 49 50 51 52 53 54 55 56 57 58 59 60 62 62 63 64 |
37 | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
38 | | //! | | |
39 | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
40 | | //! |
41 | | //! Where: |
42 | | //! Non-Digit Separator Flags: |
43 | | //! I/R = Required integer digits. |
44 | | //! F/R = Required fraction digits. |
45 | | //! E/R = Required exponent digits. |
46 | | //! M/R = Required mantissa digits. |
47 | | //! +/M = No mantissa positive sign. |
48 | | //! R/M = Required positive sign. |
49 | | //! e/e = No exponent notation. |
50 | | //! +/E = No exponent positive sign. |
51 | | //! R/E = Required exponent sign. |
52 | | //! e/F = No exponent without fraction. |
53 | | //! S/S = No special (non-finite) values. |
54 | | //! S/C = Case-sensitive special (non-finite) values. |
55 | | //! N/I = No integer leading zeros. |
56 | | //! N/F = No float leading zeros. |
57 | | //! R/e = Required exponent characters. |
58 | | //! e/C = Case-sensitive exponent character. |
59 | | //! e/P = Case-sensitive base prefix. |
60 | | //! e/S = Case-sensitive base suffix. |
61 | | //! |
62 | | //! Digit Separator Flags: |
63 | | //! I/I = Integer internal digit separator. |
64 | | //! F/I = Fraction internal digit separator. |
65 | | //! E/I = Exponent internal digit separator. |
66 | | //! I/L = Integer leading digit separator. |
67 | | //! F/L = Fraction leading digit separator. |
68 | | //! E/L = Exponent leading digit separator. |
69 | | //! I/T = Integer trailing digit separator. |
70 | | //! F/T = Fraction trailing digit separator. |
71 | | //! E/T = Exponent trailing digit separator. |
72 | | //! I/C = Integer consecutive digit separator. |
73 | | //! F/C = Fraction consecutive digit separator. |
74 | | //! E/C = Exponent consecutive digit separator. |
75 | | //! S/D = Special (non-finite) digit separator. |
76 | | //! ``` |
77 | | //! |
78 | | //! The upper 64-bits are designated for control characters and radixes, |
79 | | //! such as the digit separator and base prefix characters, radixes, |
80 | | //! and more. |
81 | | //! |
82 | | //! ```text |
83 | | //! 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
84 | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
85 | | //! | Digit Separator | | |
86 | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
87 | | //! |
88 | | //! 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
89 | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
90 | | //! | | Base Prefix | | |
91 | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
92 | | //! |
93 | | //! 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
94 | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
95 | | //! | Base Suffix | | Mantissa Radix | | |
96 | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
97 | | //! |
98 | | //! 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
99 | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
100 | | //! | Exponent Base | | Exponent Radix | | |
101 | | //! +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
102 | | //! ``` |
103 | | //! |
104 | | //! |
105 | | //! Note: |
106 | | //! ----- |
107 | | //! |
108 | | //! In order to limit the format specification and avoid parsing |
109 | | //! non-numerical data, all number formats require some significant |
110 | | //! digits. Examples of always invalid numbers include: |
111 | | //! - ` ` |
112 | | //! - `.` |
113 | | //! - `e` |
114 | | //! - `e7` |
115 | | //! |
116 | | //! Test Cases: |
117 | | //! ----------- |
118 | | //! |
119 | | //! The following test-cases are used to define whether a literal or |
120 | | //! a string float is valid in a given language, and these tests are |
121 | | //! used to denote features in pre-defined formats. Only a few |
122 | | //! of these flags may modify the parsing behavior of integers. |
123 | | //! Integer parsing is assumed to be derived from float parsing, |
124 | | //! so if consecutive digit separators are valid in the integer |
125 | | //! component of a float, they are also valid in an integer. |
126 | | //! |
127 | | //! ```text |
128 | | //! 0: '.3' // Non-required integer. |
129 | | //! 1: '3.' // Non-required fraction. |
130 | | //! 2: '3e' // Non-required exponent. |
131 | | //! 3. '+3.0' // Mantissa positive sign. |
132 | | //! 4: '3.0e7' // Exponent notation. |
133 | | //! 5: '3.0e+7' // Exponent positive sign. |
134 | | //! 6. '3e7' // Exponent notation without fraction. |
135 | | //! 7: 'NaN' // Special (non-finite) values. |
136 | | //! 8: 'NAN' // Case-sensitive special (non-finite) values. |
137 | | //! 9: '3_4.01' // Integer internal digit separator. |
138 | | //! A: '3.0_1' // Fraction internal digit separator. |
139 | | //! B: '3.0e7_1' // Exponent internal digit separator. |
140 | | //! C: '_3.01' // Integer leading digit separator. |
141 | | //! D: '3._01' // Fraction leading digit separator. |
142 | | //! E: '3.0e_71' // Exponent leading digit separator. |
143 | | //! F: '3_.01' // Integer trailing digit separator. |
144 | | //! G: '3.01_' // Fraction trailing digit separator. |
145 | | //! H: '3.0e71_' // Exponent trailing digit separator. |
146 | | //! I: '3__4.01' // Integer consecutive digit separator. |
147 | | //! J: '3.0__1' // Fraction consecutive digit separator. |
148 | | //! K: '3.0e7__1' // Exponent consecutive digit separator. |
149 | | //! L: 'In_f' // Special (non-finite) digit separator. |
150 | | //! M: '010' // No integer leading zeros. |
151 | | //! N: '010.0' // No float leading zeros. |
152 | | //! O: '1.0' // No required exponent notation. |
153 | | //! P: '3.0E7' // Case-insensitive exponent character. |
154 | | //! P: '0x3.0' // Case-insensitive base prefix. |
155 | | //! P: '3.0H' // Case-insensitive base postfix. |
156 | | //! ``` |
157 | | //! |
158 | | //! Currently Supported Programming and Data Languages: |
159 | | //! --------------------------------------------------- |
160 | | //! |
161 | | //! 1. `Rust` |
162 | | //! 2. `Python` |
163 | | //! 3. `C++` (98, 03, 11, 14, 17) |
164 | | //! 4. `C` (89, 90, 99, 11, 18) |
165 | | //! 5. `Ruby` |
166 | | //! 6. `Swift` |
167 | | //! 7. `Go` |
168 | | //! 8. `Haskell` |
169 | | //! 9. `Javascript` |
170 | | //! 10. `Perl` |
171 | | //! 11. `PHP` |
172 | | //! 12. `Java` |
173 | | //! 13. `R` |
174 | | //! 14. `Kotlin` |
175 | | //! 15. `Julia` |
176 | | //! 16. `C#` (ISO-1, ISO-2, 3, 4, 5, 6, 7) |
177 | | //! 17. `Kawa` |
178 | | //! 18. `Gambit-C` |
179 | | //! 19. `Guile` |
180 | | //! 20. `Clojure` |
181 | | //! 21. `Erlang` |
182 | | //! 22. `Elm` |
183 | | //! 23. `Scala` |
184 | | //! 24. `Elixir` |
185 | | //! 25. `FORTRAN` |
186 | | //! 26. `D` |
187 | | //! 27. `Coffeescript` |
188 | | //! 28. `Cobol` |
189 | | //! 29. `F#` |
190 | | //! 30. `Visual Basic` |
191 | | //! 31. `OCaml` |
192 | | //! 32. `Objective-C` |
193 | | //! 33. `ReasonML` |
194 | | //! 34. `Octave` |
195 | | //! 35. `Matlab` |
196 | | //! 36. `Zig` |
197 | | //! 37. `SageMath` |
198 | | //! 38. `JSON` |
199 | | //! 39. `TOML` |
200 | | //! 40. `XML` |
201 | | //! 41. `SQLite` |
202 | | //! 42. `PostgreSQL` |
203 | | //! 43. `MySQL` |
204 | | //! 44. `MongoDB` |
205 | | |
206 | | #![cfg_attr(rustfmt, rustfmt::skip)] |
207 | | #![doc(hidden)] |
208 | | |
209 | | // ASSERTIONS |
210 | | // ---------- |
211 | | |
212 | | // Ensure all our bit flags are valid. |
213 | | macro_rules! check_subsequent_flags { |
214 | | ($x:ident, $y:ident) => { |
215 | | const _: () = assert!($x << 1 == $y); |
216 | | }; |
217 | | } |
218 | | |
219 | | // Ensure all our bit masks don't overlap. |
220 | | macro_rules! check_subsequent_masks { |
221 | | ($x:ident, $y:ident) => { |
222 | | const _: () = assert!($x & $y == 0); |
223 | | }; |
224 | | } |
225 | | |
226 | | // Check all our masks are in the range `[0, 255]` after shifting. |
227 | | macro_rules! check_mask_shifts { |
228 | | ($mask:ident, $shift:ident) => { |
229 | | const _: () = assert!(0 < $mask >> $shift && 255 >= $mask >> $shift); |
230 | | }; |
231 | | } |
232 | | |
233 | | // Ensure all our bit masks don't overlap with existing flags. |
234 | | macro_rules! check_masks_and_flags { |
235 | | ($x:ident, $y:ident) => { |
236 | | const _: () = assert!($x & $y == 0); |
237 | | }; |
238 | | } |
239 | | |
240 | | // NON-DIGIT SEPARATOR FLAGS & MASKS |
241 | | // --------------------------------- |
242 | | |
243 | | /// Digits are required before the decimal point. |
244 | | pub const REQUIRED_INTEGER_DIGITS: u128 = 1 << 0; |
245 | | |
246 | | /// Digits are required after the decimal point. |
247 | | /// This check will only occur if the decimal point is present. |
248 | | pub const REQUIRED_FRACTION_DIGITS: u128 = 1 << 1; |
249 | | |
250 | | /// Digits are required after the exponent character. |
251 | | /// This check will only occur if the exponent character is present. |
252 | | pub const REQUIRED_EXPONENT_DIGITS: u128 = 1 << 2; |
253 | | |
254 | | /// Mantissa digits are required (either before or after the decimal point). |
255 | | pub const REQUIRED_MANTISSA_DIGITS: u128 = 1 << 3; |
256 | | |
257 | | /// At least 1 digit in the number is required. |
258 | | pub const REQUIRED_DIGITS: u128 = |
259 | | REQUIRED_INTEGER_DIGITS | |
260 | | REQUIRED_FRACTION_DIGITS | |
261 | | REQUIRED_EXPONENT_DIGITS | |
262 | | REQUIRED_MANTISSA_DIGITS; |
263 | | |
264 | | /// Positive sign before the mantissa is not allowed. |
265 | | pub const NO_POSITIVE_MANTISSA_SIGN: u128 = 1 << 4; |
266 | | |
267 | | /// Positive sign before the mantissa is required. |
268 | | pub const REQUIRED_MANTISSA_SIGN: u128 = 1 << 5; |
269 | | |
270 | | /// Exponent notation is not allowed. |
271 | | pub const NO_EXPONENT_NOTATION: u128 = 1 << 6; |
272 | | |
273 | | /// Positive sign before the exponent is not allowed. |
274 | | pub const NO_POSITIVE_EXPONENT_SIGN: u128 = 1 << 7; |
275 | | |
276 | | /// Positive sign before the exponent is required. |
277 | | pub const REQUIRED_EXPONENT_SIGN: u128 = 1 << 8; |
278 | | |
279 | | /// Exponent without a fraction component is not allowed. |
280 | | /// |
281 | | /// This only checks if a decimal point precedes the exponent character. |
282 | | /// To require fraction digits or exponent digits with this check, |
283 | | /// please use the appropriate flags. |
284 | | pub const NO_EXPONENT_WITHOUT_FRACTION: u128 = 1 << 9; |
285 | | |
286 | | /// Special (non-finite) values are not allowed. |
287 | | pub const NO_SPECIAL: u128 = 1 << 10; |
288 | | |
289 | | /// Special (non-finite) values are case-sensitive. |
290 | | pub const CASE_SENSITIVE_SPECIAL: u128 = 1 << 11; |
291 | | |
292 | | /// Leading zeros before an integer value are not allowed. |
293 | | /// |
294 | | /// If the value is a literal, then this distinction applies |
295 | | /// when the value is treated like an integer literal, typically |
296 | | /// when there is no decimal point. If the value is parsed, |
297 | | /// then this distinction applies when the value as parsed |
298 | | /// as an integer. |
299 | | /// |
300 | | /// # Warning |
301 | | /// |
302 | | /// This also does not mean that the value parsed will be correct, |
303 | | /// for example, in languages like C, this will not auto- |
304 | | /// deduce that the radix is 8 with leading zeros, for an octal |
305 | | /// literal. |
306 | | pub const NO_INTEGER_LEADING_ZEROS: u128 = 1 << 12; |
307 | | |
308 | | /// Leading zeros before a float value are not allowed. |
309 | | /// |
310 | | /// If the value is a literal, then this distinction applies |
311 | | /// when the value is treated like an integer float, typically |
312 | | /// when there is a decimal point. If the value is parsed, |
313 | | /// then this distinction applies when the value as parsed |
314 | | /// as a float. |
315 | | /// |
316 | | /// # Warning |
317 | | /// |
318 | | /// This also does not mean that the value parsed will be correct, |
319 | | /// for example, in languages like C, this will not auto- |
320 | | /// deduce that the radix is 8 with leading zeros, for an octal |
321 | | /// literal. |
322 | | pub const NO_FLOAT_LEADING_ZEROS: u128 = 1 << 13; |
323 | | |
324 | | /// Exponent notation is required. |
325 | | /// |
326 | | /// Valid floats must contain an exponent notation character, and if |
327 | | /// applicable, a sign character and digits afterwards. |
328 | | pub const REQUIRED_EXPONENT_NOTATION: u128 = 1 << 14; |
329 | | |
330 | | /// Exponent characters are case-sensitive. |
331 | | pub const CASE_SENSITIVE_EXPONENT: u128 = 1 << 15; |
332 | | |
333 | | /// Base prefixes are case-sensitive. |
334 | | pub const CASE_SENSITIVE_BASE_PREFIX: u128 = 1 << 16; |
335 | | |
336 | | /// Base suffixes are case-sensitive. |
337 | | pub const CASE_SENSITIVE_BASE_SUFFIX: u128 = 1 << 17; |
338 | | |
339 | | // Non-digit separator flags. |
340 | | const _: () = assert!(REQUIRED_INTEGER_DIGITS == 1); |
341 | | check_subsequent_flags!(REQUIRED_INTEGER_DIGITS, REQUIRED_FRACTION_DIGITS); |
342 | | check_subsequent_flags!(REQUIRED_FRACTION_DIGITS, REQUIRED_EXPONENT_DIGITS); |
343 | | check_subsequent_flags!(REQUIRED_EXPONENT_DIGITS, REQUIRED_MANTISSA_DIGITS); |
344 | | check_subsequent_flags!(REQUIRED_MANTISSA_DIGITS, NO_POSITIVE_MANTISSA_SIGN); |
345 | | check_subsequent_flags!(NO_POSITIVE_MANTISSA_SIGN, REQUIRED_MANTISSA_SIGN); |
346 | | check_subsequent_flags!(REQUIRED_MANTISSA_SIGN, NO_EXPONENT_NOTATION); |
347 | | check_subsequent_flags!(NO_EXPONENT_NOTATION, NO_POSITIVE_EXPONENT_SIGN); |
348 | | check_subsequent_flags!(NO_POSITIVE_EXPONENT_SIGN, REQUIRED_EXPONENT_SIGN); |
349 | | check_subsequent_flags!(REQUIRED_EXPONENT_SIGN, NO_EXPONENT_WITHOUT_FRACTION); |
350 | | check_subsequent_flags!(NO_EXPONENT_WITHOUT_FRACTION, NO_SPECIAL); |
351 | | check_subsequent_flags!(NO_SPECIAL, CASE_SENSITIVE_SPECIAL); |
352 | | check_subsequent_flags!(NO_SPECIAL, CASE_SENSITIVE_SPECIAL); |
353 | | check_subsequent_flags!(CASE_SENSITIVE_SPECIAL, NO_INTEGER_LEADING_ZEROS); |
354 | | check_subsequent_flags!(NO_INTEGER_LEADING_ZEROS, NO_FLOAT_LEADING_ZEROS); |
355 | | check_subsequent_flags!(NO_FLOAT_LEADING_ZEROS, REQUIRED_EXPONENT_NOTATION); |
356 | | check_subsequent_flags!(REQUIRED_EXPONENT_NOTATION, CASE_SENSITIVE_EXPONENT); |
357 | | check_subsequent_flags!(CASE_SENSITIVE_EXPONENT, CASE_SENSITIVE_BASE_PREFIX); |
358 | | check_subsequent_flags!(CASE_SENSITIVE_BASE_PREFIX, CASE_SENSITIVE_BASE_SUFFIX); |
359 | | |
360 | | // DIGIT SEPARATOR FLAGS & MASKS |
361 | | // ----------------------------- |
362 | | |
363 | | /// Digit separators are allowed between integer digits. |
364 | | pub const INTEGER_INTERNAL_DIGIT_SEPARATOR: u128 = 1 << 32; |
365 | | |
366 | | /// Digit separators are allowed between fraction digits. |
367 | | pub const FRACTION_INTERNAL_DIGIT_SEPARATOR: u128 = 1 << 33; |
368 | | |
369 | | /// Digit separators are allowed between exponent digits. |
370 | | pub const EXPONENT_INTERNAL_DIGIT_SEPARATOR: u128 = 1 << 34; |
371 | | |
372 | | /// A digit separator is allowed before any integer digits. |
373 | | pub const INTEGER_LEADING_DIGIT_SEPARATOR: u128 = 1 << 35; |
374 | | |
375 | | /// A digit separator is allowed before any fraction digits. |
376 | | pub const FRACTION_LEADING_DIGIT_SEPARATOR: u128 = 1 << 36; |
377 | | |
378 | | /// A digit separator is allowed before any exponent digits. |
379 | | pub const EXPONENT_LEADING_DIGIT_SEPARATOR: u128 = 1 << 37; |
380 | | |
381 | | /// A digit separator is allowed after any integer digits. |
382 | | pub const INTEGER_TRAILING_DIGIT_SEPARATOR: u128 = 1 << 38; |
383 | | |
384 | | /// A digit separator is allowed after any fraction digits. |
385 | | pub const FRACTION_TRAILING_DIGIT_SEPARATOR: u128 = 1 << 39; |
386 | | |
387 | | /// A digit separator is allowed after any exponent digits. |
388 | | pub const EXPONENT_TRAILING_DIGIT_SEPARATOR: u128 = 1 << 40; |
389 | | |
390 | | /// Multiple consecutive integer digit separators are allowed. |
391 | | pub const INTEGER_CONSECUTIVE_DIGIT_SEPARATOR: u128 = 1 << 41; |
392 | | |
393 | | /// Multiple consecutive fraction digit separators are allowed. |
394 | | pub const FRACTION_CONSECUTIVE_DIGIT_SEPARATOR: u128 = 1 << 42; |
395 | | |
396 | | /// Multiple consecutive exponent digit separators are allowed. |
397 | | pub const EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR: u128 = 1 << 43; |
398 | | |
399 | | /// Digit separators are allowed between digits. |
400 | | pub const INTERNAL_DIGIT_SEPARATOR: u128 = |
401 | | INTEGER_INTERNAL_DIGIT_SEPARATOR | |
402 | | FRACTION_INTERNAL_DIGIT_SEPARATOR | |
403 | | EXPONENT_INTERNAL_DIGIT_SEPARATOR; |
404 | | |
405 | | /// A digit separator is allowed before any digits. |
406 | | pub const LEADING_DIGIT_SEPARATOR: u128 = |
407 | | INTEGER_LEADING_DIGIT_SEPARATOR | |
408 | | FRACTION_LEADING_DIGIT_SEPARATOR | |
409 | | EXPONENT_LEADING_DIGIT_SEPARATOR; |
410 | | |
411 | | /// A digit separator is allowed after any digits. |
412 | | pub const TRAILING_DIGIT_SEPARATOR: u128 = |
413 | | INTEGER_TRAILING_DIGIT_SEPARATOR | |
414 | | FRACTION_TRAILING_DIGIT_SEPARATOR | |
415 | | EXPONENT_TRAILING_DIGIT_SEPARATOR; |
416 | | |
417 | | /// Multiple consecutive digit separators are allowed. |
418 | | pub const CONSECUTIVE_DIGIT_SEPARATOR: u128 = |
419 | | INTEGER_CONSECUTIVE_DIGIT_SEPARATOR | |
420 | | FRACTION_CONSECUTIVE_DIGIT_SEPARATOR | |
421 | | EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR; |
422 | | |
423 | | /// Any digit separators are allowed in special (non-finite) values. |
424 | | pub const SPECIAL_DIGIT_SEPARATOR: u128 = 1 << 44; |
425 | | |
426 | | // Digit separator flags. |
427 | | const _: () = assert!(INTEGER_INTERNAL_DIGIT_SEPARATOR == 1 << 32); |
428 | | check_subsequent_flags!(INTEGER_INTERNAL_DIGIT_SEPARATOR, FRACTION_INTERNAL_DIGIT_SEPARATOR); |
429 | | check_subsequent_flags!(FRACTION_INTERNAL_DIGIT_SEPARATOR, EXPONENT_INTERNAL_DIGIT_SEPARATOR); |
430 | | check_subsequent_flags!(EXPONENT_INTERNAL_DIGIT_SEPARATOR, INTEGER_LEADING_DIGIT_SEPARATOR); |
431 | | check_subsequent_flags!(INTEGER_LEADING_DIGIT_SEPARATOR, FRACTION_LEADING_DIGIT_SEPARATOR); |
432 | | check_subsequent_flags!(FRACTION_LEADING_DIGIT_SEPARATOR, EXPONENT_LEADING_DIGIT_SEPARATOR); |
433 | | check_subsequent_flags!(EXPONENT_LEADING_DIGIT_SEPARATOR, INTEGER_TRAILING_DIGIT_SEPARATOR); |
434 | | check_subsequent_flags!(INTEGER_TRAILING_DIGIT_SEPARATOR, FRACTION_TRAILING_DIGIT_SEPARATOR); |
435 | | check_subsequent_flags!(FRACTION_TRAILING_DIGIT_SEPARATOR, EXPONENT_TRAILING_DIGIT_SEPARATOR); |
436 | | check_subsequent_flags!(EXPONENT_TRAILING_DIGIT_SEPARATOR, INTEGER_CONSECUTIVE_DIGIT_SEPARATOR); |
437 | | check_subsequent_flags!(INTEGER_CONSECUTIVE_DIGIT_SEPARATOR, FRACTION_CONSECUTIVE_DIGIT_SEPARATOR); |
438 | | check_subsequent_flags!(FRACTION_CONSECUTIVE_DIGIT_SEPARATOR, EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR); |
439 | | check_subsequent_flags!(EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR, SPECIAL_DIGIT_SEPARATOR); |
440 | | |
441 | | // CONTROL CHARACTER & RADIX MASKS |
442 | | // ------------------------------- |
443 | | |
444 | | /// Shift to convert to and from a digit separator as a `u8`. |
445 | | pub const DIGIT_SEPARATOR_SHIFT: i32 = 64; |
446 | | |
447 | | /// Mask to extract the digit separator character. |
448 | | pub const DIGIT_SEPARATOR: u128 = 0xFF << DIGIT_SEPARATOR_SHIFT; |
449 | | |
450 | | /// Shift to convert to and from a base prefix as a `u8`. |
451 | | pub const BASE_PREFIX_SHIFT: i32 = 88; |
452 | | |
453 | | /// Mask to extract the base prefix character. |
454 | | pub const BASE_PREFIX: u128 = 0xFF << BASE_PREFIX_SHIFT; |
455 | | |
456 | | /// Shift to convert to and from a base suffix as a `u8`. |
457 | | pub const BASE_SUFFIX_SHIFT: i32 = 96; |
458 | | |
459 | | /// Mask to extract the base suffix character. |
460 | | pub const BASE_SUFFIX: u128 = 0xFF << BASE_SUFFIX_SHIFT; |
461 | | |
462 | | /// Shift to convert to and from a mantissa radix as a `u32`. |
463 | | pub const MANTISSA_RADIX_SHIFT: i32 = 104; |
464 | | |
465 | | /// Mask to extract the mantissa radix: the radix for the significant digits. |
466 | | pub const MANTISSA_RADIX: u128 = 0xFF << MANTISSA_RADIX_SHIFT; |
467 | | |
468 | | /// Alias for [`MANTISSA_RADIX_SHIFT`]. |
469 | | pub const RADIX_SHIFT: i32 = MANTISSA_RADIX_SHIFT; |
470 | | |
471 | | /// Alias for [`MANTISSA_RADIX`]. |
472 | | pub const RADIX: u128 = MANTISSA_RADIX; |
473 | | |
474 | | /// Shift to convert to and from an exponent base as a `u32`. |
475 | | pub const EXPONENT_BASE_SHIFT: i32 = 112; |
476 | | |
477 | | /// Mask to extract the exponent base: the base the exponent is raised to. |
478 | | pub const EXPONENT_BASE: u128 = 0xFF << EXPONENT_BASE_SHIFT; |
479 | | |
480 | | /// Shift to convert to and from an exponent radix as a `u32`. |
481 | | pub const EXPONENT_RADIX_SHIFT: i32 = 120; |
482 | | |
483 | | /// Mask to extract the exponent radix: the radix for the exponent digits. |
484 | | pub const EXPONENT_RADIX: u128 = 0xFF << EXPONENT_RADIX_SHIFT; |
485 | | |
486 | | /// Mask to extract the exponent radix: the radix for the exponent digits. |
487 | | /// |
488 | | /// This only extracts the radix bits, so negating it can be used |
489 | | /// to see if any other custom settings were provided. |
490 | | pub const RADIX_MASK: u128 = MANTISSA_RADIX | EXPONENT_RADIX; |
491 | | |
492 | | // Masks do not overlap. |
493 | | check_subsequent_masks!(DIGIT_SEPARATOR, BASE_PREFIX); |
494 | | check_subsequent_masks!(BASE_PREFIX, BASE_SUFFIX); |
495 | | check_subsequent_masks!(BASE_SUFFIX, MANTISSA_RADIX); |
496 | | check_subsequent_masks!(MANTISSA_RADIX, EXPONENT_BASE); |
497 | | check_subsequent_masks!(EXPONENT_BASE, EXPONENT_RADIX); |
498 | | |
499 | | // Check all our shifts shift the masks to a single byte. |
500 | | check_mask_shifts!(DIGIT_SEPARATOR, DIGIT_SEPARATOR_SHIFT); |
501 | | check_mask_shifts!(BASE_PREFIX, BASE_PREFIX_SHIFT); |
502 | | check_mask_shifts!(BASE_SUFFIX, BASE_SUFFIX_SHIFT); |
503 | | check_mask_shifts!(MANTISSA_RADIX, MANTISSA_RADIX_SHIFT); |
504 | | check_mask_shifts!(EXPONENT_BASE, EXPONENT_BASE_SHIFT); |
505 | | check_mask_shifts!(EXPONENT_RADIX, EXPONENT_RADIX_SHIFT); |
506 | | |
507 | | // Check masks don't overlap with neighboring flags. |
508 | | check_masks_and_flags!(DIGIT_SEPARATOR, SPECIAL_DIGIT_SEPARATOR); |
509 | | |
510 | | // HIDDEN MASKS |
511 | | // ------------ |
512 | | |
513 | | /// Mask to extract the flag bits. |
514 | | #[doc(hidden)] |
515 | | pub const FLAG_MASK: u128 = |
516 | | REQUIRED_DIGITS | |
517 | | NO_POSITIVE_MANTISSA_SIGN | |
518 | | REQUIRED_MANTISSA_SIGN | |
519 | | NO_EXPONENT_NOTATION | |
520 | | NO_POSITIVE_EXPONENT_SIGN | |
521 | | REQUIRED_EXPONENT_SIGN | |
522 | | NO_EXPONENT_WITHOUT_FRACTION | |
523 | | NO_SPECIAL | |
524 | | CASE_SENSITIVE_SPECIAL | |
525 | | NO_INTEGER_LEADING_ZEROS | |
526 | | NO_FLOAT_LEADING_ZEROS | |
527 | | REQUIRED_EXPONENT_NOTATION | |
528 | | CASE_SENSITIVE_EXPONENT | |
529 | | CASE_SENSITIVE_BASE_PREFIX | |
530 | | CASE_SENSITIVE_BASE_SUFFIX | |
531 | | INTERNAL_DIGIT_SEPARATOR | |
532 | | LEADING_DIGIT_SEPARATOR | |
533 | | TRAILING_DIGIT_SEPARATOR | |
534 | | CONSECUTIVE_DIGIT_SEPARATOR | |
535 | | SPECIAL_DIGIT_SEPARATOR; |
536 | | |
537 | | /// Mask to extract the flag bits controlling interface parsing. |
538 | | /// |
539 | | /// This mask controls all the flags handled by the interface, |
540 | | /// omitting those that are handled prior. This limits the |
541 | | /// number of match paths required to determine the correct |
542 | | /// interface. |
543 | | #[doc(hidden)] |
544 | | pub const INTERFACE_FLAG_MASK: u128 = |
545 | | REQUIRED_DIGITS | |
546 | | NO_EXPONENT_NOTATION | |
547 | | NO_POSITIVE_EXPONENT_SIGN | |
548 | | REQUIRED_EXPONENT_SIGN | |
549 | | NO_EXPONENT_WITHOUT_FRACTION | |
550 | | NO_FLOAT_LEADING_ZEROS | |
551 | | REQUIRED_EXPONENT_NOTATION | |
552 | | INTERNAL_DIGIT_SEPARATOR | |
553 | | LEADING_DIGIT_SEPARATOR | |
554 | | TRAILING_DIGIT_SEPARATOR | |
555 | | CONSECUTIVE_DIGIT_SEPARATOR; |
556 | | |
557 | | /// Mask to extract digit separator flags. |
558 | | #[doc(hidden)] |
559 | | pub const DIGIT_SEPARATOR_FLAG_MASK: u128 = |
560 | | INTERNAL_DIGIT_SEPARATOR | |
561 | | LEADING_DIGIT_SEPARATOR | |
562 | | TRAILING_DIGIT_SEPARATOR | |
563 | | CONSECUTIVE_DIGIT_SEPARATOR | |
564 | | SPECIAL_DIGIT_SEPARATOR; |
565 | | |
566 | | /// Mask to extract exponent flags. |
567 | | #[doc(hidden)] |
568 | | pub const EXPONENT_FLAG_MASK: u128 = |
569 | | REQUIRED_EXPONENT_DIGITS | |
570 | | NO_EXPONENT_NOTATION | |
571 | | NO_POSITIVE_EXPONENT_SIGN | |
572 | | REQUIRED_EXPONENT_SIGN | |
573 | | NO_EXPONENT_WITHOUT_FRACTION | |
574 | | REQUIRED_EXPONENT_NOTATION | |
575 | | EXPONENT_INTERNAL_DIGIT_SEPARATOR | |
576 | | EXPONENT_LEADING_DIGIT_SEPARATOR | |
577 | | EXPONENT_TRAILING_DIGIT_SEPARATOR | |
578 | | EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR; |
579 | | |
580 | | /// Mask to extract integer digit separator flags. |
581 | | #[doc(hidden)] |
582 | | pub const INTEGER_DIGIT_SEPARATOR_FLAG_MASK: u128 = |
583 | | INTEGER_INTERNAL_DIGIT_SEPARATOR | |
584 | | INTEGER_LEADING_DIGIT_SEPARATOR | |
585 | | INTEGER_TRAILING_DIGIT_SEPARATOR | |
586 | | INTEGER_CONSECUTIVE_DIGIT_SEPARATOR; |
587 | | |
588 | | /// Mask to extract fraction digit separator flags. |
589 | | #[doc(hidden)] |
590 | | pub const FRACTION_DIGIT_SEPARATOR_FLAG_MASK: u128 = |
591 | | FRACTION_INTERNAL_DIGIT_SEPARATOR | |
592 | | FRACTION_LEADING_DIGIT_SEPARATOR | |
593 | | FRACTION_TRAILING_DIGIT_SEPARATOR | |
594 | | FRACTION_CONSECUTIVE_DIGIT_SEPARATOR; |
595 | | |
596 | | /// Mask to extract exponent digit separator flags. |
597 | | #[doc(hidden)] |
598 | | pub const EXPONENT_DIGIT_SEPARATOR_FLAG_MASK: u128 = |
599 | | EXPONENT_INTERNAL_DIGIT_SEPARATOR | |
600 | | EXPONENT_LEADING_DIGIT_SEPARATOR | |
601 | | EXPONENT_TRAILING_DIGIT_SEPARATOR | |
602 | | EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR; |
603 | | |
604 | | // EXTRACTORS |
605 | | // ---------- |
606 | | |
607 | | /// Extract the digit separator from the format packed struct. |
608 | | #[doc(hidden)] |
609 | | #[inline(always)] |
610 | 28.4k | pub const fn digit_separator(format: u128) -> u8 { |
611 | 28.4k | ((format & DIGIT_SEPARATOR) >> DIGIT_SEPARATOR_SHIFT) as u8 |
612 | 28.4k | } |
613 | | |
614 | | /// Extract the base prefix character from the format packed struct. |
615 | | #[doc(hidden)] |
616 | | #[inline(always)] |
617 | 18.9k | pub const fn base_prefix(format: u128) -> u8 { |
618 | 18.9k | ((format & BASE_PREFIX) >> BASE_PREFIX_SHIFT) as u8 |
619 | 18.9k | } |
620 | | |
621 | | /// Extract the base suffix character from the format packed struct. |
622 | | #[doc(hidden)] |
623 | | #[inline(always)] |
624 | 18.9k | pub const fn base_suffix(format: u128) -> u8 { |
625 | 18.9k | ((format & BASE_SUFFIX) >> BASE_SUFFIX_SHIFT) as u8 |
626 | 18.9k | } |
627 | | |
628 | | /// Extract the mantissa radix from the format packed struct. |
629 | | #[doc(hidden)] |
630 | | #[inline(always)] |
631 | 28.4k | pub const fn mantissa_radix(format: u128) -> u32 { |
632 | 28.4k | ((format & MANTISSA_RADIX) >> MANTISSA_RADIX_SHIFT) as u32 |
633 | 28.4k | } |
634 | | |
635 | | /// Extract the exponent base from the format packed struct. |
636 | | /// |
637 | | /// If not provided, defaults to `mantissa_radix`. |
638 | | #[doc(hidden)] |
639 | | #[inline(always)] |
640 | 9.46k | pub const fn exponent_base(format: u128) -> u32 { |
641 | 9.46k | let radix = ((format & EXPONENT_BASE) >> EXPONENT_BASE_SHIFT) as u32; |
642 | 9.46k | if radix == 0 { |
643 | 9.46k | mantissa_radix(format) |
644 | | } else { |
645 | 0 | radix |
646 | | } |
647 | 9.46k | } |
648 | | |
649 | | /// Extract the exponent radix from the format packed struct. |
650 | | /// |
651 | | /// If not provided, defaults to `mantissa_radix`. |
652 | | #[doc(hidden)] |
653 | | #[inline(always)] |
654 | 9.46k | pub const fn exponent_radix(format: u128) -> u32 { |
655 | 9.46k | let radix = ((format & EXPONENT_RADIX) >> EXPONENT_RADIX_SHIFT) as u32; |
656 | 9.46k | if radix == 0 { |
657 | 9.46k | mantissa_radix(format) |
658 | | } else { |
659 | 0 | radix |
660 | | } |
661 | 9.46k | } |
662 | | |
663 | | /// Extract a generic radix from the format and bitflags. |
664 | | #[doc(hidden)] |
665 | | #[inline(always)] |
666 | | pub const fn radix_from_flags(format: u128, mask: u128, shift: i32) -> u32 { |
667 | | let radix = ((format & mask) >> shift) as u32; |
668 | | if radix == 0 { |
669 | | mantissa_radix(format) |
670 | | } else { |
671 | | radix |
672 | | } |
673 | | } |
674 | | |
675 | | // VALIDATORS |
676 | | // ---------- |
677 | | |
678 | | // NOTE: All of these are only used when building formats so it doesn't matter if |
679 | | // they have performance issues, since these will be built at compile time. |
680 | | |
681 | | /// Determine if the provided exponent flags are valid. |
682 | | #[inline(always)] |
683 | | pub const fn is_valid_exponent_flags(format: u128) -> bool { |
684 | | // Both cannot be set. |
685 | | format & NO_EXPONENT_NOTATION == 0 || format & REQUIRED_EXPONENT_NOTATION == 0 |
686 | | } |
687 | | |
688 | | /// Determine if an optional control character is valid. |
689 | | #[doc(hidden)] |
690 | | #[inline(always)] |
691 | | const fn is_valid_optional_control_radix(radix: u32, value: u8) -> bool { |
692 | | // Validate the character isn't a digit or sign character, and is valid ASCII. |
693 | | use crate::ascii::is_valid_ascii; |
694 | | use crate::digit::char_is_digit_const; |
695 | | !char_is_digit_const(value, radix) && |
696 | | value != b'+' && |
697 | | value != b'-' && |
698 | | (is_valid_ascii(value) || value == 0) |
699 | | } |
700 | | |
701 | | /// Determine if an optional control character is valid. |
702 | | #[doc(hidden)] |
703 | | #[inline(always)] |
704 | | const fn is_valid_optional_control(format: u128, value: u8) -> bool { |
705 | | // Need to get the larger of the two radix values, since these |
706 | | // will be the characters that define the valid digits. |
707 | | // const fn doesn't support max as of 1.55 nightly. |
708 | | let mradix = mantissa_radix(format); |
709 | | let eradix = exponent_radix(format); |
710 | | let radix = if mradix > eradix { |
711 | | mradix |
712 | | } else { |
713 | | eradix |
714 | | }; |
715 | | is_valid_optional_control_radix(radix, value) |
716 | | } |
717 | | |
718 | | /// Determine if an control character is valid. |
719 | | #[doc(hidden)] |
720 | | #[inline(always)] |
721 | | const fn is_valid_control(format: u128, value: u8) -> bool { |
722 | | value != 0 && is_valid_optional_control(format, value) |
723 | | } |
724 | | |
725 | | /// Determine if the digit separator is valid. |
726 | | /// |
727 | | /// Digit separators must not be valid digits or sign characters. |
728 | | #[inline(always)] |
729 | 9.46k | pub const fn is_valid_digit_separator(format: u128) -> bool { |
730 | 9.46k | let value = digit_separator(format); |
731 | 9.46k | if cfg!(feature = "format") { |
732 | 0 | is_valid_optional_control(format, value) |
733 | | } else { |
734 | 9.46k | value == 0 |
735 | | } |
736 | 9.46k | } |
737 | | |
738 | | /// Determine if the base prefix character is valid. |
739 | | #[inline(always)] |
740 | 9.46k | pub const fn is_valid_base_prefix(format: u128) -> bool { |
741 | 9.46k | let value = base_prefix(format); |
742 | 9.46k | if cfg!(all(feature = "format", feature = "power-of-two")) { |
743 | 0 | is_valid_optional_control(format, value) |
744 | | } else { |
745 | 9.46k | value == 0 |
746 | | } |
747 | 9.46k | } |
748 | | |
749 | | /// Determine if the base suffix character is valid. |
750 | | #[inline(always)] |
751 | 9.46k | pub const fn is_valid_base_suffix(format: u128) -> bool { |
752 | 9.46k | let value = base_suffix(format); |
753 | 9.46k | if cfg!(all(feature = "format", feature = "power-of-two")) { |
754 | 0 | is_valid_optional_control(format, value) |
755 | | } else { |
756 | 9.46k | value == 0 |
757 | | } |
758 | 9.46k | } |
759 | | |
760 | | /// Determine if all of the "punctuation" characters are valid. |
761 | | #[inline(always)] |
762 | | #[allow(clippy::if_same_then_else)] // reason="all are different logic conditions" |
763 | 9.46k | pub const fn is_valid_punctuation(format: u128) -> bool { |
764 | | // All the checks against optional characters with mandatory are fine: |
765 | | // if they're not 0, then they can't overlap, and mandatory can't be 0. |
766 | 9.46k | if cfg!(not(feature = "format")) && digit_separator(format) != 0 { |
767 | | // Digit separator set when not allowed. |
768 | 0 | false |
769 | | } else { |
770 | 9.46k | let separator = digit_separator(format); |
771 | 9.46k | let prefix = base_prefix(format); |
772 | 9.46k | let suffix = base_suffix(format); |
773 | | // Check all are optional, or enough are not present. |
774 | 9.46k | match (separator, prefix, suffix) { |
775 | 9.46k | (0, 0, 0) => true, |
776 | 0 | (_, 0, 0) => true, |
777 | 0 | (0, _, 0) => true, |
778 | 0 | (0, 0, _) => true, |
779 | | // Can't have more than 1 0, check they're all different. |
780 | 0 | (x, y, z) => x != y && x != z && y != z, |
781 | | } |
782 | | } |
783 | 9.46k | } |
784 | | |
785 | | /// Determine if all of the "punctuation" characters for the options API are valid. |
786 | | #[doc(hidden)] |
787 | | #[inline(always)] |
788 | | #[allow(clippy::if_same_then_else)] // reason="all are different logic conditions" |
789 | | #[allow(clippy::needless_bool)] // reason="not needless depending on the format condition" |
790 | | pub const fn is_valid_options_punctuation(format: u128, exponent: u8, decimal_point: u8) -> bool { |
791 | | // All the checks against optional characters with mandatory are fine: |
792 | | // if they're not 0, then they can't overlap, and mandatory can't be 0. |
793 | | if !is_valid_control(format, decimal_point) || !is_valid_control(format, exponent) { |
794 | | // Must be in the valid range. |
795 | | false |
796 | | } else if decimal_point == exponent { |
797 | | // Can't have overlapping characters. |
798 | | false |
799 | | } else if cfg!(feature = "format") && digit_separator(format) == decimal_point { |
800 | | false |
801 | | } else if cfg!(feature = "format") && digit_separator(format) == exponent { |
802 | | false |
803 | | } else if cfg!(feature = "format") && base_prefix(format) == decimal_point { |
804 | | false |
805 | | } else if cfg!(feature = "format") && base_prefix(format) == exponent { |
806 | | false |
807 | | } else if cfg!(feature = "format") && base_suffix(format) == decimal_point { |
808 | | false |
809 | | } else if cfg!(feature = "format") && base_suffix(format) == exponent { |
810 | | false |
811 | | } else { |
812 | | true |
813 | | } |
814 | | } |
815 | | |
816 | | /// Determine if the radix is valid. |
817 | | #[inline(always)] |
818 | 28.4k | pub const fn is_valid_radix(radix: u32) -> bool { |
819 | 28.4k | if cfg!(feature = "radix") { |
820 | 0 | radix >= 2 && radix <= 36 |
821 | 28.4k | } else if cfg!(feature = "power-of-two") { |
822 | 0 | matches!(radix, 2 | 4 | 8 | 10 | 16 | 32) |
823 | | } else { |
824 | 28.4k | radix == 10 |
825 | | } |
826 | 28.4k | } |