Skip to main content

fast_cache/storage/
command.rs

1use crate::Result;
2use crate::commands::{BorrowedCommandBox, CommandCatalog, OwnedCommandBox};
3use crate::protocol::{BorrowedCommandFrame, Frame, RespCodec};
4
5#[derive(Debug)]
6pub struct Command {
7    inner: OwnedCommandBox,
8}
9
10impl Command {
11    pub(crate) fn new(inner: OwnedCommandBox) -> Self {
12        Self { inner }
13    }
14
15    pub fn from_frame(frame: Frame) -> Result<Self> {
16        let parts = RespCodec::as_command(frame)?.parts;
17        CommandCatalog::parse_owned(&parts)
18    }
19
20    pub fn name(&self) -> &'static str {
21        self.inner.name()
22    }
23
24    pub fn mutates_value(&self) -> bool {
25        self.inner.mutates_value()
26    }
27
28    pub fn route_key(&self) -> Option<&[u8]> {
29        self.inner.route_key()
30    }
31
32    pub(crate) fn to_borrowed_command(&self) -> BorrowedCommand<'_> {
33        BorrowedCommand::new(self.inner.to_borrowed_command())
34    }
35}
36
37#[derive(Debug)]
38pub struct BorrowedCommand<'a> {
39    inner: BorrowedCommandBox<'a>,
40}
41
42impl<'a> BorrowedCommand<'a> {
43    pub(crate) fn new(inner: BorrowedCommandBox<'a>) -> Self {
44        Self { inner }
45    }
46
47    pub fn from_frame(frame: BorrowedCommandFrame<'a>) -> Result<Self> {
48        Self::from_parts(&frame.parts)
49    }
50
51    pub fn from_parts(parts: &[&'a [u8]]) -> Result<Self> {
52        CommandCatalog::parse_borrowed(parts).map(Self::new)
53    }
54
55    pub fn name(&self) -> &'static str {
56        self.inner.name()
57    }
58
59    pub fn mutates_value(&self) -> bool {
60        self.inner.mutates_value()
61    }
62
63    pub fn route_key(&self) -> Option<&'a [u8]> {
64        self.inner.route_key()
65    }
66
67    pub(crate) fn supports_spanned_resp(&self) -> bool {
68        self.inner.supports_spanned_resp()
69    }
70
71    pub fn to_owned_command(&self) -> Command {
72        self.inner.to_owned_command()
73    }
74
75    pub(crate) fn execute_engine<'b>(
76        &'b self,
77        ctx: crate::storage::EngineCommandContext<'b>,
78    ) -> crate::storage::EngineFrameFuture<'b>
79    where
80        'a: 'b,
81    {
82        self.inner.execute_engine(ctx)
83    }
84
85    #[cfg(feature = "server")]
86    pub(crate) fn execute_borrowed_frame(
87        &self,
88        store: &crate::storage::EmbeddedStore,
89        now_ms: u64,
90    ) -> Frame {
91        self.inner.execute_borrowed_frame(store, now_ms)
92    }
93
94    #[cfg(feature = "server")]
95    pub(crate) fn execute_borrowed(
96        &self,
97        ctx: crate::server::commands::BorrowedCommandContext<'_, '_, '_>,
98    ) {
99        self.inner.execute_borrowed(ctx);
100    }
101
102    #[cfg(feature = "server")]
103    pub(crate) fn execute_direct_borrowed(
104        &self,
105        ctx: crate::server::commands::DirectCommandContext,
106    ) -> Frame {
107        self.inner.execute_direct_borrowed(ctx)
108    }
109}
110
111#[cfg(test)]
112mod tests {
113    use crate::commands::CommandCatalog;
114    use crate::protocol::Frame;
115
116    use super::{BorrowedCommand, Command};
117
118    #[test]
119    fn parses_set_with_ttl() {
120        let command = Command::from_frame(Frame::Array(vec![
121            Frame::BlobString(b"SET".to_vec()),
122            Frame::BlobString(b"alpha".to_vec()),
123            Frame::BlobString(b"beta".to_vec()),
124            Frame::BlobString(b"EX".to_vec()),
125            Frame::BlobString(b"5".to_vec()),
126        ]))
127        .unwrap();
128
129        assert_eq!(command.name(), "SET");
130        assert!(command.mutates_value());
131        assert_eq!(command.route_key(), Some(b"alpha".as_slice()));
132    }
133
134    #[test]
135    fn parses_get_command() {
136        let command =
137            BorrowedCommand::from_parts(&[b"GET".as_slice(), b"alpha".as_slice()]).unwrap();
138
139        assert_eq!(command.name(), "GET");
140        assert!(!command.mutates_value());
141        assert_eq!(command.route_key(), Some(b"alpha".as_slice()));
142    }
143
144    #[test]
145    fn parses_del_command() {
146        let command = BorrowedCommand::from_parts(&[
147            b"DEL".as_slice(),
148            b"alpha".as_slice(),
149            b"beta".as_slice(),
150        ])
151        .unwrap();
152
153        assert_eq!(command.name(), "DEL");
154        assert!(command.mutates_value());
155        assert_eq!(command.route_key(), Some(b"alpha".as_slice()));
156        assert_eq!(
157            command.to_owned_command().route_key(),
158            Some(b"alpha".as_slice())
159        );
160    }
161
162    #[test]
163    fn parses_borrowed_command_object() {
164        let command = CommandCatalog::parse_borrowed(&[
165            b"SET".as_slice(),
166            b"alpha".as_slice(),
167            b"beta".as_slice(),
168        ])
169        .unwrap();
170
171        assert_eq!(command.name(), "SET");
172        assert!(command.mutates_value());
173        assert_eq!(command.route_key(), Some(b"alpha".as_slice()));
174        assert_eq!(
175            command.to_owned_command().route_key(),
176            Some(b"alpha".as_slice())
177        );
178    }
179}