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