1use serde::{Deserialize, Serialize};
2use serde_json::Result;
3use std::collections::HashMap;
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6#[serde(tag = "action")]
7pub enum Command {
8 #[serde(rename = "GET")]
9 Get {
10 #[serde(rename = "key")]
11 key: String,
12 },
13 #[serde(rename = "GETDEL")]
14 GetDel {
15 #[serde(rename = "key")]
16 key: String,
17 },
18 #[serde(rename = "SET")]
19 Set {
20 #[serde(rename = "key")]
21 key: String,
22
23 #[serde(rename = "value")]
24 value: String,
25
26 #[serde(rename = "expiry_seconds")]
27 expiry_seconds: u64,
28
29 #[serde(rename = "expiry_ts")]
30 #[serde(default)]
31 expiry_ts: u64,
32 },
33 #[serde(rename = "DELETE")]
34 Delete {
35 #[serde(rename = "keys")]
36 keys: Vec<String>,
37 },
38 #[serde(rename = "LPUSH")]
39 LPush {
40 #[serde(rename = "key")]
41 key: String,
42 #[serde(rename = "values")]
43 values: Vec<String>,
44 },
45 #[serde(rename = "RPUSH")]
46 RPush {
47 #[serde(rename = "key")]
48 key: String,
49 #[serde(rename = "values")]
50 values: Vec<String>,
51 },
52 #[serde(rename = "LRANGE")]
53 LRange {
54 #[serde(rename = "key")]
55 key: String,
56 #[serde(rename = "start")]
57 start: Option<usize>,
58 #[serde(rename = "end")]
59 end: Option<usize>,
60 },
61 #[serde(rename = "LLEN")]
62 LLen {
63 #[serde(rename = "key")]
64 key: String,
65 },
66 #[serde(rename = "LPOP")]
67 LPop {
68 #[serde(rename = "key")]
69 key: String,
70 },
71 #[serde(rename = "RPOP")]
72 RPop {
73 #[serde(rename = "key")]
74 key: String,
75 },
76 #[serde(rename = "EXISTS")]
77 Exists {
78 #[serde(rename = "key")]
79 key: String,
80 },
81 #[serde(rename = "INCR")]
82 Incr {
83 #[serde(rename = "key")]
84 key: String,
85 },
86 #[serde(rename = "INCRBY")]
87 IncrBy {
88 #[serde(rename = "key")]
89 key: String,
90 #[serde(rename = "increment")]
91 increment: i64,
92 },
93 #[serde(rename = "DECR")]
94 Decr {
95 #[serde(rename = "key")]
96 key: String,
97 },
98 #[serde(rename = "DECRBY")]
99 DecrBy {
100 #[serde(rename = "key")]
101 key: String,
102 #[serde(rename = "decrement")]
103 decrement: i64,
104 },
105 #[serde(rename = "SADD")]
106 SAdd {
107 #[serde(rename = "key")]
108 key: String,
109 #[serde(rename = "values")]
110 values: Vec<String>,
111 },
112 #[serde(rename = "SCARD")]
113 SCard {
114 #[serde(rename = "key")]
115 key: String,
116 },
117 #[serde(rename = "SINTER")]
118 SInter {
119 #[serde(rename = "key")]
120 key: String,
121 #[serde(rename = "others")]
122 others: Vec<String>,
123 },
124 #[serde(rename = "SDIFF")]
125 SDiff {
126 #[serde(rename = "key")]
127 key: String,
128 #[serde(rename = "others")]
129 others: Vec<String>,
130 },
131 #[serde(rename = "ZADD")]
132 ZAdd {
133 #[serde(rename = "key")]
134 key: String,
135 #[serde(rename = "values")]
136 values: HashMap<String, i64>,
137 },
138 #[serde(rename = "ZCARD")]
139 ZCard {
140 #[serde(rename = "key")]
141 key: String,
142 },
143}
144
145impl Command {
146 pub fn from_json(json_str: &str) -> Result<Command> {
147 serde_json::from_str(json_str)
148 }
149
150 pub(crate) fn to_json(&self) -> Result<String> {
151 serde_json::to_string(self)
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158
159 #[test]
160 fn test_get_command_from_json() {
161 let json_str = r#"{"action":"GET","key":"mykey"}"#;
162 let cmd = Command::from_json(json_str).unwrap();
163 match cmd {
164 Command::Get { key } => assert_eq!(key, "mykey"),
165 _ => panic!("Expected Command::Get"),
166 }
167 }
168
169 #[test]
170 fn test_set_command_to_json() {
171 let cmd = Command::Set {
172 key: "mykey".to_string(),
173 value: "myvalue".to_string(),
174 expiry_seconds: 3600,
175 expiry_ts: 0,
176 };
177 let json_str = cmd.to_json().unwrap();
178 assert_eq!(
179 json_str,
180 r#"{"action":"SET","key":"mykey","value":"myvalue","expiry_seconds":3600,"expiry_ts":0}"#
181 );
182 }
183
184 #[test]
185 fn test_zadd_command_from_json() {
186 let json_str = r#"{"action":"ZADD","key":"myset","values":{"key_1":1,"key_2":2}}"#;
187 let cmd = Command::from_json(json_str).unwrap();
188 match cmd {
189 Command::ZAdd { key, values } => {
190 assert_eq!(key, "myset");
191 assert_eq!(values.get("key_1"), Some(&1));
192 assert_eq!(values.get("key_2"), Some(&2));
193 }
194 _ => panic!("Expected Command::ZAdd"),
195 }
196 }
197
198 #[test]
199 fn test_lrange_command_to_json() {
200 let cmd = Command::LRange {
201 key: "mylist".to_string(),
202 start: Some(0),
203 end: Some(10),
204 };
205 let json_str = cmd.to_json().unwrap();
206 assert_eq!(
207 json_str,
208 r#"{"action":"LRANGE","key":"mylist","start":0,"end":10}"#
209 );
210 }
211}