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,
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,
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,
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,
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)).transpose()
116 }
117
118 pub fn mset<'a, K, V, I>(&mut self, items: I) -> Result<(), VldRedisError>
119 where
120 I: IntoIterator<Item = (K, &'a V)>,
121 K: redis::ToRedisArgs,
122 V: serde::Serialize + vld::schema::VldParse + 'a,
123 {
124 let mut cmd = redis::cmd("MSET");
125 for (key, value) in items {
126 let encoded = Self::encode_json_string(value)?;
127 cmd.arg(key).arg(encoded);
128 }
129 cmd.query::<()>(&mut self.inner)?;
130 Ok(())
131 }
132
133 pub fn mget<K, T, I>(&mut self, keys: I) -> Result<Vec<Option<T>>, VldRedisError>
134 where
135 I: IntoIterator<Item = K>,
136 K: redis::ToRedisArgs,
137 T: vld::schema::VldParse,
138 {
139 let mut cmd = redis::cmd("MGET");
140 for key in keys {
141 cmd.arg(key);
142 }
143 let raw: Vec<Option<Vec<u8>>> = cmd.query(&mut self.inner)?;
144 raw.into_iter()
145 .map(|opt| opt.map(|bytes| Self::decode_json_bytes(&bytes)).transpose())
146 .collect()
147 }
148
149 pub fn hset<K, F, V>(&mut self, key: K, field: F, value: &V) -> Result<(), VldRedisError>
150 where
151 K: redis::ToRedisArgs,
152 F: redis::ToRedisArgs,
153 V: serde::Serialize + vld::schema::VldParse,
154 {
155 let s = Self::encode_json_string(value)?;
156 redis::cmd("HSET")
157 .arg(key)
158 .arg(field)
159 .arg(s)
160 .query::<()>(&mut self.inner)?;
161 Ok(())
162 }
163
164 pub fn hget<K, F, T>(&mut self, key: K, field: F) -> Result<Option<T>, VldRedisError>
165 where
166 K: redis::ToRedisArgs,
167 F: redis::ToRedisArgs,
168 T: vld::schema::VldParse,
169 {
170 let raw: Option<Vec<u8>> = redis::cmd("HGET")
171 .arg(key)
172 .arg(field)
173 .query(&mut self.inner)?;
174 raw.map(|bytes| Self::decode_json_bytes(&bytes)).transpose()
175 }
176
177 pub fn lpush<K, V>(&mut self, key: K, value: &V) -> Result<usize, VldRedisError>
178 where
179 K: redis::ToRedisArgs,
180 V: serde::Serialize + vld::schema::VldParse,
181 {
182 let payload = Self::encode_json_string(value)?;
183 let len: usize = redis::cmd("LPUSH")
184 .arg(key)
185 .arg(payload)
186 .query(&mut self.inner)?;
187 Ok(len)
188 }
189
190 pub fn rpush<K, V>(&mut self, key: K, value: &V) -> Result<usize, VldRedisError>
191 where
192 K: redis::ToRedisArgs,
193 V: serde::Serialize + vld::schema::VldParse,
194 {
195 let payload = Self::encode_json_string(value)?;
196 let len: usize = redis::cmd("RPUSH")
197 .arg(key)
198 .arg(payload)
199 .query(&mut self.inner)?;
200 Ok(len)
201 }
202
203 pub fn lpop<K, T>(&mut self, key: K) -> Result<Option<T>, VldRedisError>
204 where
205 K: redis::ToRedisArgs,
206 T: vld::schema::VldParse,
207 {
208 let raw: Option<Vec<u8>> = redis::cmd("LPOP").arg(key).query(&mut self.inner)?;
209 raw.map(|bytes| Self::decode_json_bytes(&bytes)).transpose()
210 }
211
212 pub fn rpop<K, T>(&mut self, key: K) -> Result<Option<T>, VldRedisError>
213 where
214 K: redis::ToRedisArgs,
215 T: vld::schema::VldParse,
216 {
217 let raw: Option<Vec<u8>> = redis::cmd("RPOP").arg(key).query(&mut self.inner)?;
218 raw.map(|bytes| Self::decode_json_bytes(&bytes)).transpose()
219 }
220
221 pub fn sadd<K, V>(&mut self, key: K, value: &V) -> Result<usize, VldRedisError>
222 where
223 K: redis::ToRedisArgs,
224 V: serde::Serialize + vld::schema::VldParse,
225 {
226 let payload = Self::encode_json_string(value)?;
227 let added: usize = redis::cmd("SADD")
228 .arg(key)
229 .arg(payload)
230 .query(&mut self.inner)?;
231 Ok(added)
232 }
233
234 pub fn smembers<K, T>(&mut self, key: K) -> Result<Vec<T>, VldRedisError>
235 where
236 K: redis::ToRedisArgs,
237 T: vld::schema::VldParse,
238 {
239 let raw: Vec<Vec<u8>> = redis::cmd("SMEMBERS").arg(key).query(&mut self.inner)?;
240 raw.into_iter()
241 .map(|bytes| Self::decode_json_bytes(&bytes))
242 .collect()
243 }
244
245 pub fn zadd<K, V>(&mut self, key: K, score: f64, value: &V) -> Result<usize, VldRedisError>
246 where
247 K: redis::ToRedisArgs,
248 V: serde::Serialize + vld::schema::VldParse,
249 {
250 let payload = Self::encode_json_string(value)?;
251 let added: usize = redis::cmd("ZADD")
252 .arg(key)
253 .arg(score)
254 .arg(payload)
255 .query(&mut self.inner)?;
256 Ok(added)
257 }
258
259 pub fn zrange<K, T>(
260 &mut self,
261 key: K,
262 start: isize,
263 stop: isize,
264 ) -> Result<Vec<T>, VldRedisError>
265 where
266 K: redis::ToRedisArgs,
267 T: vld::schema::VldParse,
268 {
269 let raw: Vec<Vec<u8>> = redis::cmd("ZRANGE")
270 .arg(key)
271 .arg(start)
272 .arg(stop)
273 .query(&mut self.inner)?;
274 raw.into_iter()
275 .map(|bytes| Self::decode_json_bytes(&bytes))
276 .collect()
277 }
278
279 pub fn publish<Cn, V>(&mut self, channel: Cn, value: &V) -> Result<i64, VldRedisError>
280 where
281 Cn: redis::ToRedisArgs,
282 V: serde::Serialize + vld::schema::VldParse,
283 {
284 let payload = Self::encode_json_bytes(value)?;
285 let delivered: i64 = redis::cmd("PUBLISH")
286 .arg(channel)
287 .arg(payload)
288 .query(&mut self.inner)?;
289 Ok(delivered)
290 }
291}
292
293#[derive(Debug)]
294pub enum VldRedisError {
295 Validation(vld::error::VldError),
296 Serialization(String),
297 Deserialization(String),
298 Redis(redis::RedisError),
299}
300
301impl fmt::Display for VldRedisError {
302 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
303 match self {
304 VldRedisError::Validation(e) => write!(f, "Validation error: {e}"),
305 VldRedisError::Serialization(e) => write!(f, "Serialization error: {e}"),
306 VldRedisError::Deserialization(e) => write!(f, "Deserialization error: {e}"),
307 VldRedisError::Redis(e) => write!(f, "Redis error: {e}"),
308 }
309 }
310}
311
312impl std::error::Error for VldRedisError {
313 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
314 match self {
315 VldRedisError::Validation(e) => Some(e),
316 VldRedisError::Redis(e) => Some(e),
317 VldRedisError::Serialization(_) | VldRedisError::Deserialization(_) => None,
318 }
319 }
320}
321
322impl From<vld::error::VldError> for VldRedisError {
323 fn from(value: vld::error::VldError) -> Self {
324 Self::Validation(value)
325 }
326}
327
328impl From<redis::RedisError> for VldRedisError {
329 fn from(value: redis::RedisError) -> Self {
330 Self::Redis(value)
331 }
332}
333
334#[macro_export]
336macro_rules! impl_to_redis {
337 ($conn:ident) => {
338 let mut $conn = $crate::RedisConn::new($conn);
339 };
340}
341
342pub mod prelude {
343 pub use crate::VldRedisError;
344 pub use crate::{impl_to_redis, RedisConn};
345 pub use vld::prelude::*;
346}