1use std::io::Write;
6
7#[derive(Debug, Clone)]
9pub enum Request<'a> {
10 Get { key: &'a [u8] },
12 Gets { keys: &'a [&'a [u8]] },
14 Set {
16 key: &'a [u8],
17 value: &'a [u8],
18 flags: u32,
19 exptime: u32,
20 },
21 Add {
25 key: &'a [u8],
26 value: &'a [u8],
27 flags: u32,
28 exptime: u32,
29 },
30 Replace {
34 key: &'a [u8],
35 value: &'a [u8],
36 flags: u32,
37 exptime: u32,
38 },
39 Incr { key: &'a [u8], delta: u64 },
41 Decr { key: &'a [u8], delta: u64 },
43 Append { key: &'a [u8], value: &'a [u8] },
47 Prepend { key: &'a [u8], value: &'a [u8] },
51 Cas {
55 key: &'a [u8],
56 value: &'a [u8],
57 flags: u32,
58 exptime: u32,
59 cas_unique: u64,
60 },
61 Delete { key: &'a [u8] },
63 FlushAll,
65 Version,
67 Quit,
69}
70
71impl<'a> Request<'a> {
72 #[inline]
74 pub fn get(key: &'a [u8]) -> Self {
75 Request::Get { key }
76 }
77
78 #[inline]
80 pub fn gets(keys: &'a [&'a [u8]]) -> Self {
81 Request::Gets { keys }
82 }
83
84 #[inline]
86 pub fn set(key: &'a [u8], value: &'a [u8]) -> SetRequest<'a> {
87 SetRequest {
88 key,
89 value,
90 flags: 0,
91 exptime: 0,
92 }
93 }
94
95 #[inline]
97 pub fn add(key: &'a [u8], value: &'a [u8]) -> AddRequest<'a> {
98 AddRequest {
99 key,
100 value,
101 flags: 0,
102 exptime: 0,
103 }
104 }
105
106 #[inline]
108 pub fn replace(key: &'a [u8], value: &'a [u8]) -> ReplaceRequest<'a> {
109 ReplaceRequest {
110 key,
111 value,
112 flags: 0,
113 exptime: 0,
114 }
115 }
116
117 #[inline]
119 pub fn incr(key: &'a [u8], delta: u64) -> Self {
120 Request::Incr { key, delta }
121 }
122
123 #[inline]
125 pub fn decr(key: &'a [u8], delta: u64) -> Self {
126 Request::Decr { key, delta }
127 }
128
129 #[inline]
131 pub fn append(key: &'a [u8], value: &'a [u8]) -> Self {
132 Request::Append { key, value }
133 }
134
135 #[inline]
137 pub fn prepend(key: &'a [u8], value: &'a [u8]) -> Self {
138 Request::Prepend { key, value }
139 }
140
141 #[inline]
143 pub fn cas(key: &'a [u8], value: &'a [u8], cas_unique: u64) -> Self {
144 Request::Cas {
145 key,
146 value,
147 flags: 0,
148 exptime: 0,
149 cas_unique,
150 }
151 }
152
153 #[inline]
155 pub fn delete(key: &'a [u8]) -> Self {
156 Request::Delete { key }
157 }
158
159 #[inline]
161 pub fn flush_all() -> Self {
162 Request::FlushAll
163 }
164
165 #[inline]
167 pub fn version() -> Self {
168 Request::Version
169 }
170
171 #[inline]
173 pub fn quit() -> Self {
174 Request::Quit
175 }
176
177 pub fn encode(&self, buf: &mut [u8]) -> usize {
181 match self {
182 Request::Get { key } => encode_get(buf, key),
183 Request::Gets { keys } => encode_gets(buf, keys),
184 Request::Set {
185 key,
186 value,
187 flags,
188 exptime,
189 } => encode_storage(buf, b"set", key, value, *flags, *exptime),
190 Request::Add {
191 key,
192 value,
193 flags,
194 exptime,
195 } => encode_storage(buf, b"add", key, value, *flags, *exptime),
196 Request::Replace {
197 key,
198 value,
199 flags,
200 exptime,
201 } => encode_storage(buf, b"replace", key, value, *flags, *exptime),
202 Request::Incr { key, delta } => encode_incr_decr(buf, b"incr", key, *delta),
203 Request::Decr { key, delta } => encode_incr_decr(buf, b"decr", key, *delta),
204 Request::Append { key, value } => encode_storage(buf, b"append", key, value, 0, 0),
205 Request::Prepend { key, value } => encode_storage(buf, b"prepend", key, value, 0, 0),
206 Request::Cas {
207 key,
208 value,
209 flags,
210 exptime,
211 cas_unique,
212 } => encode_cas(buf, key, value, *flags, *exptime, *cas_unique),
213 Request::Delete { key } => encode_delete(buf, key),
214 Request::FlushAll => encode_simple(buf, b"flush_all"),
215 Request::Version => encode_simple(buf, b"version"),
216 Request::Quit => encode_simple(buf, b"quit"),
217 }
218 }
219}
220
221#[derive(Debug, Clone)]
223pub struct SetRequest<'a> {
224 key: &'a [u8],
225 value: &'a [u8],
226 flags: u32,
227 exptime: u32,
228}
229
230impl<'a> SetRequest<'a> {
231 #[inline]
233 pub fn flags(mut self, flags: u32) -> Self {
234 self.flags = flags;
235 self
236 }
237
238 #[inline]
240 pub fn exptime(mut self, exptime: u32) -> Self {
241 self.exptime = exptime;
242 self
243 }
244
245 #[inline]
247 pub fn build(self) -> Request<'a> {
248 Request::Set {
249 key: self.key,
250 value: self.value,
251 flags: self.flags,
252 exptime: self.exptime,
253 }
254 }
255
256 #[inline]
260 pub fn encode(&self, buf: &mut [u8]) -> usize {
261 encode_storage(buf, b"set", self.key, self.value, self.flags, self.exptime)
262 }
263}
264
265#[derive(Debug, Clone)]
267pub struct AddRequest<'a> {
268 key: &'a [u8],
269 value: &'a [u8],
270 flags: u32,
271 exptime: u32,
272}
273
274impl<'a> AddRequest<'a> {
275 #[inline]
277 pub fn flags(mut self, flags: u32) -> Self {
278 self.flags = flags;
279 self
280 }
281
282 #[inline]
284 pub fn exptime(mut self, exptime: u32) -> Self {
285 self.exptime = exptime;
286 self
287 }
288
289 #[inline]
291 pub fn build(self) -> Request<'a> {
292 Request::Add {
293 key: self.key,
294 value: self.value,
295 flags: self.flags,
296 exptime: self.exptime,
297 }
298 }
299
300 #[inline]
304 pub fn encode(&self, buf: &mut [u8]) -> usize {
305 encode_storage(buf, b"add", self.key, self.value, self.flags, self.exptime)
306 }
307}
308
309#[derive(Debug, Clone)]
311pub struct ReplaceRequest<'a> {
312 key: &'a [u8],
313 value: &'a [u8],
314 flags: u32,
315 exptime: u32,
316}
317
318impl<'a> ReplaceRequest<'a> {
319 #[inline]
321 pub fn flags(mut self, flags: u32) -> Self {
322 self.flags = flags;
323 self
324 }
325
326 #[inline]
328 pub fn exptime(mut self, exptime: u32) -> Self {
329 self.exptime = exptime;
330 self
331 }
332
333 #[inline]
335 pub fn build(self) -> Request<'a> {
336 Request::Replace {
337 key: self.key,
338 value: self.value,
339 flags: self.flags,
340 exptime: self.exptime,
341 }
342 }
343
344 #[inline]
348 pub fn encode(&self, buf: &mut [u8]) -> usize {
349 encode_storage(
350 buf,
351 b"replace",
352 self.key,
353 self.value,
354 self.flags,
355 self.exptime,
356 )
357 }
358}
359
360fn encode_get(buf: &mut [u8], key: &[u8]) -> usize {
362 let mut pos = 0;
363 buf[pos..pos + 4].copy_from_slice(b"get ");
364 pos += 4;
365 buf[pos..pos + key.len()].copy_from_slice(key);
366 pos += key.len();
367 buf[pos..pos + 2].copy_from_slice(b"\r\n");
368 pos + 2
369}
370
371fn encode_gets(buf: &mut [u8], keys: &[&[u8]]) -> usize {
373 if keys.is_empty() {
374 return 0;
375 }
376
377 let mut pos = 0;
378 buf[pos..pos + 4].copy_from_slice(b"gets");
379 pos += 4;
380
381 for key in keys {
382 buf[pos] = b' ';
383 pos += 1;
384 buf[pos..pos + key.len()].copy_from_slice(key);
385 pos += key.len();
386 }
387
388 buf[pos..pos + 2].copy_from_slice(b"\r\n");
389 pos + 2
390}
391
392fn encode_storage(
396 buf: &mut [u8],
397 cmd: &[u8],
398 key: &[u8],
399 value: &[u8],
400 flags: u32,
401 exptime: u32,
402) -> usize {
403 let mut pos = 0;
404
405 buf[pos..pos + cmd.len()].copy_from_slice(cmd);
407 pos += cmd.len();
408 buf[pos] = b' ';
409 pos += 1;
410 buf[pos..pos + key.len()].copy_from_slice(key);
411 pos += key.len();
412 buf[pos] = b' ';
413 pos += 1;
414
415 let mut cursor = std::io::Cursor::new(&mut buf[pos..]);
417 write!(cursor, "{} {} {}\r\n", flags, exptime, value.len()).unwrap();
418 pos += cursor.position() as usize;
419
420 buf[pos..pos + value.len()].copy_from_slice(value);
422 pos += value.len();
423 buf[pos..pos + 2].copy_from_slice(b"\r\n");
424 pos + 2
425}
426
427fn encode_delete(buf: &mut [u8], key: &[u8]) -> usize {
429 let mut pos = 0;
430 buf[pos..pos + 7].copy_from_slice(b"delete ");
431 pos += 7;
432 buf[pos..pos + key.len()].copy_from_slice(key);
433 pos += key.len();
434 buf[pos..pos + 2].copy_from_slice(b"\r\n");
435 pos + 2
436}
437
438fn encode_cas(
440 buf: &mut [u8],
441 key: &[u8],
442 value: &[u8],
443 flags: u32,
444 exptime: u32,
445 cas_unique: u64,
446) -> usize {
447 let mut pos = 0;
448
449 buf[pos..pos + 4].copy_from_slice(b"cas ");
451 pos += 4;
452 buf[pos..pos + key.len()].copy_from_slice(key);
453 pos += key.len();
454 buf[pos] = b' ';
455 pos += 1;
456
457 let mut cursor = std::io::Cursor::new(&mut buf[pos..]);
459 write!(
460 cursor,
461 "{} {} {} {}\r\n",
462 flags,
463 exptime,
464 value.len(),
465 cas_unique
466 )
467 .unwrap();
468 pos += cursor.position() as usize;
469
470 buf[pos..pos + value.len()].copy_from_slice(value);
472 pos += value.len();
473 buf[pos..pos + 2].copy_from_slice(b"\r\n");
474 pos + 2
475}
476
477fn encode_incr_decr(buf: &mut [u8], cmd: &[u8], key: &[u8], delta: u64) -> usize {
479 let mut pos = 0;
480 buf[pos..pos + cmd.len()].copy_from_slice(cmd);
481 pos += cmd.len();
482 buf[pos] = b' ';
483 pos += 1;
484 buf[pos..pos + key.len()].copy_from_slice(key);
485 pos += key.len();
486 buf[pos] = b' ';
487 pos += 1;
488
489 let mut cursor = std::io::Cursor::new(&mut buf[pos..]);
490 write!(cursor, "{}\r\n", delta).unwrap();
491 pos += cursor.position() as usize;
492 pos
493}
494
495fn encode_simple(buf: &mut [u8], cmd: &[u8]) -> usize {
497 buf[..cmd.len()].copy_from_slice(cmd);
498 buf[cmd.len()..cmd.len() + 2].copy_from_slice(b"\r\n");
499 cmd.len() + 2
500}
501
502#[cfg(test)]
503mod tests {
504 use super::*;
505
506 #[test]
507 fn test_encode_get() {
508 let mut buf = [0u8; 64];
509 let len = Request::get(b"mykey").encode(&mut buf);
510 assert_eq!(&buf[..len], b"get mykey\r\n");
511 }
512
513 #[test]
514 fn test_encode_gets() {
515 let mut buf = [0u8; 64];
516 let keys: &[&[u8]] = &[b"key1", b"key2", b"key3"];
517 let len = Request::gets(keys).encode(&mut buf);
518 assert_eq!(&buf[..len], b"gets key1 key2 key3\r\n");
519 }
520
521 #[test]
522 fn test_encode_set() {
523 let mut buf = [0u8; 64];
524 let len = Request::set(b"mykey", b"myvalue").encode(&mut buf);
525 assert_eq!(&buf[..len], b"set mykey 0 0 7\r\nmyvalue\r\n");
526 }
527
528 #[test]
529 fn test_encode_set_with_options() {
530 let mut buf = [0u8; 64];
531 let len = Request::set(b"mykey", b"myvalue")
532 .flags(123)
533 .exptime(3600)
534 .encode(&mut buf);
535 assert_eq!(&buf[..len], b"set mykey 123 3600 7\r\nmyvalue\r\n");
536 }
537
538 #[test]
539 fn test_encode_delete() {
540 let mut buf = [0u8; 64];
541 let len = Request::delete(b"mykey").encode(&mut buf);
542 assert_eq!(&buf[..len], b"delete mykey\r\n");
543 }
544
545 #[test]
546 fn test_encode_flush_all() {
547 let mut buf = [0u8; 64];
548 let len = Request::flush_all().encode(&mut buf);
549 assert_eq!(&buf[..len], b"flush_all\r\n");
550 }
551
552 #[test]
553 fn test_encode_version() {
554 let mut buf = [0u8; 64];
555 let len = Request::version().encode(&mut buf);
556 assert_eq!(&buf[..len], b"version\r\n");
557 }
558
559 #[test]
560 fn test_encode_quit() {
561 let mut buf = [0u8; 64];
562 let len = Request::quit().encode(&mut buf);
563 assert_eq!(&buf[..len], b"quit\r\n");
564 }
565
566 #[test]
569 fn test_set_request_build() {
570 let mut buf = [0u8; 64];
571 let request = Request::set(b"mykey", b"myvalue")
572 .flags(42)
573 .exptime(600)
574 .build();
575 let len = request.encode(&mut buf);
576 assert_eq!(&buf[..len], b"set mykey 42 600 7\r\nmyvalue\r\n");
577 }
578
579 #[test]
580 fn test_encode_gets_empty() {
581 let mut buf = [0u8; 64];
582 let keys: &[&[u8]] = &[];
583 let len = Request::gets(keys).encode(&mut buf);
584 assert_eq!(len, 0);
585 }
586
587 #[test]
588 fn test_encode_gets_single() {
589 let mut buf = [0u8; 64];
590 let keys: &[&[u8]] = &[b"single"];
591 let len = Request::gets(keys).encode(&mut buf);
592 assert_eq!(&buf[..len], b"gets single\r\n");
593 }
594
595 #[test]
596 fn test_request_debug() {
597 let req = Request::get(b"key");
598 let debug_str = format!("{:?}", req);
599 assert!(debug_str.contains("Get"));
600 }
601
602 #[test]
603 fn test_request_clone() {
604 let req1 = Request::get(b"key");
605 let req2 = req1.clone();
606 let mut buf1 = [0u8; 64];
608 let mut buf2 = [0u8; 64];
609 let len1 = req1.encode(&mut buf1);
610 let len2 = req2.encode(&mut buf2);
611 assert_eq!(&buf1[..len1], &buf2[..len2]);
612 }
613
614 #[test]
615 fn test_set_request_debug() {
616 let req = Request::set(b"key", b"value");
617 let debug_str = format!("{:?}", req);
618 assert!(debug_str.contains("SetRequest"));
619 }
620
621 #[test]
622 fn test_set_request_clone() {
623 let req1 = Request::set(b"key", b"value").flags(1);
624 let req2 = req1.clone();
625 let mut buf1 = [0u8; 64];
626 let mut buf2 = [0u8; 64];
627 let len1 = req1.encode(&mut buf1);
628 let len2 = req2.encode(&mut buf2);
629 assert_eq!(&buf1[..len1], &buf2[..len2]);
630 }
631
632 #[test]
633 fn test_encode_set_via_request() {
634 let mut buf = [0u8; 64];
635 let request = Request::Set {
636 key: b"k",
637 value: b"v",
638 flags: 0,
639 exptime: 0,
640 };
641 let len = request.encode(&mut buf);
642 assert_eq!(&buf[..len], b"set k 0 0 1\r\nv\r\n");
643 }
644
645 #[test]
646 fn test_encode_gets_via_request() {
647 let mut buf = [0u8; 64];
648 let keys: &[&[u8]] = &[b"a", b"b"];
649 let request = Request::Gets { keys };
650 let len = request.encode(&mut buf);
651 assert_eq!(&buf[..len], b"gets a b\r\n");
652 }
653
654 #[test]
655 fn test_encode_add() {
656 let mut buf = [0u8; 64];
657 let len = Request::add(b"mykey", b"myvalue").encode(&mut buf);
658 assert_eq!(&buf[..len], b"add mykey 0 0 7\r\nmyvalue\r\n");
659 }
660
661 #[test]
662 fn test_encode_add_with_options() {
663 let mut buf = [0u8; 64];
664 let len = Request::add(b"mykey", b"myvalue")
665 .flags(99)
666 .exptime(300)
667 .encode(&mut buf);
668 assert_eq!(&buf[..len], b"add mykey 99 300 7\r\nmyvalue\r\n");
669 }
670
671 #[test]
672 fn test_add_request_build() {
673 let mut buf = [0u8; 64];
674 let request = Request::add(b"mykey", b"myvalue")
675 .flags(42)
676 .exptime(600)
677 .build();
678 let len = request.encode(&mut buf);
679 assert_eq!(&buf[..len], b"add mykey 42 600 7\r\nmyvalue\r\n");
680 }
681
682 #[test]
683 fn test_encode_add_via_request() {
684 let mut buf = [0u8; 64];
685 let request = Request::Add {
686 key: b"k",
687 value: b"v",
688 flags: 0,
689 exptime: 0,
690 };
691 let len = request.encode(&mut buf);
692 assert_eq!(&buf[..len], b"add k 0 0 1\r\nv\r\n");
693 }
694
695 #[test]
696 fn test_encode_replace() {
697 let mut buf = [0u8; 64];
698 let len = Request::replace(b"mykey", b"myvalue").encode(&mut buf);
699 assert_eq!(&buf[..len], b"replace mykey 0 0 7\r\nmyvalue\r\n");
700 }
701
702 #[test]
703 fn test_encode_replace_with_options() {
704 let mut buf = [0u8; 64];
705 let len = Request::replace(b"mykey", b"myvalue")
706 .flags(99)
707 .exptime(300)
708 .encode(&mut buf);
709 assert_eq!(&buf[..len], b"replace mykey 99 300 7\r\nmyvalue\r\n");
710 }
711
712 #[test]
713 fn test_replace_request_build() {
714 let mut buf = [0u8; 64];
715 let request = Request::replace(b"mykey", b"myvalue")
716 .flags(42)
717 .exptime(600)
718 .build();
719 let len = request.encode(&mut buf);
720 assert_eq!(&buf[..len], b"replace mykey 42 600 7\r\nmyvalue\r\n");
721 }
722
723 #[test]
724 fn test_encode_replace_via_request() {
725 let mut buf = [0u8; 64];
726 let request = Request::Replace {
727 key: b"k",
728 value: b"v",
729 flags: 0,
730 exptime: 0,
731 };
732 let len = request.encode(&mut buf);
733 assert_eq!(&buf[..len], b"replace k 0 0 1\r\nv\r\n");
734 }
735
736 #[test]
737 fn test_encode_incr() {
738 let mut buf = [0u8; 64];
739 let len = Request::incr(b"counter", 1).encode(&mut buf);
740 assert_eq!(&buf[..len], b"incr counter 1\r\n");
741 }
742
743 #[test]
744 fn test_encode_incr_large_delta() {
745 let mut buf = [0u8; 64];
746 let len = Request::incr(b"counter", 12345).encode(&mut buf);
747 assert_eq!(&buf[..len], b"incr counter 12345\r\n");
748 }
749
750 #[test]
751 fn test_encode_decr() {
752 let mut buf = [0u8; 64];
753 let len = Request::decr(b"counter", 5).encode(&mut buf);
754 assert_eq!(&buf[..len], b"decr counter 5\r\n");
755 }
756
757 #[test]
758 fn test_encode_decr_large_delta() {
759 let mut buf = [0u8; 64];
760 let len = Request::decr(b"counter", 99999).encode(&mut buf);
761 assert_eq!(&buf[..len], b"decr counter 99999\r\n");
762 }
763
764 #[test]
765 fn test_encode_append() {
766 let mut buf = [0u8; 64];
767 let len = Request::append(b"mykey", b"extra").encode(&mut buf);
768 assert_eq!(&buf[..len], b"append mykey 0 0 5\r\nextra\r\n");
769 }
770
771 #[test]
772 fn test_encode_prepend() {
773 let mut buf = [0u8; 64];
774 let len = Request::prepend(b"mykey", b"prefix").encode(&mut buf);
775 assert_eq!(&buf[..len], b"prepend mykey 0 0 6\r\nprefix\r\n");
776 }
777
778 #[test]
779 fn test_encode_cas() {
780 let mut buf = [0u8; 128];
781 let len = Request::cas(b"mykey", b"myvalue", 12345).encode(&mut buf);
782 assert_eq!(&buf[..len], b"cas mykey 0 0 7 12345\r\nmyvalue\r\n");
783 }
784
785 #[test]
786 fn test_encode_cas_via_request() {
787 let mut buf = [0u8; 128];
788 let request = Request::Cas {
789 key: b"k",
790 value: b"v",
791 flags: 42,
792 exptime: 600,
793 cas_unique: 99,
794 };
795 let len = request.encode(&mut buf);
796 assert_eq!(&buf[..len], b"cas k 42 600 1 99\r\nv\r\n");
797 }
798}