lib_resp/
parser.rs

1use super::Value;
2use std::str::FromStr;
3use nom::{crlf, digit, not_line_ending};
4
5/// Core parser implementation.
6pub struct Parser;
7
8impl Parser {
9    /// Parses RESP from a byte buffer.
10    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    /// Parses a RESP encoded string.
82    ///
83    /// # Examples
84    ///
85    /// ```
86    /// # use lib_resp::Parser;
87    /// let age = Parser::parse_str(":-3").unwrap();
88    ///
89    /// println!("{:?}", age);
90    /// ```
91    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}