memcached_protocal/command/
store_command.rs

1use std::io::BufRead;
2
3use ::error::Result;
4use ::error::ErrorKind;
5use ::byte_utils::read_until;
6
7#[derive(Debug, PartialEq)]
8pub struct StoreCommand {
9    pub command_name: String,
10    pub key: String,
11    pub flags: u16,
12    pub exptime: u32,
13    pub bytes: u64,
14    pub cas_unique: Option<u64>,
15    pub noreply: Option<String>,
16    pub data_block: Vec<u8>,
17}
18
19
20impl StoreCommand {
21    pub fn parse<R: BufRead>(reader: &mut R) -> Result<StoreCommand> {
22        let cmd_line = try!(read_until(reader, "\r\n"));
23        let cmd_str = try!(String::from_utf8(cmd_line));
24        let segments = cmd_str.split_whitespace().collect::<Vec<&str>>();
25        let length = segments.len();
26        if length < 1 {
27            return Err(ErrorKind::ClientError("wrong size of params".to_owned()).into());
28        }
29        let cmd = segments[0];
30        let is_cas = match cmd {
31            "set" => false,
32            "add" => false,
33            "replace" => false,
34            "append" => false,
35            "prepend" => false,
36            "cas" => true,
37            _ => return Err(ErrorKind::ClientError("wrong size of params".to_owned()).into()),
38        };
39
40        match is_cas {
41            true if 6 <= length && length <= 7 => (),
42            false if 5 <= length && length <= 6 => (),
43            _ => return Err(ErrorKind::ClientError("wrong size of params".to_owned()).into()),
44        }
45
46        let bytes = try!(segments[4].parse::<u64>());
47        let cas_unique = if is_cas {
48            Some(try!(segments[5].parse::<u64>()))
49        } else {
50            None
51        };
52
53        let noreply = match is_cas {
54            true if length == 7 => Some(segments[6].to_owned()),
55            false if length == 6 => Some(segments[5].to_owned()),
56            _ => None,
57        };
58
59        let mut data_block = vec![0; bytes as usize];
60        let _ = try!(reader.read_exact(&mut data_block));
61        if try!(read_until(reader, "\r\n")) != vec![] {
62            return Err(ErrorKind::ClientError("error data block".to_owned()).into());
63        }
64
65        Ok(StoreCommand {
66            command_name: cmd.to_owned(),
67            key: segments[1].to_owned(),
68            flags: try!(segments[2].parse::<u16>()),
69            exptime: try!(segments[3].parse::<u32>()),
70            bytes: bytes,
71            cas_unique: cas_unique,
72            noreply: noreply,
73            data_block: data_block,
74        })
75    }
76}