|
1 use nom::*; |
|
2 use std::str; |
|
3 |
|
4 use super::messages::{*, EngineMessage::*, UnsyncedEngineMessage::*, SyncedEngineMessage::*, ConfigEngineMessage::*, KeystrokeAction::*}; |
|
5 |
|
6 named!(length_specifier<&[u8], u16>, alt!( |
|
7 verify!(map!(take!(1), |a : &[u8]| a[0] as u16), |l| l < 64) |
|
8 | map!(take!(2), |a| (a[0] as u16 - 64) * 256 + a[1] as u16 + 64) |
|
9 ) |
|
10 ); |
|
11 |
|
12 named!(unrecognized_message<&[u8], EngineMessage>, |
|
13 do_parse!(rest >> (Unknown)) |
|
14 ); |
|
15 |
|
16 named!(string_tail<&[u8], String>, map!(map_res!(rest, str::from_utf8), String::from)); |
|
17 |
|
18 named!(synced_message<&[u8], SyncedEngineMessage>, alt!( |
|
19 do_parse!(tag!("+l") >> (Left(Press))) |
|
20 )); |
|
21 |
|
22 named!(unsynced_message<&[u8], UnsyncedEngineMessage>, alt!( |
|
23 do_parse!(tag!("?") >> (Ping)) |
|
24 | do_parse!(tag!("!") >> (Ping)) |
|
25 | do_parse!(tag!("esay ") >> s: string_tail >> (Say(s))) |
|
26 )); |
|
27 |
|
28 named!(config_message<&[u8], ConfigEngineMessage>, alt!( |
|
29 do_parse!(tag!("C") >> (ConfigRequest)) |
|
30 )); |
|
31 |
|
32 named!(empty_message<&[u8], EngineMessage>, |
|
33 do_parse!(tag!("\0") >> (Empty)) |
|
34 ); |
|
35 |
|
36 named!(non_empty_message<&[u8], EngineMessage>, length_value!(length_specifier, |
|
37 alt!( |
|
38 map!(synced_message, |m| Synced(m, 0)) |
|
39 | map!(unsynced_message, |m| Unsynced(m)) |
|
40 | map!(config_message, |m| Config(m)) |
|
41 | unrecognized_message |
|
42 ) |
|
43 )); |
|
44 |
|
45 named!(message<&[u8], EngineMessage>, alt!( |
|
46 empty_message |
|
47 | non_empty_message |
|
48 ) |
|
49 ); |
|
50 |
|
51 named!(pub extract_messages<&[u8], Vec<EngineMessage> >, many0!(complete!(message))); |
|
52 |
|
53 #[test] |
|
54 fn parse_length() { |
|
55 assert_eq!(length_specifier(b"\x01"), Ok((&b""[..], 1))); |
|
56 assert_eq!(length_specifier(b"\x00"), Ok((&b""[..], 0))); |
|
57 assert_eq!(length_specifier(b"\x3f"), Ok((&b""[..], 63))); |
|
58 assert_eq!(length_specifier(b"\x40\x00"), Ok((&b""[..], 64))); |
|
59 assert_eq!(length_specifier(b"\xff\xff"), Ok((&b""[..], 49215))); |
|
60 } |
|
61 |
|
62 #[test] |
|
63 fn parse_synced_messages() { |
|
64 assert_eq!(message(b"\x04+l\x01\x01"), Ok((&b""[..], Synced(Left(Press), 0)))); |
|
65 } |
|
66 |
|
67 #[test] |
|
68 fn parse_unsynced_messages() { |
|
69 assert_eq!(message(b"\x0aesay hello"), Ok((&b""[..], Unsynced(Say(String::from("hello")))))); |
|
70 } |
|
71 |
|
72 #[test] |
|
73 fn parse_incorrect_messages() { |
|
74 assert_eq!(message(b"\x00"), Ok((&b""[..], Empty))); |
|
75 assert_eq!(message(b"\x01\x00"), Ok((&b""[..], Unknown))); |
|
76 } |
|
77 |
|
78 #[test] |
|
79 fn parse_config_messages() { |
|
80 assert_eq!( |
|
81 message(b"\x01C"), |
|
82 Ok(( |
|
83 &b""[..], |
|
84 Config(ConfigRequest) |
|
85 )) |
|
86 ); |
|
87 } |
|
88 #[test] |
|
89 fn parse_test_general() { |
|
90 assert_eq!(string_tail(b"abc"), Ok((&b""[..], String::from("abc")))); |
|
91 } |