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; 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 { 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 { 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] 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] it "min lower_bound" {
359 assert_scan!(b"");
360 }
361
362 #[should_panic] 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}