esp8266_wifi_serial/
parser.rs1use core::str::FromStr;
2
3use nom::{alt, char, character::streaming::digit1, do_parse, named, opt, tag, IResult};
4
5use crate::net::{IpAddr, Ipv4Addr};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum CommandResponse {
9 Connected { link_id: u16 },
10 Closed { link_id: u16 },
11 DataAvailable { link_id: u16, size: u64 },
12 WifiDisconnect,
13}
14
15fn parse_error(input: &[u8]) -> nom::Err<nom::error::Error<&[u8]>> {
16 nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Digit))
17}
18
19fn atoi<T: FromStr>(input: &[u8]) -> Result<T, nom::Err<nom::error::Error<&[u8]>>> {
20 let s = core::str::from_utf8(input).map_err(|_| parse_error(input))?;
21 s.parse().map_err(|_| parse_error(input))
22}
23
24fn parse_link_id(input: &[u8]) -> IResult<&[u8], u16> {
25 let (input, digits) = digit1(input)?;
26 let num = atoi(digits)?;
27 IResult::Ok((input, num))
28}
29
30fn parse_u64(input: &[u8]) -> IResult<&[u8], u64> {
31 let (input, digits) = digit1(input)?;
32 let num = atoi(digits)?;
33 IResult::Ok((input, num))
34}
35
36fn parse_u8(input: &[u8]) -> IResult<&[u8], u8> {
37 let (input, digits) = digit1(input)?;
38 let num = atoi(digits)?;
39 IResult::Ok((input, num))
40}
41
42named!(crlf, tag!("\r\n"));
43
44named!(
45 connected<CommandResponse>,
46 do_parse!(
47 opt!(crlf)
48 >> link_id: parse_link_id
49 >> tag!(",CONNECT")
50 >> crlf
51 >> (CommandResponse::Connected { link_id })
52 )
53);
54
55named!(
56 closed<CommandResponse>,
57 do_parse!(
58 opt!(crlf)
59 >> link_id: parse_link_id
60 >> tag!(",CLOSED")
61 >> crlf
62 >> (CommandResponse::Closed { link_id })
63 )
64);
65
66named!(
67 data_available<CommandResponse>,
68 do_parse!(
69 opt!(crlf)
70 >> tag!("+IPD,")
71 >> link_id: parse_link_id
72 >> char!(',')
73 >> size: parse_u64
74 >> char!(':')
75 >> opt!(crlf)
76 >> (CommandResponse::DataAvailable { link_id, size })
77 )
78);
79
80named!(
81 wifi_disconnect<CommandResponse>,
82 do_parse!(
83 opt!(crlf) >> tag!("WIFI DISCONNECT") >> opt!(crlf) >> (CommandResponse::WifiDisconnect)
84 )
85);
86
87named!(
88 parse<CommandResponse>,
89 alt!(connected | closed | data_available | wifi_disconnect)
90);
91
92impl CommandResponse {
93 pub fn parse(input: &[u8]) -> Option<(&[u8], Self)> {
94 parse(input).ok()
95 }
96}
97
98pub struct CifsrResponse {
99 pub ap_ip: Option<IpAddr>,
100 pub sta_ip: Option<IpAddr>,
101}
102
103named!(
104 parse_ip4_addr<IpAddr>,
105 do_parse!(
106 opt!(crlf)
107 >> a: parse_u8
108 >> char!('.')
109 >> b: parse_u8
110 >> char!('.')
111 >> c: parse_u8
112 >> char!('.')
113 >> d: parse_u8
114 >> (IpAddr::V4(Ipv4Addr::new(a, b, c, d)))
115 )
116);
117
118named!(
119 parse_apip<IpAddr>,
120 do_parse!(
121 opt!(crlf)
122 >> tag!("+CIFSR:APIP,")
123 >> char!('"')
124 >> ip_addr: parse_ip4_addr
125 >> char!('"')
126 >> opt!(crlf)
127 >> (ip_addr)
128 )
129);
130
131named!(
132 parse_staip<IpAddr>,
133 do_parse!(
134 opt!(crlf)
135 >> tag!("+CIFSR:STAIP,")
136 >> char!('"')
137 >> ip_addr: parse_ip4_addr
138 >> char!('"')
139 >> opt!(crlf)
140 >> (ip_addr)
141 )
142);
143
144named!(
145 cifsr_response<CifsrResponse>,
146 do_parse!(
147 opt!(crlf)
148 >> ap_ip: opt!(parse_apip)
149 >> sta_ip: opt!(parse_staip)
150 >> (CifsrResponse { ap_ip, sta_ip })
151 )
152);
153
154impl CifsrResponse {
155 pub fn parse(input: &[u8]) -> Option<(&[u8], Self)> {
156 cifsr_response(input).ok()
157 }
158}
159
160#[test]
161fn test_parse_connect() {
162 let raw = b"1,CONNECT\r\n";
163 let event = CommandResponse::parse(raw.as_ref()).unwrap().1;
164
165 assert_eq!(event, CommandResponse::Connected { link_id: 1 })
166}
167
168#[test]
169fn test_parse_close() {
170 let raw = b"1,CLOSED\r\n";
171 let event = CommandResponse::parse(raw.as_ref()).unwrap().1;
172
173 assert_eq!(event, CommandResponse::Closed { link_id: 1 })
174}
175
176#[test]
177fn test_parse_data_available() {
178 let raw = b"+IPD,12,6:hello\r\n";
179 let event = CommandResponse::parse(raw.as_ref()).unwrap().1;
180
181 assert_eq!(
182 event,
183 CommandResponse::DataAvailable {
184 link_id: 12,
185 size: 6
186 }
187 )
188}