rustdis/commands/
setnx.rs1use bytes::Bytes;
2use std::sync::{Arc, Mutex};
3
4use crate::commands::executable::Executable;
5use crate::commands::CommandParser;
6use crate::frame::Frame;
7use crate::store::Store;
8use crate::Error;
9
10#[derive(Debug, PartialEq)]
15pub struct Setnx {
16 pub key: String,
17 pub value: Bytes,
18}
19
20impl Executable for Setnx {
21 fn exec(self, store: Arc<Mutex<Store>>) -> Result<Frame, Error> {
22 let mut store = store.lock().unwrap();
23
24 let res = match store.get(&self.key) {
25 Some(_) => Frame::Integer(0),
26 None => {
27 store.set(self.key, self.value);
28 Frame::Integer(1)
29 }
30 };
31
32 Ok(res)
33 }
34}
35
36impl TryFrom<&mut CommandParser> for Setnx {
37 type Error = Error;
38
39 fn try_from(parser: &mut CommandParser) -> Result<Self, Self::Error> {
40 let key = parser.next_string()?;
41 let value = parser.next_bytes()?;
42
43 Ok(Self { key, value })
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50 use crate::commands::Command;
51 use bytes::Bytes;
52
53 #[test]
54 fn when_key_does_not_exists() {
55 let store = Arc::new(Mutex::new(Store::new()));
56
57 let frame = Frame::Array(vec![
58 Frame::Bulk(Bytes::from("SETNX")),
59 Frame::Bulk(Bytes::from("key1")),
60 Frame::Bulk(Bytes::from("1")),
61 ]);
62 let cmd = Command::try_from(frame).unwrap();
63
64 assert_eq!(
65 cmd,
66 Command::Setnx(Setnx {
67 key: String::from("key1"),
68 value: Bytes::from("1")
69 })
70 );
71
72 let res = cmd.exec(store.clone()).unwrap();
73
74 assert_eq!(res, Frame::Integer(1));
75 assert_eq!(store.lock().unwrap().get("key1"), Some(&Bytes::from("1")));
76 }
77
78 #[test]
79 fn when_key_already_exists() {
80 let store = Arc::new(Mutex::new(Store::new()));
81
82 let frame = Frame::Array(vec![
83 Frame::Bulk(Bytes::from("SETNX")),
84 Frame::Bulk(Bytes::from("key1")),
85 Frame::Bulk(Bytes::from("1")),
86 ]);
87 let cmd = Command::try_from(frame).unwrap();
88
89 assert_eq!(
90 cmd,
91 Command::Setnx(Setnx {
92 key: String::from("key1"),
93 value: Bytes::from("1")
94 })
95 );
96
97 store
98 .lock()
99 .unwrap()
100 .set(String::from("key1"), Bytes::from("1"));
101
102 let res = cmd.exec(store.clone()).unwrap();
103
104 assert_eq!(res, Frame::Integer(0));
105 assert_eq!(store.lock().unwrap().get("key1"), Some(&Bytes::from("1")));
106 }
107}