1use crate::error::ParseError;
6
7pub const DEFAULT_MAX_KEY_LEN: usize = 250;
9
10pub const DEFAULT_MAX_VALUE_LEN: usize = 1024 * 1024;
12
13pub const DEFAULT_MAX_KEYS: usize = 1024;
15
16#[derive(Debug, Clone, Copy)]
22pub struct ParseOptions {
23 pub max_key_len: usize,
25 pub max_value_len: usize,
27 pub max_keys: usize,
29}
30
31impl Default for ParseOptions {
32 fn default() -> Self {
33 Self {
34 max_key_len: DEFAULT_MAX_KEY_LEN,
35 max_value_len: DEFAULT_MAX_VALUE_LEN,
36 max_keys: DEFAULT_MAX_KEYS,
37 }
38 }
39}
40
41impl ParseOptions {
42 pub const fn new() -> Self {
44 Self {
45 max_key_len: DEFAULT_MAX_KEY_LEN,
46 max_value_len: DEFAULT_MAX_VALUE_LEN,
47 max_keys: DEFAULT_MAX_KEYS,
48 }
49 }
50
51 pub const fn max_key_len(mut self, len: usize) -> Self {
53 self.max_key_len = len;
54 self
55 }
56
57 pub const fn max_value_len(mut self, len: usize) -> Self {
59 self.max_value_len = len;
60 self
61 }
62
63 pub const fn max_keys(mut self, count: usize) -> Self {
65 self.max_keys = count;
66 self
67 }
68
69 pub const fn max_line_len(&self) -> usize {
74 4 + (self.max_key_len + 1) * self.max_keys
76 }
77}
78
79#[derive(Debug, Clone, PartialEq, Eq)]
83pub enum Command<'a> {
84 Get { key: &'a [u8] },
86 Gets { keys: Vec<&'a [u8]> },
88 Set {
90 key: &'a [u8],
91 flags: u32,
92 exptime: u32,
93 data: &'a [u8],
94 },
95 Add {
97 key: &'a [u8],
98 flags: u32,
99 exptime: u32,
100 data: &'a [u8],
101 },
102 Replace {
104 key: &'a [u8],
105 flags: u32,
106 exptime: u32,
107 data: &'a [u8],
108 },
109 Cas {
111 key: &'a [u8],
112 flags: u32,
113 exptime: u32,
114 data: &'a [u8],
115 cas_unique: u64,
116 },
117 Delete { key: &'a [u8] },
119 FlushAll,
121 Version,
123 Quit,
125 Incr {
127 key: &'a [u8],
128 delta: u64,
129 noreply: bool,
130 },
131 Decr {
133 key: &'a [u8],
134 delta: u64,
135 noreply: bool,
136 },
137 Append {
139 key: &'a [u8],
140 data: &'a [u8],
141 noreply: bool,
142 },
143 Prepend {
145 key: &'a [u8],
146 data: &'a [u8],
147 noreply: bool,
148 },
149}
150
151impl<'a> Command<'a> {
152 #[inline]
161 pub fn parse(buffer: &'a [u8]) -> Result<(Self, usize), ParseError> {
162 Self::parse_with_options(buffer, &ParseOptions::default())
163 }
164
165 pub fn parse_with_options(
170 buffer: &'a [u8],
171 options: &ParseOptions,
172 ) -> Result<(Self, usize), ParseError> {
173 let max_line_len = options.max_line_len();
175 let line_end = find_crlf(buffer, max_line_len)?.ok_or(ParseError::Incomplete)?;
176 let line = &buffer[..line_end];
177 let mut parts = line.split(|&b| b == b' ');
178
179 let cmd = parts.next().ok_or(ParseError::Protocol("empty command"))?;
180
181 match cmd {
182 b"get" | b"GET" => {
183 let keys: Vec<&[u8]> = parts.filter(|k| !k.is_empty()).collect();
185 if keys.is_empty() {
186 return Err(ParseError::Protocol("get requires key"));
187 }
188 if keys.len() > options.max_keys {
189 return Err(ParseError::Protocol("too many keys"));
190 }
191 if keys.len() == 1 {
192 Ok((Command::Get { key: keys[0] }, line_end + 2))
193 } else {
194 Ok((Command::Gets { keys }, line_end + 2))
195 }
196 }
197
198 b"gets" | b"GETS" => {
199 let keys: Vec<&[u8]> = parts.filter(|k| !k.is_empty()).collect();
201 if keys.is_empty() {
202 return Err(ParseError::Protocol("gets requires key"));
203 }
204 if keys.len() > options.max_keys {
205 return Err(ParseError::Protocol("too many keys"));
206 }
207 Ok((Command::Gets { keys }, line_end + 2))
208 }
209
210 b"set" | b"SET" => {
211 let key = parts
212 .next()
213 .ok_or(ParseError::Protocol("set requires key"))?;
214 if key.is_empty() {
215 return Err(ParseError::Protocol("empty key"));
216 }
217 if key.len() > options.max_key_len {
218 return Err(ParseError::Protocol("key too large"));
219 }
220 let flags_str = parts
221 .next()
222 .ok_or(ParseError::Protocol("set requires flags"))?;
223 let exptime_str = parts
224 .next()
225 .ok_or(ParseError::Protocol("set requires exptime"))?;
226 let bytes_str = parts
227 .next()
228 .ok_or(ParseError::Protocol("set requires bytes"))?;
229
230 let flags = parse_u32(flags_str)?;
231 let exptime = parse_u32(exptime_str)?;
232 let data_len = parse_usize(bytes_str)?;
233 if data_len > options.max_value_len {
234 return Err(ParseError::Protocol("value too large"));
235 }
236
237 let data_start = line_end + 2;
239 let data_end = data_start
240 .checked_add(data_len)
241 .ok_or(ParseError::InvalidNumber)?;
242 let total_len = data_end.checked_add(2).ok_or(ParseError::InvalidNumber)?;
243
244 if buffer.len() < total_len {
245 return Err(ParseError::Incomplete);
246 }
247
248 if buffer[data_end] != b'\r' || buffer[data_end + 1] != b'\n' {
250 return Err(ParseError::Protocol("missing data terminator"));
251 }
252
253 let data = &buffer[data_start..data_end];
254 Ok((
255 Command::Set {
256 key,
257 flags,
258 exptime,
259 data,
260 },
261 total_len,
262 ))
263 }
264
265 b"add" | b"ADD" => {
266 let key = parts
267 .next()
268 .ok_or(ParseError::Protocol("add requires key"))?;
269 if key.is_empty() {
270 return Err(ParseError::Protocol("empty key"));
271 }
272 if key.len() > options.max_key_len {
273 return Err(ParseError::Protocol("key too large"));
274 }
275 let flags_str = parts
276 .next()
277 .ok_or(ParseError::Protocol("add requires flags"))?;
278 let exptime_str = parts
279 .next()
280 .ok_or(ParseError::Protocol("add requires exptime"))?;
281 let bytes_str = parts
282 .next()
283 .ok_or(ParseError::Protocol("add requires bytes"))?;
284
285 let flags = parse_u32(flags_str)?;
286 let exptime = parse_u32(exptime_str)?;
287 let data_len = parse_usize(bytes_str)?;
288 if data_len > options.max_value_len {
289 return Err(ParseError::Protocol("value too large"));
290 }
291
292 let data_start = line_end + 2;
294 let data_end = data_start
295 .checked_add(data_len)
296 .ok_or(ParseError::InvalidNumber)?;
297 let total_len = data_end.checked_add(2).ok_or(ParseError::InvalidNumber)?;
298
299 if buffer.len() < total_len {
300 return Err(ParseError::Incomplete);
301 }
302
303 if buffer[data_end] != b'\r' || buffer[data_end + 1] != b'\n' {
305 return Err(ParseError::Protocol("missing data terminator"));
306 }
307
308 let data = &buffer[data_start..data_end];
309 Ok((
310 Command::Add {
311 key,
312 flags,
313 exptime,
314 data,
315 },
316 total_len,
317 ))
318 }
319
320 b"replace" | b"REPLACE" => {
321 let key = parts
322 .next()
323 .ok_or(ParseError::Protocol("replace requires key"))?;
324 if key.is_empty() {
325 return Err(ParseError::Protocol("empty key"));
326 }
327 if key.len() > options.max_key_len {
328 return Err(ParseError::Protocol("key too large"));
329 }
330 let flags_str = parts
331 .next()
332 .ok_or(ParseError::Protocol("replace requires flags"))?;
333 let exptime_str = parts
334 .next()
335 .ok_or(ParseError::Protocol("replace requires exptime"))?;
336 let bytes_str = parts
337 .next()
338 .ok_or(ParseError::Protocol("replace requires bytes"))?;
339
340 let flags = parse_u32(flags_str)?;
341 let exptime = parse_u32(exptime_str)?;
342 let data_len = parse_usize(bytes_str)?;
343 if data_len > options.max_value_len {
344 return Err(ParseError::Protocol("value too large"));
345 }
346
347 let data_start = line_end + 2;
349 let data_end = data_start
350 .checked_add(data_len)
351 .ok_or(ParseError::InvalidNumber)?;
352 let total_len = data_end.checked_add(2).ok_or(ParseError::InvalidNumber)?;
353
354 if buffer.len() < total_len {
355 return Err(ParseError::Incomplete);
356 }
357
358 if buffer[data_end] != b'\r' || buffer[data_end + 1] != b'\n' {
360 return Err(ParseError::Protocol("missing data terminator"));
361 }
362
363 let data = &buffer[data_start..data_end];
364 Ok((
365 Command::Replace {
366 key,
367 flags,
368 exptime,
369 data,
370 },
371 total_len,
372 ))
373 }
374
375 b"cas" | b"CAS" => {
376 let key = parts
377 .next()
378 .ok_or(ParseError::Protocol("cas requires key"))?;
379 if key.is_empty() {
380 return Err(ParseError::Protocol("empty key"));
381 }
382 if key.len() > options.max_key_len {
383 return Err(ParseError::Protocol("key too large"));
384 }
385 let flags_str = parts
386 .next()
387 .ok_or(ParseError::Protocol("cas requires flags"))?;
388 let exptime_str = parts
389 .next()
390 .ok_or(ParseError::Protocol("cas requires exptime"))?;
391 let bytes_str = parts
392 .next()
393 .ok_or(ParseError::Protocol("cas requires bytes"))?;
394 let cas_str = parts
395 .next()
396 .ok_or(ParseError::Protocol("cas requires cas_unique"))?;
397
398 let flags = parse_u32(flags_str)?;
399 let exptime = parse_u32(exptime_str)?;
400 let data_len = parse_usize(bytes_str)?;
401 let cas_unique = parse_u64(cas_str)?;
402 if data_len > options.max_value_len {
403 return Err(ParseError::Protocol("value too large"));
404 }
405
406 let data_start = line_end + 2;
408 let data_end = data_start
409 .checked_add(data_len)
410 .ok_or(ParseError::InvalidNumber)?;
411 let total_len = data_end.checked_add(2).ok_or(ParseError::InvalidNumber)?;
412
413 if buffer.len() < total_len {
414 return Err(ParseError::Incomplete);
415 }
416
417 if buffer[data_end] != b'\r' || buffer[data_end + 1] != b'\n' {
419 return Err(ParseError::Protocol("missing data terminator"));
420 }
421
422 let data = &buffer[data_start..data_end];
423 Ok((
424 Command::Cas {
425 key,
426 flags,
427 exptime,
428 data,
429 cas_unique,
430 },
431 total_len,
432 ))
433 }
434
435 b"delete" | b"DELETE" => {
436 let key = parts
437 .next()
438 .ok_or(ParseError::Protocol("delete requires key"))?;
439 if key.is_empty() {
440 return Err(ParseError::Protocol("empty key"));
441 }
442 Ok((Command::Delete { key }, line_end + 2))
443 }
444
445 b"flush_all" | b"FLUSH_ALL" => Ok((Command::FlushAll, line_end + 2)),
446
447 b"version" | b"VERSION" => Ok((Command::Version, line_end + 2)),
448
449 b"quit" | b"QUIT" => Ok((Command::Quit, line_end + 2)),
450
451 b"incr" | b"INCR" => {
452 let key = parts
453 .next()
454 .ok_or(ParseError::Protocol("incr requires key"))?;
455 if key.is_empty() {
456 return Err(ParseError::Protocol("empty key"));
457 }
458 if key.len() > options.max_key_len {
459 return Err(ParseError::Protocol("key too large"));
460 }
461 let delta_str = parts
462 .next()
463 .ok_or(ParseError::Protocol("incr requires delta"))?;
464 let delta = parse_u64(delta_str)?;
465 let noreply = parts
466 .next()
467 .map(|s| s == b"noreply" || s == b"NOREPLY")
468 .unwrap_or(false);
469 Ok((
470 Command::Incr {
471 key,
472 delta,
473 noreply,
474 },
475 line_end + 2,
476 ))
477 }
478
479 b"decr" | b"DECR" => {
480 let key = parts
481 .next()
482 .ok_or(ParseError::Protocol("decr requires key"))?;
483 if key.is_empty() {
484 return Err(ParseError::Protocol("empty key"));
485 }
486 if key.len() > options.max_key_len {
487 return Err(ParseError::Protocol("key too large"));
488 }
489 let delta_str = parts
490 .next()
491 .ok_or(ParseError::Protocol("decr requires delta"))?;
492 let delta = parse_u64(delta_str)?;
493 let noreply = parts
494 .next()
495 .map(|s| s == b"noreply" || s == b"NOREPLY")
496 .unwrap_or(false);
497 Ok((
498 Command::Decr {
499 key,
500 delta,
501 noreply,
502 },
503 line_end + 2,
504 ))
505 }
506
507 b"append" | b"APPEND" => {
508 let key = parts
509 .next()
510 .ok_or(ParseError::Protocol("append requires key"))?;
511 if key.is_empty() {
512 return Err(ParseError::Protocol("empty key"));
513 }
514 if key.len() > options.max_key_len {
515 return Err(ParseError::Protocol("key too large"));
516 }
517 let _flags_str = parts
519 .next()
520 .ok_or(ParseError::Protocol("append requires flags"))?;
521 let _exptime_str = parts
522 .next()
523 .ok_or(ParseError::Protocol("append requires exptime"))?;
524 let bytes_str = parts
525 .next()
526 .ok_or(ParseError::Protocol("append requires bytes"))?;
527
528 let data_len = parse_usize(bytes_str)?;
529 if data_len > options.max_value_len {
530 return Err(ParseError::Protocol("value too large"));
531 }
532
533 let noreply = parts
535 .next()
536 .map(|s| s == b"noreply" || s == b"NOREPLY")
537 .unwrap_or(false);
538
539 let data_start = line_end + 2;
541 let data_end = data_start
542 .checked_add(data_len)
543 .ok_or(ParseError::InvalidNumber)?;
544 let total_len = data_end.checked_add(2).ok_or(ParseError::InvalidNumber)?;
545
546 if buffer.len() < total_len {
547 return Err(ParseError::Incomplete);
548 }
549
550 if buffer[data_end] != b'\r' || buffer[data_end + 1] != b'\n' {
552 return Err(ParseError::Protocol("missing data terminator"));
553 }
554
555 let data = &buffer[data_start..data_end];
556 Ok((Command::Append { key, data, noreply }, total_len))
557 }
558
559 b"prepend" | b"PREPEND" => {
560 let key = parts
561 .next()
562 .ok_or(ParseError::Protocol("prepend requires key"))?;
563 if key.is_empty() {
564 return Err(ParseError::Protocol("empty key"));
565 }
566 if key.len() > options.max_key_len {
567 return Err(ParseError::Protocol("key too large"));
568 }
569 let _flags_str = parts
571 .next()
572 .ok_or(ParseError::Protocol("prepend requires flags"))?;
573 let _exptime_str = parts
574 .next()
575 .ok_or(ParseError::Protocol("prepend requires exptime"))?;
576 let bytes_str = parts
577 .next()
578 .ok_or(ParseError::Protocol("prepend requires bytes"))?;
579
580 let data_len = parse_usize(bytes_str)?;
581 if data_len > options.max_value_len {
582 return Err(ParseError::Protocol("value too large"));
583 }
584
585 let noreply = parts
587 .next()
588 .map(|s| s == b"noreply" || s == b"NOREPLY")
589 .unwrap_or(false);
590
591 let data_start = line_end + 2;
593 let data_end = data_start
594 .checked_add(data_len)
595 .ok_or(ParseError::InvalidNumber)?;
596 let total_len = data_end.checked_add(2).ok_or(ParseError::InvalidNumber)?;
597
598 if buffer.len() < total_len {
599 return Err(ParseError::Incomplete);
600 }
601
602 if buffer[data_end] != b'\r' || buffer[data_end + 1] != b'\n' {
604 return Err(ParseError::Protocol("missing data terminator"));
605 }
606
607 let data = &buffer[data_start..data_end];
608 Ok((Command::Prepend { key, data, noreply }, total_len))
609 }
610
611 _ => Err(ParseError::UnknownCommand),
612 }
613 }
614
615 pub fn name(&self) -> &'static str {
617 match self {
618 Command::Get { .. } => "GET",
619 Command::Gets { .. } => "GETS",
620 Command::Set { .. } => "SET",
621 Command::Add { .. } => "ADD",
622 Command::Replace { .. } => "REPLACE",
623 Command::Cas { .. } => "CAS",
624 Command::Delete { .. } => "DELETE",
625 Command::FlushAll => "FLUSH_ALL",
626 Command::Version => "VERSION",
627 Command::Quit => "QUIT",
628 Command::Incr { .. } => "INCR",
629 Command::Decr { .. } => "DECR",
630 Command::Append { .. } => "APPEND",
631 Command::Prepend { .. } => "PREPEND",
632 }
633 }
634
635 pub fn is_quit(&self) -> bool {
637 matches!(self, Command::Quit)
638 }
639}
640
641fn find_crlf(buffer: &[u8], max_line_len: usize) -> Result<Option<usize>, ParseError> {
648 if let Some(pos) = memchr::memchr(b'\r', buffer)
649 .filter(|&pos| pos + 1 < buffer.len() && buffer[pos + 1] == b'\n')
650 {
651 return Ok(Some(pos));
652 }
653
654 if buffer.len() > max_line_len {
656 return Err(ParseError::Protocol("line too long"));
657 }
658
659 Ok(None)
660}
661
662fn parse_u32(data: &[u8]) -> Result<u32, ParseError> {
664 std::str::from_utf8(data)
665 .map_err(|_| ParseError::InvalidNumber)?
666 .parse()
667 .map_err(|_| ParseError::InvalidNumber)
668}
669
670fn parse_u64(data: &[u8]) -> Result<u64, ParseError> {
672 std::str::from_utf8(data)
673 .map_err(|_| ParseError::InvalidNumber)?
674 .parse()
675 .map_err(|_| ParseError::InvalidNumber)
676}
677
678fn parse_usize(data: &[u8]) -> Result<usize, ParseError> {
680 std::str::from_utf8(data)
681 .map_err(|_| ParseError::InvalidNumber)?
682 .parse()
683 .map_err(|_| ParseError::InvalidNumber)
684}
685
686#[cfg(test)]
687mod tests {
688 use super::*;
689
690 #[test]
691 fn test_parse_get() {
692 let data = b"get mykey\r\n";
693 let (cmd, consumed) = Command::parse(data).unwrap();
694 assert_eq!(cmd, Command::Get { key: b"mykey" });
695 assert_eq!(consumed, data.len());
696 }
697
698 #[test]
699 fn test_parse_gets() {
700 let data = b"get key1 key2 key3\r\n";
701 let (cmd, consumed) = Command::parse(data).unwrap();
702 match cmd {
703 Command::Gets { keys } => {
704 assert_eq!(keys.len(), 3);
705 assert_eq!(keys[0], b"key1");
706 assert_eq!(keys[1], b"key2");
707 assert_eq!(keys[2], b"key3");
708 }
709 _ => panic!("expected Gets"),
710 }
711 assert_eq!(consumed, data.len());
712 }
713
714 #[test]
715 fn test_parse_set() {
716 let data = b"set mykey 0 3600 7\r\nmyvalue\r\n";
717 let (cmd, consumed) = Command::parse(data).unwrap();
718 match cmd {
719 Command::Set {
720 key,
721 flags,
722 exptime,
723 data: value,
724 } => {
725 assert_eq!(key, b"mykey");
726 assert_eq!(flags, 0);
727 assert_eq!(exptime, 3600);
728 assert_eq!(value, b"myvalue");
729 }
730 _ => panic!("expected Set"),
731 }
732 assert_eq!(consumed, data.len());
733 }
734
735 #[test]
736 fn test_parse_delete() {
737 let data = b"delete mykey\r\n";
738 let (cmd, consumed) = Command::parse(data).unwrap();
739 assert_eq!(cmd, Command::Delete { key: b"mykey" });
740 assert_eq!(consumed, data.len());
741 }
742
743 #[test]
744 fn test_parse_flush_all() {
745 let data = b"flush_all\r\n";
746 let (cmd, consumed) = Command::parse(data).unwrap();
747 assert_eq!(cmd, Command::FlushAll);
748 assert_eq!(consumed, data.len());
749 }
750
751 #[test]
752 fn test_parse_version() {
753 let data = b"version\r\n";
754 let (cmd, consumed) = Command::parse(data).unwrap();
755 assert_eq!(cmd, Command::Version);
756 assert_eq!(consumed, data.len());
757 }
758
759 #[test]
760 fn test_parse_quit() {
761 let data = b"quit\r\n";
762 let (cmd, consumed) = Command::parse(data).unwrap();
763 assert_eq!(cmd, Command::Quit);
764 assert!(cmd.is_quit());
765 assert_eq!(consumed, data.len());
766 }
767
768 #[test]
769 fn test_parse_case_insensitive() {
770 let (cmd, _) = Command::parse(b"GET mykey\r\n").unwrap();
771 assert_eq!(cmd, Command::Get { key: b"mykey" });
772
773 let (cmd, _) = Command::parse(b"SET k 0 0 1\r\nv\r\n").unwrap();
774 assert!(matches!(cmd, Command::Set { .. }));
775 }
776
777 #[test]
778 fn test_parse_incomplete() {
779 assert!(matches!(
780 Command::parse(b"set mykey 0 0 7\r\nmyval"),
781 Err(ParseError::Incomplete)
782 ));
783 assert!(matches!(
784 Command::parse(b"get mykey"),
785 Err(ParseError::Incomplete)
786 ));
787 }
788
789 #[test]
790 fn test_parse_unknown() {
791 assert!(matches!(
792 Command::parse(b"unknown\r\n"),
793 Err(ParseError::UnknownCommand)
794 ));
795 }
796
797 #[test]
798 fn test_command_name() {
799 assert_eq!(Command::Get { key: b"k" }.name(), "GET");
800 assert_eq!(
801 Command::Set {
802 key: b"k",
803 flags: 0,
804 exptime: 0,
805 data: b"v"
806 }
807 .name(),
808 "SET"
809 );
810 assert_eq!(Command::FlushAll.name(), "FLUSH_ALL");
811 }
812
813 #[test]
816 fn test_command_name_all() {
817 assert_eq!(Command::Gets { keys: vec![b"k"] }.name(), "GETS");
818 assert_eq!(Command::Delete { key: b"k" }.name(), "DELETE");
819 assert_eq!(Command::Version.name(), "VERSION");
820 assert_eq!(Command::Quit.name(), "QUIT");
821 }
822
823 #[test]
824 fn test_parse_get_no_key() {
825 assert!(matches!(
826 Command::parse(b"get\r\n"),
827 Err(ParseError::Protocol("get requires key"))
828 ));
829 }
830
831 #[test]
832 fn test_parse_get_empty_key() {
833 assert!(matches!(
835 Command::parse(b"get \r\n"),
836 Err(ParseError::Protocol("get requires key"))
837 ));
838 }
839
840 #[test]
841 fn test_parse_set_missing_key() {
842 assert!(matches!(
843 Command::parse(b"set\r\n"),
844 Err(ParseError::Protocol("set requires key"))
845 ));
846 }
847
848 #[test]
849 fn test_parse_set_missing_flags() {
850 assert!(matches!(
851 Command::parse(b"set mykey\r\n"),
852 Err(ParseError::Protocol("set requires flags"))
853 ));
854 }
855
856 #[test]
857 fn test_parse_set_missing_exptime() {
858 assert!(matches!(
859 Command::parse(b"set mykey 0\r\n"),
860 Err(ParseError::Protocol("set requires exptime"))
861 ));
862 }
863
864 #[test]
865 fn test_parse_set_missing_bytes() {
866 assert!(matches!(
867 Command::parse(b"set mykey 0 0\r\n"),
868 Err(ParseError::Protocol("set requires bytes"))
869 ));
870 }
871
872 #[test]
873 fn test_parse_set_invalid_flags() {
874 assert!(matches!(
875 Command::parse(b"set mykey abc 0 5\r\nhello\r\n"),
876 Err(ParseError::InvalidNumber)
877 ));
878 }
879
880 #[test]
881 fn test_parse_set_invalid_exptime() {
882 assert!(matches!(
883 Command::parse(b"set mykey 0 xyz 5\r\nhello\r\n"),
884 Err(ParseError::InvalidNumber)
885 ));
886 }
887
888 #[test]
889 fn test_parse_set_invalid_bytes() {
890 assert!(matches!(
891 Command::parse(b"set mykey 0 0 abc\r\nhello\r\n"),
892 Err(ParseError::InvalidNumber)
893 ));
894 }
895
896 #[test]
897 fn test_parse_set_missing_terminator() {
898 assert!(matches!(
900 Command::parse(b"set mykey 0 0 5\r\nhelloXX"),
901 Err(ParseError::Protocol("missing data terminator"))
902 ));
903 }
904
905 #[test]
906 fn test_parse_delete_missing_key() {
907 assert!(matches!(
908 Command::parse(b"delete\r\n"),
909 Err(ParseError::Protocol("delete requires key"))
910 ));
911 }
912
913 #[test]
914 fn test_parse_delete_empty_key() {
915 assert!(matches!(
919 Command::parse(b"delete \r\n"),
920 Err(ParseError::Protocol("empty key"))
921 ));
922 }
923
924 #[test]
925 fn test_parse_case_insensitive_delete() {
926 let (cmd, _) = Command::parse(b"DELETE mykey\r\n").unwrap();
927 assert_eq!(cmd, Command::Delete { key: b"mykey" });
928 }
929
930 #[test]
931 fn test_parse_case_insensitive_flush_all() {
932 let (cmd, _) = Command::parse(b"FLUSH_ALL\r\n").unwrap();
933 assert_eq!(cmd, Command::FlushAll);
934 }
935
936 #[test]
937 fn test_parse_case_insensitive_version() {
938 let (cmd, _) = Command::parse(b"VERSION\r\n").unwrap();
939 assert_eq!(cmd, Command::Version);
940 }
941
942 #[test]
943 fn test_parse_case_insensitive_quit() {
944 let (cmd, _) = Command::parse(b"QUIT\r\n").unwrap();
945 assert_eq!(cmd, Command::Quit);
946 }
947
948 #[test]
949 fn test_is_quit_false() {
950 assert!(!Command::Get { key: b"k" }.is_quit());
951 assert!(
952 !Command::Set {
953 key: b"k",
954 flags: 0,
955 exptime: 0,
956 data: b"v"
957 }
958 .is_quit()
959 );
960 assert!(!Command::Delete { key: b"k" }.is_quit());
961 assert!(!Command::FlushAll.is_quit());
962 assert!(!Command::Version.is_quit());
963 }
964
965 #[test]
966 fn test_command_debug() {
967 let cmd = Command::Get { key: b"test" };
968 let debug_str = format!("{:?}", cmd);
969 assert!(debug_str.contains("Get"));
970 }
971
972 #[test]
973 fn test_command_clone() {
974 let cmd1 = Command::Get { key: b"test" };
975 let cmd2 = cmd1.clone();
976 assert_eq!(cmd1, cmd2);
977 }
978
979 #[test]
980 fn test_command_eq() {
981 assert_eq!(Command::FlushAll, Command::FlushAll);
982 assert_ne!(Command::FlushAll, Command::Version);
983 assert_eq!(Command::Get { key: b"k" }, Command::Get { key: b"k" });
984 assert_ne!(Command::Get { key: b"k1" }, Command::Get { key: b"k2" });
985 }
986
987 #[test]
988 fn test_parse_set_data_with_zeros() {
989 let data = b"set mykey 0 0 5\r\n\x00\x01\x02\x03\x04\r\n";
991 let (cmd, consumed) = Command::parse(data).unwrap();
992 match cmd {
993 Command::Set { data: value, .. } => {
994 assert_eq!(value, b"\x00\x01\x02\x03\x04");
995 }
996 _ => panic!("expected Set"),
997 }
998 assert_eq!(consumed, data.len());
999 }
1000
1001 #[test]
1002 fn test_find_crlf_edge_case() {
1003 assert!(matches!(
1005 Command::parse(b"get mykey\r"),
1006 Err(ParseError::Incomplete)
1007 ));
1008 }
1009
1010 #[test]
1011 fn test_parse_set_overflow_bytes() {
1012 assert!(matches!(
1015 Command::parse(b"SET k 0 0 18446744073709551615\r\n"),
1016 Err(ParseError::Protocol("value too large"))
1017 ));
1018
1019 assert!(matches!(
1021 Command::parse(b"set k 0 0 abc\r\nhello\r\n"),
1022 Err(ParseError::InvalidNumber)
1023 ));
1024 }
1025
1026 #[test]
1027 fn test_parse_set_empty_key() {
1028 assert!(matches!(
1030 Command::parse(b"SET 0 0 5\r\nhello\r\n"),
1031 Err(ParseError::Protocol("empty key"))
1032 ));
1033 }
1034
1035 #[test]
1036 fn test_parse_line_too_long() {
1037 let max_line_len = ParseOptions::default().max_line_len();
1039
1040 let mut data = vec![b'g', b'e', b't', b' '];
1042 data.extend(std::iter::repeat_n(b'a', max_line_len + 1));
1043 assert!(matches!(
1045 Command::parse(&data),
1046 Err(ParseError::Protocol("line too long"))
1047 ));
1048 }
1049
1050 #[test]
1051 fn test_parse_key_too_large() {
1052 let mut data = b"set ".to_vec();
1054 data.extend(std::iter::repeat_n(b'a', DEFAULT_MAX_KEY_LEN + 1));
1055 data.extend(b" 0 0 5\r\nhello\r\n");
1056 assert!(matches!(
1057 Command::parse(&data),
1058 Err(ParseError::Protocol("key too large"))
1059 ));
1060 }
1061
1062 #[test]
1063 fn test_parse_value_too_large() {
1064 let cmd = format!("set k 0 0 {}\r\n", DEFAULT_MAX_VALUE_LEN + 1);
1066 let mut data = cmd.as_bytes().to_vec();
1067 data.extend(std::iter::repeat_n(b'x', DEFAULT_MAX_VALUE_LEN + 1));
1069 data.extend(b"\r\n");
1070 assert!(matches!(
1071 Command::parse(&data),
1072 Err(ParseError::Protocol("value too large"))
1073 ));
1074 }
1075
1076 #[test]
1081 fn test_line_length_at_exact_limit() {
1082 let max_line_len = ParseOptions::default().max_line_len();
1083 let mut data = b"get ".to_vec();
1085 let remaining = max_line_len - data.len();
1087 data.extend(std::iter::repeat_n(b'a', remaining));
1088 assert_eq!(data.len(), max_line_len);
1089 assert!(matches!(Command::parse(&data), Err(ParseError::Incomplete)));
1090 }
1091
1092 #[test]
1093 fn test_line_length_one_over_limit() {
1094 let max_line_len = ParseOptions::default().max_line_len();
1095 let mut data = b"get ".to_vec();
1097 let remaining = max_line_len + 1 - data.len();
1098 data.extend(std::iter::repeat_n(b'a', remaining));
1099 assert_eq!(data.len(), max_line_len + 1);
1100 assert!(matches!(
1101 Command::parse(&data),
1102 Err(ParseError::Protocol("line too long"))
1103 ));
1104 }
1105
1106 #[test]
1107 fn test_long_line_with_crlf_within_limit() {
1108 let mut data = b"get ".to_vec();
1111 for i in 0..10 {
1113 data.extend(format!("key{} ", i).as_bytes());
1114 }
1115 data.extend(b"\r\n");
1116 let result = Command::parse(&data);
1117 assert!(result.is_ok());
1118 }
1119
1120 #[test]
1121 fn test_key_length_at_exact_limit() {
1122 let mut data = b"set ".to_vec();
1124 data.extend(std::iter::repeat_n(b'k', DEFAULT_MAX_KEY_LEN));
1125 data.extend(b" 0 0 1\r\nv\r\n");
1126 let result = Command::parse(&data);
1127 assert!(result.is_ok());
1128 if let Ok((Command::Set { key, .. }, _)) = result {
1129 assert_eq!(key.len(), DEFAULT_MAX_KEY_LEN);
1130 }
1131 }
1132
1133 #[test]
1134 fn test_key_length_one_over_limit() {
1135 let mut data = b"set ".to_vec();
1137 data.extend(std::iter::repeat_n(b'k', DEFAULT_MAX_KEY_LEN + 1));
1138 data.extend(b" 0 0 1\r\nv\r\n");
1139 assert!(matches!(
1140 Command::parse(&data),
1141 Err(ParseError::Protocol("key too large"))
1142 ));
1143 }
1144
1145 #[test]
1146 fn test_value_length_at_exact_limit() {
1147 let cmd = format!("set k 0 0 {}\r\n", DEFAULT_MAX_VALUE_LEN);
1149 let mut data = cmd.as_bytes().to_vec();
1150 data.extend(std::iter::repeat_n(b'v', DEFAULT_MAX_VALUE_LEN));
1151 data.extend(b"\r\n");
1152 let result = Command::parse(&data);
1153 assert!(result.is_ok());
1154 if let Ok((Command::Set { data: value, .. }, _)) = result {
1155 assert_eq!(value.len(), DEFAULT_MAX_VALUE_LEN);
1156 }
1157 }
1158
1159 #[test]
1160 fn test_value_length_one_over_limit() {
1161 let cmd = format!("set k 0 0 {}\r\n", DEFAULT_MAX_VALUE_LEN + 1);
1163 let mut data = cmd.as_bytes().to_vec();
1164 data.extend(std::iter::repeat_n(b'v', DEFAULT_MAX_VALUE_LEN + 1));
1165 data.extend(b"\r\n");
1166 assert!(matches!(
1167 Command::parse(&data),
1168 Err(ParseError::Protocol("value too large"))
1169 ));
1170 }
1171
1172 #[test]
1173 fn test_multiget_many_keys() {
1174 let mut data = b"get".to_vec();
1176 for i in 0..100 {
1177 data.extend(format!(" key{}", i).as_bytes());
1178 }
1179 data.extend(b"\r\n");
1180
1181 let result = Command::parse(&data);
1182 assert!(result.is_ok());
1183 if let Ok((Command::Gets { keys }, _)) = result {
1184 assert_eq!(keys.len(), 100);
1185 }
1186 }
1187
1188 #[test]
1189 fn test_arithmetic_overflow_protection() {
1190 let cmd = format!("set k 0 0 {}\r\n", usize::MAX);
1197 let data = cmd.as_bytes();
1198 let result = Command::parse(data);
1199 assert!(result.is_err());
1201 }
1202
1203 #[test]
1204 fn test_empty_buffer() {
1205 assert!(matches!(Command::parse(b""), Err(ParseError::Incomplete)));
1206 }
1207
1208 #[test]
1209 fn test_only_whitespace_no_crlf() {
1210 let data = b" ";
1211 assert!(matches!(Command::parse(data), Err(ParseError::Incomplete)));
1212 }
1213
1214 #[test]
1215 fn test_cr_without_lf() {
1216 let data = b"get key\r";
1217 assert!(matches!(Command::parse(data), Err(ParseError::Incomplete)));
1218 }
1219
1220 #[test]
1221 fn test_cr_without_lf_exceeds_limit() {
1222 let max_line_len = ParseOptions::default().max_line_len();
1223 let mut data = b"get ".to_vec();
1225 data.extend(std::iter::repeat_n(b'a', max_line_len));
1226 data.push(b'\r');
1227 assert!(matches!(
1228 Command::parse(&data),
1229 Err(ParseError::Protocol("line too long"))
1230 ));
1231 }
1232
1233 #[test]
1234 fn test_get_with_key_at_limit() {
1235 let mut data = b"get ".to_vec();
1237 data.extend(std::iter::repeat_n(b'k', DEFAULT_MAX_KEY_LEN));
1238 data.extend(b"\r\n");
1239 let result = Command::parse(&data);
1240 assert!(result.is_ok());
1241 }
1242
1243 #[test]
1244 fn test_delete_with_key_not_checked() {
1245 let mut data = b"delete ".to_vec();
1248 data.extend(std::iter::repeat_n(b'k', DEFAULT_MAX_KEY_LEN + 100));
1249 data.extend(b"\r\n");
1250 let result = Command::parse(&data);
1253 assert!(result.is_ok()); }
1255
1256 #[test]
1257 fn test_too_many_keys() {
1258 let mut data = b"get".to_vec();
1260 for i in 0..DEFAULT_MAX_KEYS + 1 {
1261 data.extend(format!(" k{}", i).as_bytes());
1262 }
1263 data.extend(b"\r\n");
1264 assert!(matches!(
1265 Command::parse(&data),
1266 Err(ParseError::Protocol("too many keys"))
1267 ));
1268 }
1269
1270 #[test]
1271 fn test_custom_options() {
1272 let options = ParseOptions::new()
1274 .max_key_len(10)
1275 .max_value_len(100)
1276 .max_keys(5);
1277
1278 let mut data = b"set kkkkkkkkkk 0 0 1\r\nv\r\n".to_vec();
1280 let result = Command::parse_with_options(&data, &options);
1281 assert!(result.is_ok());
1282
1283 data = b"set kkkkkkkkkkk 0 0 1\r\nv\r\n".to_vec(); let result = Command::parse_with_options(&data, &options);
1286 assert!(matches!(result, Err(ParseError::Protocol("key too large"))));
1287
1288 let cmd = b"set k 0 0 101\r\n";
1290 let mut value_data = cmd.to_vec();
1291 value_data.extend(std::iter::repeat_n(b'v', 101));
1292 value_data.extend(b"\r\n");
1293 let result = Command::parse_with_options(&value_data, &options);
1294 assert!(matches!(
1295 result,
1296 Err(ParseError::Protocol("value too large"))
1297 ));
1298
1299 let data = b"get k1 k2 k3 k4 k5 k6\r\n";
1301 let result = Command::parse_with_options(data, &options);
1302 assert!(matches!(result, Err(ParseError::Protocol("too many keys"))));
1303 }
1304
1305 #[test]
1310 fn test_parse_incr() {
1311 let data = b"incr counter 5\r\n";
1312 let (cmd, consumed) = Command::parse(data).unwrap();
1313 match cmd {
1314 Command::Incr {
1315 key,
1316 delta,
1317 noreply,
1318 } => {
1319 assert_eq!(key, b"counter");
1320 assert_eq!(delta, 5);
1321 assert!(!noreply);
1322 }
1323 _ => panic!("expected Incr"),
1324 }
1325 assert_eq!(consumed, data.len());
1326 }
1327
1328 #[test]
1329 fn test_parse_incr_noreply() {
1330 let data = b"incr counter 10 noreply\r\n";
1331 let (cmd, consumed) = Command::parse(data).unwrap();
1332 match cmd {
1333 Command::Incr {
1334 key,
1335 delta,
1336 noreply,
1337 } => {
1338 assert_eq!(key, b"counter");
1339 assert_eq!(delta, 10);
1340 assert!(noreply);
1341 }
1342 _ => panic!("expected Incr"),
1343 }
1344 assert_eq!(consumed, data.len());
1345 }
1346
1347 #[test]
1348 fn test_parse_incr_case_insensitive() {
1349 let (cmd, _) = Command::parse(b"INCR key 1\r\n").unwrap();
1350 assert!(matches!(cmd, Command::Incr { .. }));
1351 }
1352
1353 #[test]
1354 fn test_parse_incr_noreply_case_insensitive() {
1355 let (cmd, _) = Command::parse(b"incr key 1 NOREPLY\r\n").unwrap();
1356 match cmd {
1357 Command::Incr { noreply, .. } => assert!(noreply),
1358 _ => panic!("expected Incr"),
1359 }
1360 }
1361
1362 #[test]
1363 fn test_parse_incr_missing_key() {
1364 assert!(matches!(
1365 Command::parse(b"incr\r\n"),
1366 Err(ParseError::Protocol("incr requires key"))
1367 ));
1368 }
1369
1370 #[test]
1371 fn test_parse_incr_empty_key() {
1372 assert!(matches!(
1373 Command::parse(b"incr 5\r\n"),
1374 Err(ParseError::Protocol("empty key"))
1375 ));
1376 }
1377
1378 #[test]
1379 fn test_parse_incr_missing_delta() {
1380 assert!(matches!(
1381 Command::parse(b"incr key\r\n"),
1382 Err(ParseError::Protocol("incr requires delta"))
1383 ));
1384 }
1385
1386 #[test]
1387 fn test_parse_incr_invalid_delta() {
1388 assert!(matches!(
1389 Command::parse(b"incr key abc\r\n"),
1390 Err(ParseError::InvalidNumber)
1391 ));
1392 }
1393
1394 #[test]
1395 fn test_parse_incr_key_too_large() {
1396 let mut data = b"incr ".to_vec();
1397 data.extend(std::iter::repeat_n(b'k', DEFAULT_MAX_KEY_LEN + 1));
1398 data.extend(b" 5\r\n");
1399 assert!(matches!(
1400 Command::parse(&data),
1401 Err(ParseError::Protocol("key too large"))
1402 ));
1403 }
1404
1405 #[test]
1406 fn test_parse_decr() {
1407 let data = b"decr counter 3\r\n";
1408 let (cmd, consumed) = Command::parse(data).unwrap();
1409 match cmd {
1410 Command::Decr {
1411 key,
1412 delta,
1413 noreply,
1414 } => {
1415 assert_eq!(key, b"counter");
1416 assert_eq!(delta, 3);
1417 assert!(!noreply);
1418 }
1419 _ => panic!("expected Decr"),
1420 }
1421 assert_eq!(consumed, data.len());
1422 }
1423
1424 #[test]
1425 fn test_parse_decr_noreply() {
1426 let data = b"decr counter 10 noreply\r\n";
1427 let (cmd, consumed) = Command::parse(data).unwrap();
1428 match cmd {
1429 Command::Decr {
1430 key,
1431 delta,
1432 noreply,
1433 } => {
1434 assert_eq!(key, b"counter");
1435 assert_eq!(delta, 10);
1436 assert!(noreply);
1437 }
1438 _ => panic!("expected Decr"),
1439 }
1440 assert_eq!(consumed, data.len());
1441 }
1442
1443 #[test]
1444 fn test_parse_decr_case_insensitive() {
1445 let (cmd, _) = Command::parse(b"DECR key 1\r\n").unwrap();
1446 assert!(matches!(cmd, Command::Decr { .. }));
1447 }
1448
1449 #[test]
1450 fn test_parse_decr_missing_key() {
1451 assert!(matches!(
1452 Command::parse(b"decr\r\n"),
1453 Err(ParseError::Protocol("decr requires key"))
1454 ));
1455 }
1456
1457 #[test]
1458 fn test_parse_decr_missing_delta() {
1459 assert!(matches!(
1460 Command::parse(b"decr key\r\n"),
1461 Err(ParseError::Protocol("decr requires delta"))
1462 ));
1463 }
1464
1465 #[test]
1466 fn test_parse_decr_invalid_delta() {
1467 assert!(matches!(
1468 Command::parse(b"decr key xyz\r\n"),
1469 Err(ParseError::InvalidNumber)
1470 ));
1471 }
1472
1473 #[test]
1474 fn test_incr_decr_command_names() {
1475 assert_eq!(
1476 Command::Incr {
1477 key: b"k",
1478 delta: 1,
1479 noreply: false
1480 }
1481 .name(),
1482 "INCR"
1483 );
1484 assert_eq!(
1485 Command::Decr {
1486 key: b"k",
1487 delta: 1,
1488 noreply: false
1489 }
1490 .name(),
1491 "DECR"
1492 );
1493 }
1494
1495 #[test]
1496 fn test_incr_decr_is_quit() {
1497 assert!(
1498 !Command::Incr {
1499 key: b"k",
1500 delta: 1,
1501 noreply: false
1502 }
1503 .is_quit()
1504 );
1505 assert!(
1506 !Command::Decr {
1507 key: b"k",
1508 delta: 1,
1509 noreply: false
1510 }
1511 .is_quit()
1512 );
1513 }
1514
1515 #[test]
1516 fn test_incr_large_delta() {
1517 let data = b"incr key 18446744073709551615\r\n"; let (cmd, _) = Command::parse(data).unwrap();
1519 match cmd {
1520 Command::Incr { delta, .. } => {
1521 assert_eq!(delta, u64::MAX);
1522 }
1523 _ => panic!("expected Incr"),
1524 }
1525 }
1526}