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
use std::io::BufRead; use ::error::Result; use ::error::ErrorKind; use ::byte_utils::read_until; #[derive(Debug, PartialEq)] pub struct StoreCommand { pub command_name: String, pub key: String, pub flags: u16, pub exptime: u32, pub bytes: u64, pub cas_unique: Option<u64>, pub noreply: Option<String>, pub data_block: Vec<u8>, } impl StoreCommand { pub fn parse<R: BufRead>(reader: &mut R) -> Result<StoreCommand> { let cmd_line = try!(read_until(reader, "\r\n")); let cmd_str = try!(String::from_utf8(cmd_line)); let segments = cmd_str.split_whitespace().collect::<Vec<&str>>(); let length = segments.len(); if length < 1 { return Err(ErrorKind::ClientError("wrong size of params".to_owned()).into()); } let cmd = segments[0]; let is_cas = match cmd { "set" => false, "add" => false, "replace" => false, "append" => false, "prepend" => false, "cas" => true, _ => return Err(ErrorKind::ClientError("wrong size of params".to_owned()).into()), }; match is_cas { true if 6 <= length && length <= 7 => (), false if 5 <= length && length <= 6 => (), _ => return Err(ErrorKind::ClientError("wrong size of params".to_owned()).into()), } let bytes = try!(segments[4].parse::<u64>()); let cas_unique = if is_cas { Some(try!(segments[5].parse::<u64>())) } else { None }; let noreply = match is_cas { true if length == 7 => Some(segments[6].to_owned()), false if length == 6 => Some(segments[5].to_owned()), _ => None, }; let mut data_block = vec![0; bytes as usize]; let _ = try!(reader.read_exact(&mut data_block)); if try!(read_until(reader, "\r\n")) != vec![] { return Err(ErrorKind::ClientError("error data block".to_owned()).into()); } Ok(StoreCommand { command_name: cmd.to_owned(), key: segments[1].to_owned(), flags: try!(segments[2].parse::<u16>()), exptime: try!(segments[3].parse::<u32>()), bytes: bytes, cas_unique: cas_unique, noreply: noreply, data_block: data_block, }) } }