Coverage Report

Created: 2026-01-13 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/lexical-util-1.0.7/src/digit.rs
Line
Count
Source
1
//! Utilities to process digits.
2
//!
3
//! This both contains routines to convert to and from digits,
4
//! as well as iterate over digits while skipping digit separators.
5
6
// CONST FNS
7
// ---------
8
9
// These are optimized functions for when the radix is known at compile-time,
10
// which is **most** of our cases. There are cases where for code generation,
11
// using a runtime algorithm is preferable.
12
13
/// Unchecked, highly optimized algorithm to convert a char to a digit.
14
/// This only works if the input character is known to be a valid digit.
15
#[inline(always)]
16
30.9k
pub const fn char_to_valid_digit_const(c: u8, radix: u32) -> u32 {
17
30.9k
    if radix <= 10 {
18
        // Optimize for small radixes.
19
30.9k
        (c.wrapping_sub(b'0')) as u32
20
    } else {
21
        // Fallback, still decently fast.
22
0
        let digit = match c {
23
0
            b'0'..=b'9' => c - b'0',
24
0
            b'A'..=b'Z' => c - b'A' + 10,
25
0
            b'a'..=b'z' => c - b'a' + 10,
26
0
            _ => 0xFF,
27
        };
28
0
        digit as u32
29
    }
30
30.9k
}
31
32
/// Convert a character to a digit with a radix known at compile time.
33
///
34
/// This optimizes for cases where radix is <= 10, and uses a decent,
35
/// match-based fallback algorithm.
36
#[inline(always)]
37
30.0k
pub const fn char_to_digit_const(c: u8, radix: u32) -> Option<u32> {
38
30.0k
    let digit = char_to_valid_digit_const(c, radix);
39
30.0k
    if digit < radix {
40
29.3k
        Some(digit)
41
    } else {
42
686
        None
43
    }
44
30.0k
}
45
46
/// Determine if a character is a digit with a radix known at compile time.
47
#[inline(always)]
48
0
pub const fn char_is_digit_const(c: u8, radix: u32) -> bool {
49
0
    char_to_digit_const(c, radix).is_some()
50
0
}
51
52
/// Convert a digit to a character with a radix known at compile time.
53
///
54
/// This optimizes for cases where radix is <= 10, and uses a decent,
55
/// match-based fallback algorithm.
56
#[inline(always)]
57
#[cfg(any(feature = "parse-floats", feature = "write-floats", feature = "write-integers"))]
58
0
pub const fn digit_to_char_const(digit: u32, radix: u32) -> u8 {
59
0
    if radix <= 10 || digit < 10 {
60
        // Can short-circuit if we know the radix is small at compile time.
61
0
        digit as u8 + b'0'
62
    } else {
63
0
        digit as u8 + b'A' - 10
64
    }
65
0
}
66
67
// NON-CONST
68
// ---------
69
70
// These are less optimized functions for when the radix is not known at
71
// compile-time, which is a few (but important) cases. These generally have
72
// improved compiler optimization passes when generics are used more sparingly.
73
74
/// Convert a character to a digit.
75
#[inline(always)]
76
#[cfg(any(feature = "parse-floats", feature = "parse-integers"))]
77
0
pub const fn char_to_digit(c: u8, radix: u32) -> Option<u32> {
78
    // Fallback, still decently fast.
79
0
    let digit = match c {
80
0
        b'0'..=b'9' => c - b'0',
81
0
        b'A'..=b'Z' => c - b'A' + 10,
82
0
        b'a'..=b'z' => c - b'a' + 10,
83
0
        _ => 0xFF,
84
    } as u32;
85
0
    if digit < radix {
86
0
        Some(digit)
87
    } else {
88
0
        None
89
    }
90
0
}
91
92
/// Determine if a character is a digit.
93
#[inline(always)]
94
#[cfg(any(feature = "parse-floats", feature = "parse-integers"))]
95
0
pub const fn char_is_digit(c: u8, radix: u32) -> bool {
96
0
    char_to_digit(c, radix).is_some()
97
0
}
98
99
/// Convert a digit to a character. This uses a pre-computed table to avoid
100
/// branching.
101
///
102
/// # Panics
103
///
104
/// Panics if `digit >= 36`.
105
#[inline(always)]
106
#[cfg(any(feature = "write-floats", feature = "write-integers"))]
107
pub fn digit_to_char(digit: u32) -> u8 {
108
    const TABLE: [u8; 36] = [
109
        b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'A', b'B', b'C', b'D', b'E',
110
        b'F', b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P', b'Q', b'R', b'S', b'T',
111
        b'U', b'V', b'W', b'X', b'Y', b'Z',
112
    ];
113
    debug_assert!(digit < 36, "digit_to_char() invalid character.");
114
    TABLE[digit as usize]
115
}