1use std::fmt;
24use std::ops::{Deref, DerefMut};
25
26pub use vld;
27
28pub struct RedisConn<C> {
30 inner: C,
31}
32
33impl<C> RedisConn<C> {
34 pub fn new(inner: C) -> Self {
35 Self { inner }
36 }
37
38 pub fn into_inner(self) -> C {
39 self.inner
40 }
41}
42
43impl<C> Deref for RedisConn<C> {
44 type Target = C;
45
46 fn deref(&self) -> &Self::Target {
47 &self.inner
48 }
49}
50
51impl<C> DerefMut for RedisConn<C> {
52 fn deref_mut(&mut self) -> &mut Self::Target {
53 &mut self.inner
54 }
55}
56
57impl<C> RedisConn<C>
58where
59 C: redis::ConnectionLike,
60{
61 fn encode_json_value<V>(value: &V) -> Result<serde_json::Value, VldRedisError>
62 where
63 V: serde::Serialize + vld::schema::VldParse + ?Sized,
64 {
65 let json =
66 serde_json::to_value(value).map_err(|e| VldRedisError::Serialization(e.to_string()))?;
67 <V as vld::schema::VldParse>::vld_parse_value(&json).map_err(VldRedisError::Validation)?;
68 Ok(json)
69 }
70
71 fn encode_json_string<V>(value: &V) -> Result<String, VldRedisError>
72 where
73 V: serde::Serialize + vld::schema::VldParse + ?Sized,
74 {
75 let json = Self::encode_json_value(value)?;
76 serde_json::to_string(&json).map_err(|e| VldRedisError::Serialization(e.to_string()))
77 }
78
79 fn encode_json_bytes<V>(value: &V) -> Result<Vec<u8>, VldRedisError>
80 where
81 V: serde::Serialize + vld::schema::VldParse + ?Sized,
82 {
83 let json = Self::encode_json_value(value)?;
84 serde_json::to_vec(&json).map_err(|e| VldRedisError::Serialization(e.to_string()))
85 }
86
87 fn decode_json_bytes<T>(bytes: &[u8]) -> Result<T, VldRedisError>
88 where
89 T: vld::schema::VldParse,
90 {
91 let value: serde_json::Value = serde_json::from_slice(bytes)
92 .map_err(|e| VldRedisError::Deserialization(e.to_string()))?;
93 <T as vld::schema::VldParse>::vld_parse_value(&value).map_err(VldRedisError::Validation)
94 }
95
96 pub fn set<K, V>(&mut self, key: K, value: &V) -> Result<(), VldRedisError>
97 where
98 K: redis::ToRedisArgs,
99 V: serde::Serialize + vld::schema::VldParse + ?Sized,
100 {
101 let s = Self::encode_json_string(value)?;
102 redis::cmd("SET")
103 .arg(key)
104 .arg(s)
105 .query::<()>(&mut self.inner)?;
106 Ok(())
107 }
108
109 pub fn get<K, T>(&mut self, key: K) -> Result<Option<T>, VldRedisError>
110 where
111 K: redis::ToRedisArgs,
112 T: vld::schema::VldParse,
113 {
114 let raw: Option<Vec<u8>> = redis::cmd("GET").arg(key).query(&mut self.inner)?;
115 raw.map(|bytes| Self::decode_json_bytes(&bytes))
116 .transpose()
117 }
118
119 pub fn mset<'a, K, V, I>(&mut self, items: I) -> Result<(), VldRedisError>
120 where
121 I: IntoIterator<Item = (K, &'a V)>,
122 K: redis::ToRedisArgs,
123 V: serde::Serialize + vld::schema::VldParse + ?Sized + 'a,
124 {
125 let mut cmd = redis::cmd("MSET");
126 for (key, value) in items {
127 let encoded = Self::encode_json_string(value)?;
128 cmd.arg(key).arg(encoded);
129 }
130 cmd.query::<()>(&mut self.inner)?;
131 Ok(())
132 }
133
134 pub fn mget<K, T, I>(&mut self, keys: I) -> Result<Vec<Option<T>>, VldRedisError>
135 where
136 I: IntoIterator<Item = K>,
137 K: redis::ToRedisArgs,
138 T: vld::schema::VldParse,
139 {
140 let mut cmd = redis::cmd("MGET");
141 for key in keys {
142 cmd.arg(key);
143 }
144 let raw: Vec<Option<Vec<u8>>> = cmd.query(&mut self.inner)?;
145 raw.into_iter()
146 .map(|opt| opt.map(|bytes| Self::decode_json_bytes(&bytes)).transpose())
147 .collect()
148 }
149
150 pub fn hset<K, F, V>(&mut self, key: K, field: F, value: &V) -> Result<(), VldRedisError>
151 where
152 K: redis::ToRedisArgs,
153 F: redis::ToRedisArgs,
154 V: serde::Serialize + vld::schema::VldParse + ?Sized,
155 {
156 let s = Self::encode_json_string(value)?;
157 redis::cmd("HSET")
158 .arg(key)
159 .arg(field)
160 .arg(s)
161 .query::<()>(&mut self.inner)?;
162 Ok(())
163 }
164
165 pub fn hget<K, F, T>(&mut self, key: K, field: F) -> Result<Option<T>, VldRedisError>
166 where
167 K: redis::ToRedisArgs,
168 F: redis::ToRedisArgs,
169 T: vld::schema::VldParse,
170 {
171 let raw: Option<Vec<u8>> = redis::cmd("HGET")
172 .arg(key)
173 .arg(field)
174 .query(&mut self.inner)?;
175 raw.map(|bytes| Self::decode_json_bytes(&bytes))
176 .transpose()
177 }
178
179 pub fn lpush<K, V>(&mut self, key: K, value: &V) -> Result<usize, VldRedisError>
180 where
181 K: redis::ToRedisArgs,
182 V: serde::Serialize + vld::schema::VldParse + ?Sized,
183 {
184 let payload = Self::encode_json_string(value)?;
185 let len: usize = redis::cmd("LPUSH").arg(key).arg(payload).query(&mut self.inner)?;
186 Ok(len)
187 }
188
189 pub fn rpush<K, V>(&mut self, key: K, value: &V) -> Result<usize, VldRedisError>
190 where
191 K: redis::ToRedisArgs,
192 V: serde::Serialize + vld::schema::VldParse + ?Sized,
193 {
194 let payload = Self::encode_json_string(value)?;
195 let len: usize = redis::cmd("RPUSH").arg(key).arg(payload).query(&mut self.inner)?;
196 Ok(len)
197 }
198
199 pub fn lpop<K, T>(&mut self, key: K) -> Result<Option<T>, VldRedisError>
200 where
201 K: redis::ToRedisArgs,
202 T: vld::schema::VldParse,
203 {
204 let raw: Option<Vec<u8>> = redis::cmd("LPOP").arg(key).query(&mut self.inner)?;
205 raw.map(|bytes| Self::decode_json_bytes(&bytes)).transpose()
206 }
207
208 pub fn rpop<K, T>(&mut self, key: K) -> Result<Option<T>, VldRedisError>
209 where
210 K: redis::ToRedisArgs,
211 T: vld::schema::VldParse,
212 {
213 let raw: Option<Vec<u8>> = redis::cmd("RPOP").arg(key).query(&mut self.inner)?;
214 raw.map(|bytes| Self::decode_json_bytes(&bytes)).transpose()
215 }
216
217 pub fn sadd<K, V>(&mut self, key: K, value: &V) -> Result<usize, VldRedisError>
218 where
219 K: redis::ToRedisArgs,
220 V: serde::Serialize + vld::schema::VldParse + ?Sized,
221 {
222 let payload = Self::encode_json_string(value)?;
223 let added: usize = redis::cmd("SADD").arg(key).arg(payload).query(&mut self.inner)?;
224 Ok(added)
225 }
226
227 pub fn smembers<K, T>(&mut self, key: K) -> Result<Vec<T>, VldRedisError>
228 where
229 K: redis::ToRedisArgs,
230 T: vld::schema::VldParse,
231 {
232 let raw: Vec<Vec<u8>> = redis::cmd("SMEMBERS").arg(key).query(&mut self.inner)?;
233 raw.into_iter()
234 .map(|bytes| Self::decode_json_bytes(&bytes))
235 .collect()
236 }
237
238 pub fn zadd<K, V>(&mut self, key: K, score: f64, value: &V) -> Result<usize, VldRedisError>
239 where
240 K: redis::ToRedisArgs,
241 V: serde::Serialize + vld::schema::VldParse + ?Sized,
242 {
243 let payload = Self::encode_json_string(value)?;
244 let added: usize = redis::cmd("ZADD")
245 .arg(key)
246 .arg(score)
247 .arg(payload)
248 .query(&mut self.inner)?;
249 Ok(added)
250 }
251
252 pub fn zrange<K, T>(&mut self, key: K, start: isize, stop: isize) -> Result<Vec<T>, VldRedisError>
253 where
254 K: redis::ToRedisArgs,
255 T: vld::schema::VldParse,
256 {
257 let raw: Vec<Vec<u8>> = redis::cmd("ZRANGE")
258 .arg(key)
259 .arg(start)
260 .arg(stop)
261 .query(&mut self.inner)?;
262 raw.into_iter()
263 .map(|bytes| Self::decode_json_bytes(&bytes))
264 .collect()
265 }
266
267 pub fn publish<Cn, V>(&mut self, channel: Cn, value: &V) -> Result<i64, VldRedisError>
268 where
269 Cn: redis::ToRedisArgs,
270 V: serde::Serialize + vld::schema::VldParse + ?Sized,
271 {
272 let payload = Self::encode_json_bytes(value)?;
273 let delivered: i64 = redis::cmd("PUBLISH")
274 .arg(channel)
275 .arg(payload)
276 .query(&mut self.inner)?;
277 Ok(delivered)
278 }
279}
280
281#[derive(Debug)]
282pub enum VldRedisError {
283 Validation(vld::error::VldError),
284 Serialization(String),
285 Deserialization(String),
286 Redis(redis::RedisError),
287}
288
289impl fmt::Display for VldRedisError {
290 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
291 match self {
292 VldRedisError::Validation(e) => write!(f, "Validation error: {e}"),
293 VldRedisError::Serialization(e) => write!(f, "Serialization error: {e}"),
294 VldRedisError::Deserialization(e) => write!(f, "Deserialization error: {e}"),
295 VldRedisError::Redis(e) => write!(f, "Redis error: {e}"),
296 }
297 }
298}
299
300impl std::error::Error for VldRedisError {
301 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
302 match self {
303 VldRedisError::Validation(e) => Some(e),
304 VldRedisError::Redis(e) => Some(e),
305 VldRedisError::Serialization(_) | VldRedisError::Deserialization(_) => None,
306 }
307 }
308}
309
310impl From<vld::error::VldError> for VldRedisError {
311 fn from(value: vld::error::VldError) -> Self {
312 Self::Validation(value)
313 }
314}
315
316impl From<redis::RedisError> for VldRedisError {
317 fn from(value: redis::RedisError) -> Self {
318 Self::Redis(value)
319 }
320}
321
322#[macro_export]
324macro_rules! impl_to_redis {
325 ($conn:ident) => {
326 let mut $conn = $crate::RedisConn::new($conn);
327 };
328}
329
330pub mod prelude {
331 pub use crate::VldRedisError;
332 pub use crate::{impl_to_redis, RedisConn};
333 pub use vld::prelude::*;
334}