use std::io::{Error, ErrorKind};
#[derive(Debug)]
pub enum ResponseLine {
Array(usize),
SimpleString(String),
Error(String),
Integer(i64),
BulkString(usize),
Null,
}
#[derive(Debug, PartialEq, Eq)]
pub enum ResponseValue {
Empty,
String(String),
Integer(i64),
}
#[derive(Debug, PartialEq, Eq)]
pub enum Response {
Array(Vec<ResponseValue>),
Item(ResponseValue),
Error,
}
fn read_line_size(line: String) -> Result<Option<usize>, Error> {
match line.trim_end().split_at(1).1 {
"-1" => Ok(None),
value => value
.parse::<usize>()
.map_err(|e| {
Error::new(
ErrorKind::Other,
format!("invalid array length value '{}': {}", line.as_str(), e),
)
})
.map(Some),
}
}
pub fn readline(result: String) -> Result<ResponseLine, Error> {
match result.bytes().next() {
Some(b'*') => match read_line_size(result)? {
None => Ok(ResponseLine::Null),
Some(size) => Ok(ResponseLine::Array(size)),
},
Some(b'$') => match read_line_size(result)? {
Some(size) => Ok(ResponseLine::BulkString(size)),
None => Ok(ResponseLine::Null),
},
Some(b'-') => Ok(ResponseLine::Error(result)),
Some(b'+') => Ok(ResponseLine::SimpleString(String::from(result.split_at(1).1))),
Some(b':') => {
let (_, rest) = result.trim_end().split_at(1);
rest
.parse::<i64>()
.map_err(|e| Error::new(ErrorKind::Other, format!("{:?}", e)))
.map(ResponseLine::Integer)
}
Some(unknown) => Err(Error::new(
ErrorKind::Other,
format!("invalid message byte leader: {}", unknown),
)),
None => Err(Error::new(
ErrorKind::Other,
"empty line in response, unable to determine type",
)),
}
}