1use super::Value;
2use std::str::FromStr;
3use nom::{crlf, digit, not_line_ending};
4
5pub struct Parser;
7
8impl Parser {
9 pub fn parse(data: &[u8]) -> Result<(&[u8], Value), ::nom::Err<&[u8]>> {
11 named!(
12 read_line<&str>,
13 do_parse!(line: map_res!(not_line_ending, ::std::str::from_utf8) >> crlf >> (line))
14 );
15
16 named!(
17 int<i64>,
18 do_parse!(
19 neg: opt!(tag!("-"))
20 >> value: map_res!(map_res!(digit, ::std::str::from_utf8), i64::from_str)
21 >> (if neg == None { value } else { -value })
22 )
23 );
24
25 named!(
26 parse_int<Value>,
27 preceded!(
28 tag!(":"),
29 do_parse!(datum: int >> crlf >> (Value::Int(datum)))
30 )
31 );
32
33 named!(
34 parse_str<Value>,
35 preceded!(
36 tag!("+"),
37 do_parse!(datum: read_line >> (Value::str(datum)))
38 )
39 );
40
41 named!(
42 parse_err<Value>,
43 preceded!(
44 tag!("-"),
45 do_parse!(datum: read_line >> (Value::err(datum)))
46 )
47 );
48
49 named!(
50 parse_bstr<Value>,
51 preceded!(
52 tag!("$"),
53 do_parse!(
54 len: int >> crlf >> datum: cond_with_error!(len > -1, take_str!(len))
55 >> cond_with_error!(len > -1, crlf)
56 >> (Value::b_str(datum))
57 )
58 )
59 );
60
61 named!(
62 parse_array<Value>,
63 preceded!(
64 tag!("*"),
65 do_parse!(
66 len: int >> crlf
67 >> data: cond_with_error!(len > -1, count!(parse_resp, len as usize))
68 >> (Value::Array(data))
69 )
70 )
71 );
72
73 named!(
74 parse_resp<Value>,
75 alt!(parse_int | parse_str | parse_err | parse_bstr | parse_array)
76 );
77
78 parse_resp(data)
79 }
80
81 pub fn parse_str(resp: &str) -> Result<Option<Value>, ()> {
92 match Parser::parse(resp.as_bytes()) {
93 Ok((_i, o)) => Ok(Some(o)),
94 Err(e) => {
95 if e.is_incomplete() {
96 Ok(None)
97 } else {
98 Err(())
99 }
100 }
101 }
102 }
103}