bronzedb_protocol/
request.rs

1use crate::ext::{ReadKVExt, WriteKVExt};
2use crate::{MAX_KEY, MIN_KEY};
3use bronzedb_util::types::{Key, Value};
4use byteorder::{ReadBytesExt, WriteBytesExt};
5use std::io::{self, Read, Write};
6use std::ops::Deref;
7use std::u8::MAX;
8
9#[derive(Debug, Copy, Clone)]
10pub enum Action {
11    NoResponse = 0,
12    Ping = 1,
13    Set = 2,
14    Get = 3,
15    Delete = 4,
16    Scan = 5,
17    Unknown = MAX as isize,
18}
19
20impl From<u8> for Action {
21    fn from(value: u8) -> Self {
22        match value {
23            0 => Action::NoResponse,
24            1 => Action::Ping,
25            2 => Action::Set,
26            3 => Action::Get,
27            4 => Action::Delete,
28            5 => Action::Scan,
29            _ => Action::Unknown,
30        }
31    }
32}
33
34pub enum Request {
35    NoResponse,
36    Ping,
37    Set(Key, Value),
38    Get(Key),
39    Delete(Key),
40    Scan {
41        lower_bound: Option<Key>,
42        upper_bound: Option<Key>,
43    },
44    Unknown,
45}
46
47impl Request {
48    pub fn write_to(self, mut writer: impl Write) -> io::Result<usize> {
49        let mut counter = 1usize; // for Action
50        match self {
51            Request::Set(key, value) => {
52                writer.write_u8(Action::Set as u8)?;
53                counter += writer.write_key(&key)?;
54                counter += writer.write_value(&value)?;
55            }
56
57            Request::Get(key) => {
58                writer.write_u8(Action::Get as u8)?;
59                counter += writer.write_key(&key)?;
60            }
61
62            Request::Delete(key) => {
63                writer.write_u8(Action::Delete as u8)?;
64                counter += writer.write_key(&key)?;
65            }
66
67            Request::Scan {
68                lower_bound,
69                upper_bound,
70            } => {
71                writer.write_u8(Action::Scan as u8)?;
72                let lower_key = match lower_bound.as_ref() {
73                    Some(key) => key.deref(),
74                    None => MIN_KEY,
75                };
76                let upper_key = match upper_bound.as_ref() {
77                    Some(key) => key.deref(),
78                    None => MAX_KEY,
79                };
80                counter += writer.write_key(&lower_key)?;
81                counter += writer.write_key(&upper_key)?;
82            }
83
84            Request::Ping => writer.write_u8(Action::Ping as u8)?,
85            Request::NoResponse => writer.write_u8(Action::NoResponse as u8)?,
86            Request::Unknown => panic!("cannot send Request::Unknown"),
87        }
88        Ok(counter)
89    }
90}
91
92impl Request {
93    pub fn read_from(mut reader: impl Read) -> io::Result<Self> {
94        let action = reader.read_u8()?.into();
95        match action {
96            Action::Set => Ok(Request::Set(
97                reader.read_key()?.into(),
98                reader.read_value()?,
99            )),
100            Action::Get => Ok(Request::Get(reader.read_key()?.into())),
101            Action::Delete => Ok(Request::Delete(reader.read_key()?.into())),
102            Action::Scan => {
103                let lower_bound = reader.read_key()?;
104                let upper_bound = reader.read_key()?;
105                Ok(Request::Scan {
106                    lower_bound: if lower_bound.as_slice() == MIN_KEY {
107                        None
108                    } else {
109                        Some(lower_bound.into())
110                    },
111                    upper_bound: if upper_bound.as_slice() == MAX_KEY {
112                        None
113                    } else {
114                        Some(upper_bound.into())
115                    },
116                })
117            }
118            Action::Ping => Ok(Request::Ping),
119            Action::NoResponse => Ok(Request::NoResponse),
120            Action::Unknown => Ok(Request::Unknown),
121        }
122    }
123}
124
125#[cfg(test)]
126mod tests {
127    use super::Request;
128    use crate::{MAX_KEY, MAX_KEY_LEN, MAX_VALUE_LEN, MIN_KEY};
129    use matches::matches;
130    use speculate::speculate;
131    use std::io::Cursor;
132    use bronzedb_util::status::Result;
133
134    pub trait RequestTestExt: Sized {
135        fn transfer_move(self) -> Result<(Self, usize)>;
136    }
137
138    impl RequestTestExt for Request {
139        fn transfer_move(self) -> Result<(Self, usize)> {
140            let mut buf = Vec::new();
141            let bytes = self.write_to(&mut buf)?;
142            Ok((Request::read_from(&mut Cursor::new(buf))?, bytes))
143        }
144    }
145
146    macro_rules! assert_delete {
147        ($data:expr) => {
148            let (new_request, bytes) = Request::Delete($data[..].to_vec().into())
149                .transfer_move()
150                .unwrap();
151            assert_eq!($data[..].len() + 3, bytes);
152            assert!(matches!(&new_request, Request::Delete(ref _key)));
153            if let Request::Delete(ref key) = new_request {
154                assert_eq!(&$data[..], key.as_slice());
155            }
156        };
157    }
158
159    speculate! {
160        describe "delete" {
161            it "normal" {
162                assert_delete!(b"name");
163            }
164
165            it "zero" {
166                assert_delete!([0; 0]);
167            }
168
169            it "max length" {
170                assert_delete!([0; MAX_KEY_LEN]);
171            }
172
173            #[should_panic]
174            it "overflow" {
175                assert_delete!([0; MAX_KEY_LEN + 1]);
176            }
177        }
178    }
179
180    macro_rules! assert_get {
181        ($data:expr) => {
182            let (new_request, bytes) = Request::Get($data[..].to_vec().into())
183                .transfer_move()
184                .unwrap();
185            assert_eq!($data[..].len() + 3, bytes);
186            assert!(matches!(&new_request, Request::Get(ref _key)));
187            if let Request::Get(ref key) = new_request {
188                assert_eq!(&$data[..], key.as_slice());
189            }
190        };
191    }
192
193    speculate! {
194        describe "get" {
195            it "normal" {
196                assert_get!(b"name");
197            }
198
199            it "zero" {
200                assert_get!([0; 0]);
201            }
202
203            it "max length" {
204                assert_get!([0; MAX_KEY_LEN]);
205            }
206
207            #[should_panic]
208            it "overflow" {
209                assert_get!([0; MAX_KEY_LEN + 1]);
210            }
211        }
212    }
213
214    macro_rules! assert_no_response {
215        () => {
216            let (new_request, bytes) = Request::NoResponse.transfer_move().unwrap();
217            assert_eq!(1, bytes);
218            assert!(matches!(new_request, Request::NoResponse));
219        };
220    }
221
222    speculate! {
223        it "just no response" {
224            assert_no_response!();
225        }
226    }
227
228    macro_rules! assert_ping {
229        () => {
230            let (new_request, bytes) = Request::Ping.transfer_move().unwrap();
231            assert_eq!(1, bytes);
232            assert!(matches!(new_request, Request::Ping));
233        };
234    }
235
236    speculate! {
237        it "just ping" {
238            assert_ping!();
239        }
240    }
241
242    macro_rules! assert_scan {
243        () => {
244            let (new_request, bytes) = Request::Scan {
245                lower_bound: None,
246                upper_bound: None,
247            }
248            .transfer_move()
249            .unwrap();
250            assert_eq!(1 + 4 + MAX_KEY.len() + MIN_KEY.len(), bytes);
251            assert!(matches!(&new_request, Request::Scan{lower_bound: _, upper_bound: _}));
252            if let Request::Scan {
253                lower_bound,
254                upper_bound,
255            } = new_request
256            {
257                assert!(matches!(lower_bound, None));
258                assert!(matches!(upper_bound, None));
259            }
260        };
261
262        ($lower_bound:expr, $upper_bound:expr) => {
263            let (new_request, bytes) = Request::Scan {
264                lower_bound: Some($lower_bound[..].to_vec().into()),
265                upper_bound: Some($upper_bound[..].to_vec().into()),
266            }
267            .transfer_move()
268            .unwrap();
269            assert_eq!(1 + 4 + $lower_bound[..].len() + $upper_bound[..].len(), bytes);
270            assert!(matches!(&new_request, Request::Scan{lower_bound: _, upper_bound: _}));
271            if let Request::Scan {
272                lower_bound,
273                upper_bound,
274            } = new_request
275            {
276                assert!(matches!(lower_bound, Some(ref _key)));
277                assert!(matches!(upper_bound, Some(ref _key)));
278                assert_eq!(&$lower_bound[..], lower_bound.unwrap().as_slice());
279                assert_eq!(&$upper_bound[..], upper_bound.unwrap().as_slice());
280            }
281        };
282
283        ($any_bound:expr) => {
284            { // lower_bound
285                let (new_request, bytes) = Request::Scan {
286                    lower_bound: Some($any_bound[..].to_vec().into()),
287                    upper_bound: None,
288                }
289                .transfer_move()
290                .unwrap();
291                assert_eq!(1 + 4 + $any_bound[..].len() + MAX_KEY.len(), bytes);
292                assert!(matches!(&new_request, Request::Scan{lower_bound: _, upper_bound: _}));
293                if let Request::Scan {
294                    lower_bound,
295                    upper_bound,
296                } = new_request
297                {
298                    assert!(matches!(lower_bound, Some(ref _key)));
299                    assert!(matches!(upper_bound, None));
300                    assert_eq!(&$any_bound[..], lower_bound.unwrap().as_slice());
301                }
302            }
303            { // upper_bound
304                let (new_request, bytes) = Request::Scan {
305                    lower_bound: None,
306                    upper_bound: Some($any_bound[..].to_vec().into()),
307                }
308                .transfer_move()
309                .unwrap();
310                assert_eq!(1 + 4 + MIN_KEY.len() + $any_bound[..].len(), bytes);
311                assert!(matches!(&new_request, Request::Scan{lower_bound: _, upper_bound: _}));
312                if let Request::Scan {
313                    lower_bound,
314                    upper_bound,
315                } = new_request
316                {
317                    assert!(matches!(lower_bound, None));
318                    assert!(matches!(upper_bound, Some(ref _key)));
319                    assert_eq!(&$any_bound[..], upper_bound.unwrap().as_slice());
320                }
321            }
322        };
323    }
324
325    speculate! {
326        use std::u8::MAX;
327
328        describe "scan with two bounds" {
329            it "normal" {
330                assert_scan!(b"last_name", b"name");
331            }
332
333            it "max length" {
334                assert_scan!([1; MAX_KEY_LEN], [MAX - 1; MAX_KEY_LEN]);
335            }
336
337            #[should_panic] // should be (None, None)
338            it "max range" {
339                assert_scan!(b"", [MAX; MAX_KEY_LEN]);
340            }
341
342            #[should_panic]
343            it "overflow" {
344                assert_scan!([0; MAX_KEY_LEN + 1], [MAX; MAX_KEY_LEN + 1]);
345            }
346        }
347
348        describe "scan with one bound" {
349            it "normal" {
350                assert_scan!(b"last_name");
351            }
352
353            it "max length" {
354                assert_scan!([1; MAX_KEY_LEN]);
355            }
356
357            #[should_panic] // should be (None, None)
358            it "min lower_bound" {
359                assert_scan!(b"");
360            }
361
362            #[should_panic] // should be (None, None)
363            it "max upper_bound" {
364                assert_scan!([MAX; MAX_KEY_LEN]);
365            }
366
367            #[should_panic]
368            it "overflow" {
369                assert_scan!([0; MAX_KEY_LEN + 1]);
370            }
371        }
372
373        describe "scan with no bound" {
374            it "normal" {
375                assert_scan!();
376            }
377        }
378    }
379
380    macro_rules! assert_set {
381        ($key:expr, $value:expr) => {
382            let (new_request, bytes) =
383                Request::Set($key[..].to_vec().into(), $value[..].to_vec().into())
384                    .transfer_move()
385                    .unwrap();
386            assert_eq!(5 + $key.len() + $value.len(), bytes);
387            assert!(matches!(&new_request, Request::Set(ref _key, ref _value)));
388            if let Request::Set(ref key, ref value) = new_request {
389                assert_eq!(&$key[..], key.as_slice());
390                assert_eq!(&$value[..], value.as_slice());
391            }
392        };
393    }
394
395    speculate! {
396        describe "set" {
397            it "normal" {
398                assert_set!(b"name", b"hexi");
399            }
400
401            it "zero" {
402                assert_set!([0; 0], [0; 0]);
403            }
404
405            it "max length" {
406                assert_set!([0; MAX_KEY_LEN], [0; MAX_VALUE_LEN]);
407            }
408
409            #[should_panic]
410            it "key overflow" {
411                assert_set!([0; MAX_KEY_LEN + 1], [0; MAX_VALUE_LEN]);
412            }
413
414            #[should_panic]
415            it "value overflow" {
416                assert_set!([0; MAX_KEY_LEN], [0; MAX_VALUE_LEN + 1]);
417            }
418        }
419    }
420}