kade_proto/cmd/
set.rs

1use crate::cmd::{Parse, ParseError};
2use crate::prelude::*;
3
4use bytes::Bytes;
5use std::time::Duration;
6use tracing::{debug, instrument};
7
8#[derive(Debug)]
9pub struct Set {
10    key: String,
11    value: Bytes,
12    expire: Option<Duration>,
13}
14
15impl Set {
16    pub fn new(key: impl ToString, value: Bytes, expire: Option<Duration>) -> Set { Set { key: key.to_string(), value, expire } }
17
18    pub fn key(&self) -> &str { &self.key }
19
20    pub fn value(&self) -> &Bytes { &self.value }
21
22    pub fn expire(&self) -> Option<Duration> { self.expire }
23
24    pub fn parse_frames(parse: &mut Parse) -> crate::Result<Set> {
25        use ParseError::EndOfStream;
26
27        let key = parse.next_string()?;
28        let value = parse.next_bytes()?;
29        let mut expire = None;
30
31        match parse.next_string() {
32            Ok(s) if s.to_uppercase() == "EX" => {
33                let secs = parse.next_int()?;
34                expire = Some(Duration::from_secs(secs));
35            }
36            Ok(s) if s.to_uppercase() == "PX" => {
37                let ms = parse.next_int()?;
38                expire = Some(Duration::from_millis(ms));
39            }
40            Ok(_) => return Err("currently `SET` only supports the expiration option".into()),
41            Err(EndOfStream) => {}
42            Err(err) => return Err(err.into()),
43        }
44
45        Ok(Set { key, value, expire })
46    }
47
48    #[instrument(skip(self, db, dst))]
49    pub async fn apply(self, db: &Db, dst: &mut Connection) -> crate::Result<()> {
50        db.set(self.key, self.value, self.expire);
51
52        let response = Frame::Simple("OK".to_string());
53        debug!(?response);
54        dst.write_frame(&response).await?;
55
56        Ok(())
57    }
58
59    pub fn into_frame(self) -> Frame {
60        let mut frame = Frame::array();
61        frame.push_bulk(Bytes::from("set".as_bytes()));
62        frame.push_bulk(Bytes::from(self.key.into_bytes()));
63        frame.push_bulk(self.value);
64        if let Some(ms) = self.expire {
65            frame.push_bulk(Bytes::from("px".as_bytes()));
66            frame.push_int(ms.as_millis() as u64);
67        }
68        frame
69    }
70}