1use nom::{space, not_line_ending, alphanumeric, ErrorKind};
6
7named!(comment<()>,
8 chain!(tag!("#") ~
9 not_line_ending,
10 || ()));
11
12named!(endl<()>,
13 chain!(space? ~
14 comment? ~
15 char!('\r')? ~
16 char!('\n'),
17 || ()));
18
19named!(token<Token>,
20 map_res!(recognize!(many1!(alt!(alphanumeric | tag!("_")))),
21 |bv: &[_]| String::from_utf8(bv.to_owned())));
22
23named!(hex_digit<u8>,
24 map!(one_of!(b"0123456789abcdefABCDEF"), |b| match b {
25 '0' ... '9' => b as u8 - b'0',
26 'a' ... 'f' => b as u8 - b'a' + 10,
27 'A' ... 'F' => b as u8 - b'A' + 10,
28 _ => unreachable!()
29 }));
30named!(octal_digit<u8>, map!(one_of!("01234567"), |b| b as u8 - b'0'));
31named!(quad_digit<u8>, map!(one_of!("0123"), |b| b as u8 - b'0'));
32
33named!(octal_esc<u8>,
34 chain!(tag!("\\") ~
35 a: quad_digit ~
36 b: octal_digit ~
37 c: octal_digit,
38 || { a << 6 | b << 3 | c }));
39
40named!(hex_esc<u8>,
41 chain!(tag!("\\x") ~
42 a: hex_digit ~
43 b: hex_digit,
44 || { a << 4 | b }));
45
46named!(quoted_string<String>,
47 delimited!(tag!("\""),
48 map_res!(many0!(alt!(map!(none_of!("\\\""), |b| b as u8) | hex_esc)),
49 String::from_utf8),
50 tag!("\"")));
51
52named!(multiline_octal<Vec<u8> >,
53 many0!(preceded!(leading_junk, octal_esc)));
54
55named!(type_and_value<Value>,
56 alt!(preceded!(tag!("MULTILINE_OCTAL"),
57 error!(ErrorKind::Alt,
58 chain!(endl ~
59 bits: multiline_octal ~
60 endl ~
61 tag!("END") ~
62 endl,
63 || Value::Binary(bits)))) |
64 preceded!(tag!("UTF8"),
65 error!(ErrorKind::Alt,
67 chain!(space ~
68 value: quoted_string ~
69 endl,
70 || Value::String(value)))) |
71 chain!(type_tag: token ~
72 space ~
73 value: token ~
74 endl,
75 || Value::Token(type_tag, value))));
76
77named!(pub attribute<Attr>,
78 chain!(leading_junk ~
79 key: token ~
80 space ~
81 value: type_and_value,
82 || (key, value)));
83
84named!(pub leading_junk<()>,
85 chain!(fold_many0!(endl, (), |(), ()| ()) ~ space?, || ()));
86
87named!(pub begindata<()>,
88 chain!(leading_junk ~
89 tag!("BEGINDATA") ~
90 endl,
91 || ()));
92
93pub type Token = String;
94pub type Type = Token;
95pub type Attr = (Token, Value);
96
97#[derive(Clone, Debug, PartialEq, Eq)]
98pub enum Value {
99 Token(Type, Token),
100 String(String),
101 Binary(Vec<u8>), }
103
104impl Value {
105 pub fn get_type(&self) -> &str {
106 match *self {
107 Value::Token(ref ttype, _) => ttype,
108 Value::String(_) => "UTF8",
109 Value::Binary(_) => "MULTILINE_OCTAL",
110 }
111 }
112 pub fn into_type(self) -> String {
113 match self {
114 Value::Token(ttype, _) => ttype,
115 _ => self.get_type().to_owned(),
116 }
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::{comment, endl, token, quad_digit, octal_digit, hex_digit, octal_esc, hex_esc,
123 quoted_string, multiline_octal, type_and_value, attribute, Value};
124 use nom::IResult::*;
125 use nom::{Needed, ErrorKind, Err};
126
127 #[test]
128 fn test_comment() {
129 assert_eq!(comment(b"# thing"), Done(&b""[..], ()));
130 assert_eq!(comment(b"#thing"), Done(&b""[..], ()));
131 assert_eq!(comment("# ýŷỳ".as_bytes()), Done(&b""[..], ()));
132 assert_eq!(comment(b"#"), Done(&b""[..], ()));
133 assert_eq!(comment(b""), Incomplete(Needed::Size(1)));
134 assert_eq!(comment(b"# thing\n stuff"), Done(&b"\n stuff"[..], ()));
135 assert_eq!(comment(b"bees"), Error(Err::Position(ErrorKind::Tag, &b"bees"[..])));
136 assert_eq!(comment(b" #bees"), Error(Err::Position(ErrorKind::Tag, &b" #bees"[..])));
137 }
138
139 #[test]
140 fn test_endl() {
141 assert_eq!(endl(b"\n"), Done(&b""[..], ()));
142 assert_eq!(endl(b"\r\n"), Done(&b""[..], ()));
143 assert_eq!(endl(b"\n\n"), Done(&b"\n"[..], ()));
144 assert_eq!(endl(b"\n "), Done(&b" "[..], ()));
145 assert_eq!(endl(b" \n"), Done(&b""[..], ()));
146 assert_eq!(endl(b" \n"), Done(&b""[..], ()));
147 assert_eq!(endl(b"\t\n"), Done(&b""[..], ()));
148 assert_eq!(endl(b"# bees \n"), Done(&b""[..], ()));
149 assert_eq!(endl(b" # bees \n"), Done(&b""[..], ()));
150 assert_eq!(endl(b" bees \n"), Error(Err::Position(ErrorKind::Char, &b"bees \n"[..])));
151 assert_eq!(endl(b"# bees"), Incomplete(Needed::Size("# bees".len() + 1)));
152 }
153
154 #[test]
155 fn test_token() {
156 assert_eq!(token(b"CK_TRUE"), Done(&b""[..], "CK_TRUE".to_owned()));
157 assert_eq!(token(b"UTF8"), Done(&b""[..], "UTF8".to_owned()));
158 assert_eq!(token(b"CKA_CERT_MD5_HASH"), Done(&b""[..], "CKA_CERT_MD5_HASH".to_owned()));
159 assert_eq!(token(b"UTF8 "), Done(&b" "[..], "UTF8".to_owned()));
160 assert_eq!(token(b"UTF8\n"), Done(&b"\n"[..], "UTF8".to_owned()));
161 assert_eq!(token(b" UTF8"), Error(Err::Position(ErrorKind::Many1, &b" UTF8"[..])));
162 assert_eq!(token(b"\"UTF8\""), Error(Err::Position(ErrorKind::Many1, &b"\"UTF8\""[..])));
163 assert_eq!(token(b"\\x41"), Error(Err::Position(ErrorKind::Many1, &b"\\x41"[..])));
164 assert_eq!(token(b"\\101"), Error(Err::Position(ErrorKind::Many1, &b"\\101"[..])));
165 assert_eq!(token(b""), Incomplete(Needed::Size(1)))
166 }
167
168 #[test]
169 fn test_digits() {
170 assert_eq!(quad_digit(b"0"), Done(&b""[..], 0));
171 assert_eq!(octal_digit(b"0"), Done(&b""[..], 0));
172 assert_eq!(hex_digit(b"0"), Done(&b""[..], 0));
173
174 assert_eq!(quad_digit(b"00"), Done(&b"0"[..], 0));
175 assert_eq!(octal_digit(b"00"), Done(&b"0"[..], 0));
176 assert_eq!(hex_digit(b"00"), Done(&b"0"[..], 0));
177
178 assert_eq!(quad_digit(b"32"), Done(&b"2"[..], 3));
179 assert_eq!(octal_digit(b"76"), Done(&b"6"[..], 7));
180 assert_eq!(hex_digit(b"98"), Done(&b"8"[..], 9));
181
182 assert_eq!(quad_digit(b"4"), Error(Err::Position(ErrorKind::OneOf, &b"4"[..])));
183 assert_eq!(octal_digit(b"8"), Error(Err::Position(ErrorKind::OneOf, &b"8"[..])));
184 assert_eq!(hex_digit(b"g"), Error(Err::Position(ErrorKind::OneOf, &b"g"[..])));
185 assert_eq!(hex_digit(b"G"), Error(Err::Position(ErrorKind::OneOf, &b"G"[..])));
186 assert_eq!(hex_digit(b":"), Error(Err::Position(ErrorKind::OneOf, &b":"[..])));
187 assert_eq!(hex_digit(b"@"), Error(Err::Position(ErrorKind::OneOf, &b"@"[..])));
188
189 assert_eq!(hex_digit(b"a"), Done(&b""[..], 10));
190 assert_eq!(hex_digit(b"A"), Done(&b""[..], 10));
191 assert_eq!(hex_digit(b"f"), Done(&b""[..], 15));
192 assert_eq!(hex_digit(b"F"), Done(&b""[..], 15));
193 }
194
195 #[test]
196 fn test_octal_esc() {
197 assert_eq!(octal_esc(b"\\000"), Done(&b""[..], 0o000));
198 assert_eq!(octal_esc(b"\\007"), Done(&b""[..], 0o007));
199 assert_eq!(octal_esc(b"\\077"), Done(&b""[..], 0o077));
200 assert_eq!(octal_esc(b"\\377"), Done(&b""[..], 0o377));
201
202 assert_eq!(octal_esc(b"\\"), Incomplete(Needed::Size(2)));
203 assert_eq!(octal_esc(b"\\0"), Incomplete(Needed::Size(3)));
204 assert_eq!(octal_esc(b"\\00"), Incomplete(Needed::Size(4)));
205 assert_eq!(octal_esc(b"\\0000"), Done(&b"0"[..], 0));
206 assert_eq!(octal_esc(b"\\3765"), Done(&b"5"[..], 0o376));
207
208 assert_eq!(octal_esc(b"\\080"), Error(Err::Position(ErrorKind::OneOf, &b"80"[..])));
209 assert_eq!(octal_esc(b"\\400"), Error(Err::Position(ErrorKind::OneOf, &b"400"[..])));
210
211 assert_eq!(octal_esc(b"\\x00"), Error(Err::Position(ErrorKind::OneOf, &b"x00"[..])));
212 assert_eq!(octal_esc(b"A"), Error(Err::Position(ErrorKind::Tag, &b"A"[..])));
213 assert_eq!(octal_esc(b" \\000"), Error(Err::Position(ErrorKind::Tag, &b" \\000"[..])));
214 }
215
216 #[test]
217 fn test_hex_esc() {
218 assert_eq!(hex_esc(b"\\x00"), Done(&b""[..], 0x00));
219 assert_eq!(hex_esc(b"\\x0f"), Done(&b""[..], 0x0f));
220 assert_eq!(hex_esc(b"\\xf0"), Done(&b""[..], 0xf0));
221
222 assert_eq!(hex_esc(b"\\"), Incomplete(Needed::Size(2)));
223 assert_eq!(hex_esc(b"\\x"), Incomplete(Needed::Size(3)));
224 assert_eq!(hex_esc(b"\\x0"), Incomplete(Needed::Size(4)));
225 assert_eq!(hex_esc(b"\\x000"), Done(&b"0"[..], 0x00));
226 assert_eq!(hex_esc(b"\\xba9"), Done(&b"9"[..], 0xba));
227
228 assert_eq!(hex_esc(b"0x41"), Error(Err::Position(ErrorKind::Tag, &b"0x41"[..])));
229 assert_eq!(hex_esc(b"\\000"), Error(Err::Position(ErrorKind::Tag, &b"\\000"[..])));
230 assert_eq!(hex_esc(b"\\x0g"), Error(Err::Position(ErrorKind::OneOf, &b"g"[..])));
231 }
232
233 #[test]
234 fn test_quoted_string() {
235 assert_eq!(quoted_string(b"\"Stuff\""), Done(&b""[..], "Stuff".to_owned()));
236 assert_eq!(quoted_string("\"Stũff\"".as_bytes()), Done(&b""[..], "Stũff".to_owned()));
237 assert_eq!(quoted_string(b"\"a\"\"b\""), Done(&b"\"b\""[..], "a".to_owned()));
238
239 assert_eq!(quoted_string(b"\"A\\x42\""), Done(&b""[..], "AB".to_owned()));
240
241 assert_eq!(quoted_string(b"UTF8"), Error(Err::Position(ErrorKind::Tag, &b"UTF8"[..])));
242
243 assert_eq!(quoted_string(b"\"A\\x82\""),
244 Error(Err::Position(ErrorKind::MapRes, &b"A\\x82\""[..])));
245 assert_eq!(quoted_string(b"\"A\\xce\""),
246 Error(Err::Position(ErrorKind::MapRes, &b"A\\xce\""[..])));
247 assert_eq!(quoted_string(b"\"A\\xce\\xbb\""),
248 Done(&b""[..], "Aλ".to_owned()));
249
250 assert_eq!(quoted_string(b"\"A\\\\B\""),
251 Error(Err::Position(ErrorKind::Tag, &b"\\\\B\""[..])));
252 assert_eq!(quoted_string(b"\"A\\\"B\""),
253 Error(Err::Position(ErrorKind::Tag, &b"\\\"B\""[..])));
254 assert_eq!(quoted_string(b"\"A\\102\""),
255 Error(Err::Position(ErrorKind::Tag, &b"\\102\""[..])));
256
257 assert_eq!(quoted_string(b"\"AC Ra\\xC3\\xADz\""),
258 Done(&b""[..], "AC Raíz".to_owned()));
259 assert_eq!(quoted_string("\"Főtanúsítvány\"".as_bytes()),
260 Done(&b""[..], "Főtanúsítvány".to_owned()));
261 }
262
263 #[test]
264 fn test_multiline_octal() {
265 assert_eq!(multiline_octal(b"\\101"), Done(&b""[..], vec![65]));
266 assert_eq!(multiline_octal(b"\\101\\033"), Done(&b""[..], vec![65, 27]));
267 assert_eq!(multiline_octal(b"\\101\n\\033"), Done(&b""[..], vec![65, 27]));
268 assert_eq!(multiline_octal(b"\\101\\033\n"),
269 Incomplete(Needed::Size("\\101\\033\n".len() + 1)));
270 assert_eq!(multiline_octal(b"\n\\101\\033"), Done(&b""[..], vec![65, 27]));
271 assert_eq!(multiline_octal(b"\\101\n\n\n\n\n\n\\033"), Done(&b""[..], vec![65, 27]));
272 assert_eq!(multiline_octal(b"\\101\r\n\r\n\r\n\\033"), Done(&b""[..], vec![65, 27]));
273 assert_eq!(multiline_octal(b"\\101 \\033"), Done(&b""[..], vec![65, 27]));
274 assert_eq!(multiline_octal(b"\\101 # Sixty-five \n\t\\033"), Done(&b""[..], vec![65, 27]));
275 assert_eq!(multiline_octal(b"\\101\\033\nEND"), Done(&b"\nEND"[..], vec![65, 27]));
276 assert_eq!(multiline_octal(b"\\101\\033\n END"), Done(&b"\n END"[..], vec![65, 27]));
277 }
278
279 #[test]
280 fn test_token_value() {
281 assert_eq!(type_and_value(b"CK_BBOOL CK_TRUE\n"),
282 Done(&b""[..], Value::Token("CK_BBOOL".to_owned(), "CK_TRUE".to_owned())));
283 assert_eq!(type_and_value(b"CK_BBOOL \t CK_TRUE\n"),
284 Done(&b""[..], Value::Token("CK_BBOOL".to_owned(), "CK_TRUE".to_owned())));
285 assert_eq!(type_and_value(b"CK_BBOOL CK_TRUE\n\n"),
286 Done(&b"\n"[..], Value::Token("CK_BBOOL".to_owned(), "CK_TRUE".to_owned())));
287 assert_eq!(type_and_value(b"CK_BBOOL CK_TRUE \n "),
288 Done(&b" "[..], Value::Token("CK_BBOOL".to_owned(), "CK_TRUE".to_owned())));
289 assert_eq!(type_and_value(b"CK_BBOOL CK_TRUE # Very true. Wow. \n"),
290 Done(&b""[..], Value::Token("CK_BBOOL".to_owned(), "CK_TRUE".to_owned())));
291 assert_eq!(type_and_value(b"CK_BBOOL CK_TRUE"),
292 Incomplete(Needed::Size("CK_BBOOL CK_TRUE".len() + 1)));
293 assert!(type_and_value(b"CK_BBOOL\nCK_TRUE\n").is_err());
294
295 let bad_rhs = |ek: ErrorKind| {
296 let inner = Box::new(Err::Position(ek, &b"CK_TRUE\n"[..]));
297 Error(Err::NodePosition(ErrorKind::Alt, &b" CK_TRUE\n"[..], inner))
298 };
299 assert_eq!(type_and_value(b"UTF8 CK_TRUE\n"), bad_rhs(ErrorKind::Tag));
300 assert_eq!(type_and_value(b"MULTILINE_OCTAL CK_TRUE\n"), bad_rhs(ErrorKind::Char));
301 }
302
303 #[test]
304 fn test_string_value() {
305 assert_eq!(type_and_value(b"UTF8 \"0\"\n"),
306 Done(&b""[..], Value::String("0".to_owned())));
307 assert_eq!(type_and_value(b"UTF8 \"Bogus Mozilla Addons\"\n"),
308 Done(&b""[..], Value::String("Bogus Mozilla Addons".to_owned())));
309
310 assert!(type_and_value(b"UTF8\n\"0\"\n").is_err());
311 assert!(type_and_value(b"CK_OBJECT_CLASS \"0\"\n").is_err());
312 assert!(type_and_value(b"MULTILINE_OCTAL \"0\"\n").is_err());
313
314 assert_eq!(type_and_value(b"UTF8 "), Incomplete(Needed::Size("UTF8 ".len() + 1)));
315 assert_eq!(type_and_value(b"UTF8 \""), Incomplete(Needed::Size("UTF8 \"".len() + 1)));
316 assert_eq!(type_and_value(b"UTF8 \"x\""), Incomplete(Needed::Size("UTF8 \"x\"".len() + 1)));
317 }
318
319 #[test]
320 fn test_octal_value() {
321 assert_eq!(type_and_value(b"MULTILINE_OCTAL\n\
322 \\000\\001\\002\n\
323 \\010\\011\\012\n\
324 END\n"),
325 Done(&b""[..], Value::Binary(vec![0, 1, 2, 8, 9, 10])))
326
327 }
329
330 #[test]
331 fn test_attr() {
332 assert_eq!(attribute(b"# This is a thing.\n\
333 CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE\n"),
334 Done(&b""[..], ("CKA_CLASS".to_owned(),
335 Value::Token("CK_OBJECT_CLASS".to_owned(),
336 "CKO_CERTIFICATE".to_owned()))));
337
338 assert_eq!(attribute(b"CKA_SERIAL_NUMBER MULTILINE_OCTAL\n\
339 \\002\\004\\011\\023\\310\\251\n\
340 END\n"),
341 Done(&b""[..], ("CKA_SERIAL_NUMBER".to_owned(),
342 Value::Binary(vec![0x02, 4, 0x9, 0x13, 0xc8, 0xa9]))));
343
344 }
346}