Skip to main content

undis/
command.rs

1//! Helper methods for each Redis commands.
2//!
3//! For more information, see the [`CommandHelper`](CommandHelper) type.
4
5use futures_core::future::BoxFuture;
6use serde::{de::DeserializeOwned, Deserialize, Serialize};
7
8use crate::connection::Error;
9
10mod base;
11mod hash;
12mod strings;
13
14/// A wrapper to provide helper methods for each Redis command.
15#[derive(Debug)]
16pub struct CommandHelper<T: RawCommand>(pub T);
17
18/// A Mutex-based wrapper to adapt [`impl RawCommandMut`](RawCommandMut)
19/// into [`CommandHelper`](CommandHelper). This is required since all its methods require `&self`.
20#[derive(Debug)]
21pub struct Mutex<T>(tokio::sync::Mutex<T>);
22
23// To ensure response is constant "OK"
24#[derive(Debug, Deserialize)]
25enum OkResp {
26    OK,
27}
28
29/// A trait for sending raw commands to the Redis server with `&self`.
30pub trait RawCommand: Send + Sync {
31    /// Sends any command and get a response.
32    ///
33    /// Both command and response are serialized/deserialized using [`serde`](serde).
34    /// See [`CommandSerializer`](crate::resp3::ser_cmd::CommandSerializer)
35    /// and [`Deserializer`](crate::resp3::de::Deserializer) for details.
36    ///
37    /// Implementations may also supply an inherent method with the same name and functionality
38    /// to reduce allocation/dynamic dispatch.
39    fn raw_command<'a, Req, Resp>(&'a self, request: Req) -> BoxFuture<'a, Result<Resp, Error>>
40    where
41        Req: Serialize + Send + 'a,
42        Resp: DeserializeOwned + 'a;
43}
44
45/// A trait for sending raw commands to the Redis server with `&mut self`.
46pub trait RawCommandMut: Send {
47    /// Sends any command and get a response.
48    ///
49    /// Both command and response are serialized/deserialized using [`serde`](serde).
50    /// See [`CommandSerializer`](crate::resp3::ser_cmd::CommandSerializer)
51    /// and [`Deserializer`](crate::resp3::de::Deserializer) for details.
52    ///
53    /// Returned response may contain a reference to the connection's internal receive buffer.
54    ///
55    /// Implementations may also have inherent method with same name and functionality
56    /// to reduce allocation/dynamic dispatch.
57    fn raw_command<'de, Req, Resp>(
58        &'de mut self,
59        request: Req,
60    ) -> BoxFuture<'de, Result<Resp, Error>>
61    where
62        Req: Serialize + Send + 'de,
63        Resp: Deserialize<'de> + 'de;
64
65    /// Wraps `self` to allow calling helper methods.
66    fn command(self) -> CommandHelper<Mutex<Self>>
67    where
68        Self: Sized,
69    {
70        CommandHelper(Mutex::new(self))
71    }
72}
73
74impl<T: RawCommand> CommandHelper<T> {
75    /// Sends any command and get a response.
76    ///
77    /// Both command and response are serialized/deserialized using [`serde`](serde).
78    /// See [`CommandSerializer`](crate::resp3::ser_cmd::CommandSerializer)
79    /// and [`Deserializer`](crate::resp3::de::Deserializer) for details.
80    pub async fn raw_command<Req, Resp>(&self, request: Req) -> Result<Resp, Error>
81    where
82        Req: Serialize + Send,
83        Resp: DeserializeOwned,
84    {
85        self.0.raw_command(request).await
86    }
87}
88
89impl<T: RawCommand> From<T> for CommandHelper<T> {
90    fn from(v: T) -> Self {
91        CommandHelper(v)
92    }
93}
94
95impl<T> Mutex<T> {
96    /// Constructs a mutex from the value.
97    pub fn new(value: T) -> Self {
98        Mutex(tokio::sync::Mutex::new(value))
99    }
100
101    /// Returns a mutable reference to the underlying data.
102    ///
103    /// It doesn't require any synchronization as it takes `&mut self`.
104    pub fn get_mut(&mut self) -> &mut T {
105        self.0.get_mut()
106    }
107
108    /// Consumes this mutex, returning the underlying data.
109    pub fn into_inner(self) -> T {
110        self.0.into_inner()
111    }
112}
113
114impl<T: RawCommandMut> RawCommand for Mutex<T> {
115    fn raw_command<'a, Req, Resp>(&'a self, request: Req) -> BoxFuture<'a, Result<Resp, Error>>
116    where
117        Req: Serialize + Send + 'a,
118        Resp: DeserializeOwned,
119    {
120        Box::pin(async move { self.0.lock().await.raw_command(request).await })
121    }
122}
123
124impl<T> From<T> for Mutex<T> {
125    fn from(v: T) -> Self {
126        Mutex(v.into())
127    }
128}
129
130impl<'r, T: RawCommand> RawCommand for &'r T {
131    fn raw_command<'a, Req, Resp>(&'a self, request: Req) -> BoxFuture<'a, Result<Resp, Error>>
132    where
133        Req: Serialize + Send + 'a,
134        Resp: DeserializeOwned + 'a,
135    {
136        (**self).raw_command(request)
137    }
138}
139
140impl<'a, T: RawCommandMut> RawCommandMut for &'a mut T {
141    fn raw_command<'de, Req, Resp>(
142        &'de mut self,
143        request: Req,
144    ) -> BoxFuture<'de, Result<Resp, Error>>
145    where
146        Req: Serialize + Send + 'de,
147        Resp: Deserialize<'de> + 'de,
148    {
149        (**self).raw_command(request)
150    }
151}