Skip to main content

pdf_lib_rs/core/syntax/
classification.rs

1use super::CharCodes;
2
3/// Check if a byte is a PDF whitespace character.
4pub fn is_whitespace(byte: u8) -> bool {
5    matches!(
6        byte,
7        CharCodes::Null
8            | CharCodes::Tab
9            | CharCodes::Newline
10            | CharCodes::FormFeed
11            | CharCodes::CarriageReturn
12            | CharCodes::Space
13    )
14}
15
16/// Check if a byte is a PDF delimiter character.
17pub fn is_delimiter(byte: u8) -> bool {
18    matches!(
19        byte,
20        CharCodes::LeftParen
21            | CharCodes::RightParen
22            | CharCodes::LessThan
23            | CharCodes::GreaterThan
24            | CharCodes::LeftSquareBracket
25            | CharCodes::RightSquareBracket
26            | CharCodes::LeftCurly
27            | CharCodes::RightCurly
28            | CharCodes::ForwardSlash
29            | CharCodes::Percent
30    )
31}
32
33/// Check if a byte is an "irregular" character (whitespace, delimiter, or hash).
34pub fn is_irregular(byte: u8) -> bool {
35    is_whitespace(byte) || is_delimiter(byte) || byte == CharCodes::Hash
36}
37
38/// Check if a byte is a digit (0-9).
39pub fn is_digit(byte: u8) -> bool {
40    (CharCodes::Zero..=CharCodes::Nine).contains(&byte)
41}
42
43/// Check if a byte is a numeric prefix (+, -, .).
44pub fn is_numeric_prefix(byte: u8) -> bool {
45    matches!(byte, CharCodes::Period | CharCodes::Plus | CharCodes::Minus)
46}
47
48/// Check if a byte is numeric (digit or numeric prefix).
49pub fn is_numeric(byte: u8) -> bool {
50    is_digit(byte) || is_numeric_prefix(byte)
51}
52
53/// Check if a character code is a "regular" character for PDF names.
54/// Regular characters are ! through ~ excluding irregular characters.
55pub fn is_regular_char(code: u8) -> bool {
56    (CharCodes::ExclamationPoint..=CharCodes::Tilde).contains(&code) && !is_irregular(code)
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn test_whitespace() {
65        assert!(is_whitespace(0));   // Null
66        assert!(is_whitespace(9));   // Tab
67        assert!(is_whitespace(10));  // Newline
68        assert!(is_whitespace(12));  // FormFeed
69        assert!(is_whitespace(13));  // CarriageReturn
70        assert!(is_whitespace(32));  // Space
71        assert!(!is_whitespace(65)); // 'A'
72    }
73
74    #[test]
75    fn test_delimiter() {
76        assert!(is_delimiter(b'('));
77        assert!(is_delimiter(b')'));
78        assert!(is_delimiter(b'<'));
79        assert!(is_delimiter(b'>'));
80        assert!(is_delimiter(b'['));
81        assert!(is_delimiter(b']'));
82        assert!(is_delimiter(b'{'));
83        assert!(is_delimiter(b'}'));
84        assert!(is_delimiter(b'/'));
85        assert!(is_delimiter(b'%'));
86        assert!(!is_delimiter(b'A'));
87    }
88
89    #[test]
90    fn test_is_digit() {
91        for d in b'0'..=b'9' {
92            assert!(is_digit(d));
93        }
94        assert!(!is_digit(b'A'));
95        assert!(!is_digit(b' '));
96    }
97}