Skip to main content

abnf_core/
lib.rs

1//!
2//! Parsing of ABNF Core Rules
3//!
4//! See <https://tools.ietf.org/html/rfc5234#appendix-B.1>
5//!
6
7#![no_std]
8
9pub mod complete;
10pub mod streaming;
11
12use nom::AsChar;
13
14/// A-Z / a-z
15///
16/// ALPHA = %x41-5A / %x61-7A
17pub fn is_alpha(c: impl AsChar) -> bool {
18    matches!(c.as_char(), '\x41'..='\x5A' | '\x61'..='\x7A')
19}
20
21/// BIT = "0" / "1"
22/// BIT = %x30 / %x31
23pub fn is_bit(c: impl AsChar) -> bool {
24    matches!(c.as_char(), '\x30'..='\x31')
25}
26
27/// Any 7-bit US-ASCII character, excluding NUL
28///
29/// CHAR = %x01-7F
30pub fn is_char(c: impl AsChar) -> bool {
31    matches!(c.as_char(), '\x01'..='\x7F')
32}
33
34/// Carriage return
35///
36/// CR = %x0D
37pub fn is_cr(c: impl AsChar) -> bool {
38    matches!(c.as_char(), '\x0D')
39}
40
41// CRLF
42// Not implemented as predicate.
43
44/// Controls
45///
46/// CTL = %x00-1F / %x7F
47pub fn is_ctl(c: impl AsChar) -> bool {
48    matches!(c.as_char(), '\x00'..='\x1F' | '\x7F')
49}
50
51/// 0-9
52///
53/// DIGIT = %x30-39
54pub fn is_digit(c: impl AsChar) -> bool {
55    matches!(c.as_char(), '\x30'..='\x39')
56}
57
58/// Double Quote (")
59///
60/// DQUOTE = %x22
61pub fn is_dquote(c: impl AsChar) -> bool {
62    matches!(c.as_char(), '\x22')
63}
64
65/// HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
66///
67/// Note: ABNF strings are case-insensitive so `a` / ... / `f` are allowed, too.
68/// Issue: <https://github.com/duesee/abnf-core/issues/12>
69pub fn is_hexdig(c: impl AsChar) -> bool {
70    matches!(c.as_char(), '0'..='9' | 'a'..='f' | 'A'..='F')
71}
72
73/// Horizontal tab
74///
75/// HTAB = %x09
76pub fn is_htab(c: impl AsChar) -> bool {
77    matches!(c.as_char(), '\x09')
78}
79
80/// Linefeed
81///
82/// LF = %x0A
83pub fn is_lf(c: impl AsChar) -> bool {
84    matches!(c.as_char(), '\x0A')
85}
86
87// LWSP
88// Not implemented as predicate.
89
90/// 8 bits of data
91///
92/// OCTET = %x00-FF
93pub fn is_octet(_: u8) -> bool {
94    true
95}
96
97/// Space
98///
99/// SP = %x20
100pub fn is_sp(c: impl AsChar) -> bool {
101    matches!(c.as_char(), '\x20')
102}
103
104/// Visible (printing) characters
105///
106/// VCHAR = %x21-7E
107pub fn is_vchar(c: impl AsChar) -> bool {
108    matches!(c.as_char(), '\x21'..='\x7E')
109}
110
111/// White space
112///
113/// WSP = SP / HTAB
114pub fn is_wsp(c: impl AsChar) -> bool {
115    matches!(c.as_char(), '\x20' | '\x09')
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121
122    #[test]
123    fn test_is_alpha() {
124        assert!(is_alpha(b'a'));
125        assert!(is_alpha('A'));
126        assert!(is_alpha('z'));
127        assert!(is_alpha('Z'));
128        assert!(!is_alpha('0'));
129        assert!(!is_alpha('9'));
130        assert!(!is_alpha('#'));
131    }
132
133    #[test]
134    fn test_is_bit() {
135        assert!(is_bit(b'0'));
136        assert!(is_bit('1'));
137        assert!(!is_bit('2'));
138        assert!(!is_bit('a'));
139        assert!(!is_bit('A'));
140        assert!(!is_bit('z'));
141        assert!(!is_bit('Z'));
142        assert!(!is_bit('#'));
143    }
144
145    #[test]
146    fn test_is_char() {
147        assert!(is_char(b'a'));
148        assert!(is_char('A'));
149        assert!(is_char('z'));
150        assert!(is_char('Z'));
151        assert!(is_char('\x7F'));
152        assert!(!is_char('\x00'));
153    }
154
155    #[test]
156    fn test_is_cr() {
157        assert!(is_cr(b'\r'));
158        assert!(!is_cr('\n'));
159        assert!(!is_cr('a'));
160        assert!(!is_cr('A'));
161        assert!(!is_cr('z'));
162        assert!(!is_cr('Z'));
163    }
164
165    #[test]
166    fn test_is_ctl() {
167        assert!(is_ctl(b'\x00'));
168        assert!(is_ctl('\x1F'));
169        assert!(is_ctl('\x7F'));
170        assert!(!is_ctl('a'));
171        assert!(!is_ctl('A'));
172        assert!(!is_ctl('z'));
173        assert!(!is_ctl('Z'));
174    }
175
176    #[test]
177    fn test_is_digit() {
178        assert!(is_digit(b'0'));
179        assert!(is_digit('9'));
180        assert!(!is_digit('a'));
181        assert!(!is_digit('A'));
182        assert!(!is_digit('z'));
183        assert!(!is_digit('Z'));
184    }
185
186    #[test]
187    fn test_is_dquote() {
188        assert!(is_dquote(b'"'));
189        assert!(!is_dquote('\''));
190        assert!(!is_dquote('a'));
191        assert!(!is_dquote('A'));
192        assert!(!is_dquote('z'));
193        assert!(!is_dquote('Z'));
194    }
195
196    #[test]
197    fn test_is_hexdig() {
198        assert!(is_hexdig(b'0'));
199        assert!(is_hexdig('9'));
200        assert!(is_hexdig('a'));
201        assert!(is_hexdig('f'));
202        assert!(is_hexdig('A'));
203        assert!(is_hexdig('F'));
204        assert!(!is_hexdig('z'));
205        assert!(!is_hexdig('Z'));
206    }
207
208    #[test]
209    fn test_is_htab() {
210        assert!(is_htab(b'\t'));
211    }
212
213    #[test]
214    fn test_is_lf() {
215        assert!(is_lf(b'\n'));
216        assert!(!is_lf('\r'));
217        assert!(!is_lf('a'));
218        assert!(!is_lf('A'));
219        assert!(!is_lf('z'));
220        assert!(!is_lf('Z'));
221    }
222
223    #[test]
224    fn test_is_octet() {
225        assert!(is_octet(0x00));
226        assert!(is_octet(0x7F));
227        assert!(is_octet(0xFF));
228    }
229
230    #[test]
231    fn test_is_sp() {
232        assert!(is_sp(b' '));
233        assert!(!is_sp('\t'));
234        assert!(!is_sp('a'));
235        assert!(!is_sp('A'));
236        assert!(!is_sp('z'));
237        assert!(!is_sp('Z'));
238    }
239
240    #[test]
241    fn test_is_vchar() {
242        assert!(is_vchar(b'!'));
243        assert!(is_vchar('~'));
244        assert!(!is_vchar('\x20'));
245        assert!(!is_vchar('\x7F'));
246    }
247
248    #[test]
249    fn test_is_wsp() {
250        assert!(is_wsp(b' '));
251        assert!(is_wsp('\t'));
252        assert!(!is_wsp('a'));
253        assert!(!is_wsp('A'));
254        assert!(!is_wsp('z'));
255        assert!(!is_wsp('Z'));
256    }
257}