1use std::io::{Read, BufReader};
2
3use types::{RedisResult, Value, ErrorKind, make_extension_error};
4
5
6pub struct Parser<T> {
8 reader: T,
9}
10
11impl<'a, T: Read> Parser<T> {
16 pub fn new(reader: T) -> Parser<T> {
21 Parser { reader: reader }
22 }
23
24 pub fn parse_value(&mut self) -> RedisResult<Value> {
30 let b = try!(self.read_byte());
31 match b as char {
32 '+' => self.parse_status(),
33 ':' => self.parse_int(),
34 '$' => self.parse_data(),
35 '*' => self.parse_bulk(),
36 '-' => self.parse_error(),
37 _ => fail!((ErrorKind::PatternError, "Invalid response when parsing value")),
38 }
39 }
40
41 #[inline]
44 fn expect_char(&mut self, refchar: char) -> RedisResult<()> {
45 if try!(self.read_byte()) as char == refchar {
46 Ok(())
47 } else {
48 fail!((ErrorKind::PatternError, "Invalid byte in response"));
49 }
50 }
51
52 #[inline]
53 fn expect_newline(&mut self) -> RedisResult<()> {
54 match try!(self.read_byte()) as char {
55 '\r' => self.expect_char('\n'),
56 _ => fail!((ErrorKind::PatternError, "Invalid byte in response")),
57 }
58 }
59
60 fn read_line(&mut self) -> RedisResult<Vec<u8>> {
61 let mut rv = vec![];
62
63 loop {
64 let b = try!(self.read_byte());
65 match b as char {
66 '\r' => {
67 try!(self.expect_char('\n'));
68 break;
69 }
70 _ => rv.push(b),
71 };
72 }
73
74 Ok(rv)
75 }
76
77 fn read_string_line(&mut self) -> RedisResult<String> {
78 match String::from_utf8(try!(self.read_line())) {
79 Err(_) => fail!((ErrorKind::PatternError, "Expected valid string, got garbage")),
80 Ok(value) => Ok(value),
81 }
82 }
83
84 fn read_byte(&mut self) -> RedisResult<u8> {
85 let buf: &mut [u8; 1] = &mut [0];
86 let nread = try!(self.reader.read(buf));
87
88 if nread < 1 {
89 fail!((ErrorKind::PatternError, "Could not read enough bytes"))
90 } else {
91 Ok(buf[0])
92 }
93 }
94
95 fn read(&mut self, bytes: usize) -> RedisResult<Vec<u8>> {
96 let mut rv = vec![0; bytes];
97 let mut i = 0;
98 while i < bytes {
99 let res_nread = {
100 let ref mut buf = &mut rv[i..];
101 self.reader.read(buf)
102 };
103 match res_nread {
104 Ok(nread) if nread > 0 => i += nread,
105 Ok(_) => return fail!((ErrorKind::PatternError, "Could not read enough bytes")),
106 Err(e) => return Err(From::from(e)),
107 }
108 }
109 Ok(rv)
110 }
111
112 fn read_int_line(&mut self) -> RedisResult<i64> {
113 let line = try!(self.read_string_line());
114 match line.trim().parse::<i64>() {
115 Err(_) => fail!((ErrorKind::PatternError, "Expected integer, got garbage")),
116 Ok(value) => Ok(value),
117 }
118 }
119
120 fn parse_status(&mut self) -> RedisResult<Value> {
121 let line = try!(self.read_string_line());
122 if line == "OK" {
123 Ok(Value::Okay)
124 } else {
125 Ok(Value::Status(line))
126 }
127 }
128
129 fn parse_int(&mut self) -> RedisResult<Value> {
130 Ok(Value::Int(try!(self.read_int_line())))
131 }
132
133 fn parse_data(&mut self) -> RedisResult<Value> {
134 let length = try!(self.read_int_line());
135 if length < 0 {
136 Ok(Value::Nil)
137 } else {
138 let data = try!(self.read(length as usize));
139 try!(self.expect_newline());
140 Ok(Value::Data(data))
141 }
142 }
143
144 fn parse_bulk(&mut self) -> RedisResult<Value> {
145 let length = try!(self.read_int_line());
146 if length < 0 {
147 Ok(Value::Nil)
148 } else {
149 let mut rv = vec![];
150 rv.reserve(length as usize);
151 for _ in 0..length {
152 rv.push(try!(self.parse_value()));
153 }
154 Ok(Value::Bulk(rv))
155 }
156 }
157
158 fn parse_error(&mut self) -> RedisResult<Value> {
159 let desc = "An error was signalled by the server";
160 let line = try!(self.read_string_line());
161 let mut pieces = line.splitn(2, ' ');
162 let kind = match pieces.next().unwrap() {
163 "ERR" => ErrorKind::ResponseError,
164 "EXECABORT" => ErrorKind::ExecAbortError,
165 "LOADING" => ErrorKind::BusyLoadingError,
166 "NOSCRIPT" => ErrorKind::NoScriptError,
167 code => {
168 fail!(make_extension_error(code, pieces.next()));
169 }
170 };
171 match pieces.next() {
172 Some(detail) => fail!((kind, desc, detail.to_string())),
173 None => fail!((kind, desc)),
174 }
175 }
176}
177
178
179pub fn parse_redis_value(bytes: &[u8]) -> RedisResult<Value> {
184 let mut parser = Parser::new(BufReader::new(bytes));
185 parser.parse_value()
186}