redis_asio/base/
command.rs

1use crate::RespInternalValue;
2
3
4/// Make a Redis command represents array of `BulkString`s
5/// wrapped into `RedisCommand`.
6///
7/// # Example
8///
9/// ```
10/// use redis_asio::command;
11/// let cmd = redis_asio::command("SET").arg("foo").arg("bar");
12/// ```
13pub fn command(cmd: &str) -> RedisCommand {
14    RedisCommand::cmd(cmd)
15}
16
17/// Enumeration of base types that can be put into
18/// `RedisCommand` chain as argument.
19pub enum RedisArgument {
20    Int(i64),
21    String(String),
22    Bytes(Vec<u8>),
23}
24
25/// Redis command wrapper represents array of `BulkString`s
26#[derive(Clone)]
27pub struct RedisCommand {
28    args: Vec<RespInternalValue>,
29}
30
31/// Trait interface requires to implement method to convert base type
32/// into `RedisArgument`.
33///
34/// # Example
35/// ```
36/// use redis_asio::{RedisArgument, IntoRedisArgument, command};
37///
38/// struct ClientStruct { pub data: String }
39///
40/// impl IntoRedisArgument for ClientStruct {
41///     fn into_redis_argument(self) -> RedisArgument {
42///         RedisArgument::String(self.data)
43///     }
44/// }
45///
46/// let value = ClientStruct { data: "Hello, world".to_string() };
47/// let cmd = command("SET").arg("foo").arg(value);
48/// ```
49pub trait IntoRedisArgument {
50    fn into_redis_argument(self) -> RedisArgument;
51}
52
53impl RedisCommand {
54    pub(crate) fn new() -> RedisCommand {
55        RedisCommand { args: Vec::new() }
56    }
57
58    /// Method is used by `redis::command()`.
59    pub(crate) fn cmd(cmd: &str) -> RedisCommand {
60        RedisCommand {
61            args: vec![RespInternalValue::BulkString(cmd.as_bytes().to_vec())]
62        }
63    }
64
65    /// Add new argument into `RedisCommand` and move the one back.
66    /// The argument should implement the `IntoRedisArgument` trait.
67    pub fn arg<T: IntoRedisArgument>(mut self, arg: T) -> RedisCommand {
68        self.args.push(arg.into_redis_argument().into_resp_value());
69        self
70    }
71
72    /// Add new argument into `RedisCommand` through object changing.
73    /// The argument should implement the `IntoRedisArgument` trait.
74    pub fn arg_mut<T: IntoRedisArgument>(&mut self, arg: T) {
75        self.args.push(arg.into_redis_argument().into_resp_value());
76    }
77
78    /// Append the other `RedisCommand`'s arguments into self arguments.
79    pub fn append(&mut self, mut other: RedisCommand) {
80        self.args.append(&mut other.args);
81    }
82
83    // TODO make it pub(crate) maybe.
84    /// Convert the self into `RespInternalValue`.
85    pub fn into_resp_value(self) -> RespInternalValue {
86        RespInternalValue::Array(self.args)
87    }
88}
89
90impl RedisArgument {
91    pub(crate) fn into_resp_value(self) -> RespInternalValue {
92        match self {
93            RedisArgument::Int(x) => RespInternalValue::BulkString(x.to_string().into()),
94            RedisArgument::String(x) => RespInternalValue::BulkString(x.into()),
95            RedisArgument::Bytes(x) => RespInternalValue::BulkString(x),
96        }
97    }
98}
99
100impl IntoRedisArgument for RedisArgument {
101    fn into_redis_argument(self) -> RedisArgument {
102        self
103    }
104}
105
106impl IntoRedisArgument for &str {
107    fn into_redis_argument(self) -> RedisArgument {
108        RedisArgument::String(self.to_string())
109    }
110}
111
112impl IntoRedisArgument for String {
113    fn into_redis_argument(self) -> RedisArgument {
114        RedisArgument::String(self)
115    }
116}
117
118impl IntoRedisArgument for Vec<u8> {
119    fn into_redis_argument(self) -> RedisArgument {
120        RedisArgument::Bytes(self)
121    }
122}
123
124macro_rules! declare_to_int_argument {
125    ($itype:ty) => {
126        impl IntoRedisArgument for $itype {
127            fn into_redis_argument(self) -> RedisArgument {
128                RedisArgument::Int(self as i64)
129            }
130        }
131    };
132}
133
134declare_to_int_argument!(u8);
135declare_to_int_argument!(i8);
136declare_to_int_argument!(u16);
137declare_to_int_argument!(i16);
138declare_to_int_argument!(u32);
139declare_to_int_argument!(i32);
140declare_to_int_argument!(i64);
141declare_to_int_argument!(u64);
142declare_to_int_argument!(usize);