1#![warn(missing_docs)]
3use std::{rc::Rc, sync::Arc, sync::RwLock};
4
5pub trait RedisCommandHandler {
33 fn exec(&self, _: AsyncLockedStore, _: Rc<RedisCommand>) -> String;
37}
38
39pub type AsyncLockedStore<'a> = Arc<RwLock<&'a mut (dyn IStore + Send + Sync)>>;
40
41#[derive(Debug, Copy, Clone)]
43pub struct RedisCommand<'a> {
44 cmd: &'a str,
45}
46
47impl<'a> RedisCommand<'a> {
48 pub fn new(cmd: &'a str) -> Self {
50 Self { cmd }
51 }
52 pub fn params(&self) -> Vec<String> {
54 let mut args: Vec<String> = vec![];
55 let binding = self.cmd;
56 let elems: Vec<&str> = binding.split("\r\n").collect::<Vec<_>>();
57 for (idx, pat) in elems[1..].iter().enumerate() {
58 if idx.rem_euclid(2) == 0 {
59 continue;
60 }
61 args.push(pat.to_string())
62 }
63 args.clone()
64 }
65 pub fn name(&self) -> String {
67 self.params()[0].clone().to_lowercase()
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn test_args() {
77 let c = RedisCommand::new("*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$11\r\nHello World\r\n");
78 assert_eq!(vec!["SET", "key", "Hello World"], c.params());
79 }
80
81 #[test]
82 fn test_name() {
83 let c = RedisCommand::new("*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$11\r\nHello World\r\n");
84 assert_eq!("set", c.name());
85 }
86}
87
88use std::collections::HashMap;
89use std::fmt::{Debug, Display};
90
91#[derive(Debug, PartialEq)]
93pub enum StoreError {
94 KeyNotFoundError,
96 KeyMismatchError(String),
98}
99
100impl Display for StoreError {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 match self {
103 Self::KeyNotFoundError => {
104 write!(f, "-ERR key not found")
105 }
106 Self::KeyMismatchError(m) => {
107 write!(f, "-ERR {:}", m)
108 }
109 }
110 }
111}
112
113type StoreResult<T> = Result<T, StoreError>;
114
115pub trait IStore {
117 fn set(&mut self, k: String, v: Value) -> StoreResult<()>;
119 fn get(&self, k: String, vk: ValueKind) -> StoreResult<&Value>;
121}
122
123#[derive(Default)]
125pub struct RedisStore {
126 store: HashMap<String, Value>,
127}
128impl IStore for RedisStore {
129 fn set(&mut self, k: String, v: Value) -> StoreResult<()> {
130 self.store.insert(k, v);
131 Ok(())
132 }
133 fn get(&self, k: String, vk: ValueKind) -> StoreResult<&Value> {
134 match self.store.get(&k.clone()) {
135 Some(value) => {
136 if value.kind == vk {
137 return Ok(value);
138 }
139
140 Err(StoreError::KeyMismatchError(
141 "key xxx does not match yyy".to_string(),
142 ))
143 }
144 None => Err(StoreError::KeyNotFoundError),
145 }
146 }
147}
148
149#[cfg(test)]
150mod test {
151 use super::{RedisStore, StoreError, Value, ValueKind};
152 use IStore;
153
154 #[test]
155 fn test_store_get_set() {
156 let mut s = RedisStore::default();
157 let value = Value::new_string("hello pedis".to_string().as_bytes().to_vec());
158 let set_result = s.set("key:001".to_string(), value);
159 assert_eq!(set_result, Result::Ok(()));
160
161 let expected_value = Value::new_string("hello pedis".to_string().as_bytes().to_vec());
162 let get_result = s.get("key:001".to_string(), ValueKind::String);
163 assert_eq!(Result::Ok(&expected_value), get_result);
164
165 let get_key_kind_mistmatch_result = s.get("key:001".to_string(), ValueKind::Map);
166 assert_eq!(
167 Err(StoreError::KeyMismatchError(
168 "key xxx does not match yyy".to_string()
169 )),
170 get_key_kind_mistmatch_result
171 );
172
173 let get_key_not_found_result = s.get("key:013".to_string(), ValueKind::String);
174 assert_eq!(Err(StoreError::KeyNotFoundError), get_key_not_found_result);
175 }
176}
177
178#[derive(PartialEq)]
180pub struct Value {
181 pub kind: ValueKind,
183 pub data: Vec<u8>, }
189
190impl Value {
191 pub fn new(data: Vec<u8>, kind: ValueKind) -> Self {
193 Self { kind, data }
194 }
195 pub fn new_string(data: Vec<u8>) -> Self {
197 Self {
198 kind: ValueKind::String,
199 data,
200 }
201 }
202 pub fn new_map(data: Vec<u8>) -> Self {
204 Self {
205 kind: ValueKind::Map,
206 data,
207 }
208 }
209}
210
211impl Debug for Value {
212 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
213 write!(f, "k={:} len={:}", self.kind, self.data.len())
214 }
215}
216
217#[derive(PartialEq)]
219pub enum ValueKind {
220 String,
222 Map,
224 Json,
226 List,
228}
229
230impl Display for ValueKind {
231 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
232 match *self {
233 ValueKind::Map => {
234 write!(f, "map")
235 }
236 ValueKind::Json => {
237 write!(f, "json")
238 }
239 ValueKind::List => {
240 write!(f, "list")
241 }
242 ValueKind::String => {
243 write!(f, "string")
244 }
245 }
246 }
247}
248
249pub struct Teststore {
251 pub err: bool,
253}
254impl IStore for Teststore {
255 fn set(&mut self, _: String, _: Value) -> Result<(), StoreError> {
256 if self.err {
257 return Err(StoreError::KeyNotFoundError);
258 }
259 Ok(())
260 }
261 fn get(&self, _: String, _: ValueKind) -> Result<&Value, StoreError> {
262 todo!()
263 }
264}