1use crate::error::ParseError;
14use bytes::Bytes;
15use std::io::Write;
16
17#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct Value {
20 pub key: Vec<u8>,
21 pub flags: u32,
22 pub data: Vec<u8>,
23 pub cas: Option<u64>,
25}
26
27#[derive(Debug, Clone, PartialEq, Eq)]
29pub enum Response {
30 Values(Vec<Value>),
32 Stored,
34 NotStored,
36 Deleted,
38 NotFound,
40 Exists,
42 Ok,
44 Numeric(u64),
46 Version(Vec<u8>),
48 Error,
50 ClientError(Vec<u8>),
52 ServerError(Vec<u8>),
54}
55
56impl Response {
57 #[inline]
63 pub fn stored() -> Self {
64 Response::Stored
65 }
66
67 #[inline]
69 pub fn not_stored() -> Self {
70 Response::NotStored
71 }
72
73 #[inline]
75 pub fn deleted() -> Self {
76 Response::Deleted
77 }
78
79 #[inline]
81 pub fn not_found() -> Self {
82 Response::NotFound
83 }
84
85 #[inline]
87 pub fn ok() -> Self {
88 Response::Ok
89 }
90
91 #[inline]
93 pub fn numeric(value: u64) -> Self {
94 Response::Numeric(value)
95 }
96
97 #[inline]
99 pub fn miss() -> Self {
100 Response::Values(vec![])
101 }
102
103 #[inline]
105 pub fn hit(key: &[u8], flags: u32, data: &[u8]) -> Self {
106 Response::Values(vec![Value {
107 key: key.to_vec(),
108 flags,
109 data: data.to_vec(),
110 cas: None,
111 }])
112 }
113
114 #[inline]
116 pub fn error() -> Self {
117 Response::Error
118 }
119
120 #[inline]
122 pub fn client_error(msg: &[u8]) -> Self {
123 Response::ClientError(msg.to_vec())
124 }
125
126 #[inline]
128 pub fn server_error(msg: &[u8]) -> Self {
129 Response::ServerError(msg.to_vec())
130 }
131
132 #[inline]
138 pub fn is_error(&self) -> bool {
139 matches!(
140 self,
141 Response::Error | Response::ClientError(_) | Response::ServerError(_)
142 )
143 }
144
145 #[inline]
147 pub fn is_miss(&self) -> bool {
148 match self {
149 Response::Values(values) => values.is_empty(),
150 Response::NotFound => true,
151 _ => false,
152 }
153 }
154
155 #[inline]
157 pub fn is_stored(&self) -> bool {
158 matches!(self, Response::Stored)
159 }
160
161 #[inline]
169 pub fn parse(data: &[u8]) -> Result<(Self, usize), ParseError> {
170 let line_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
172 let line = &data[..line_end];
173
174 if line == b"STORED" {
176 return Ok((Response::Stored, line_end + 2));
177 }
178 if line == b"NOT_STORED" {
179 return Ok((Response::NotStored, line_end + 2));
180 }
181 if line == b"DELETED" {
182 return Ok((Response::Deleted, line_end + 2));
183 }
184 if line == b"NOT_FOUND" {
185 return Ok((Response::NotFound, line_end + 2));
186 }
187 if line == b"EXISTS" {
188 return Ok((Response::Exists, line_end + 2));
189 }
190 if line == b"END" {
191 return Ok((Response::Values(vec![]), line_end + 2));
193 }
194 if line == b"OK" {
195 return Ok((Response::Ok, line_end + 2));
196 }
197 if line == b"ERROR" {
198 return Ok((Response::Error, line_end + 2));
199 }
200 if line.starts_with(b"CLIENT_ERROR ") {
201 let msg = line[13..].to_vec();
202 return Ok((Response::ClientError(msg), line_end + 2));
203 }
204 if line.starts_with(b"SERVER_ERROR ") {
205 let msg = line[13..].to_vec();
206 return Ok((Response::ServerError(msg), line_end + 2));
207 }
208 if line.starts_with(b"VERSION ") {
209 let version = line[8..].to_vec();
210 return Ok((Response::Version(version), line_end + 2));
211 }
212
213 if line.starts_with(b"VALUE ") {
215 return parse_value_response(data);
216 }
217
218 if !line.is_empty() && line.iter().all(|&b| b.is_ascii_digit()) {
220 let value = parse_u64(line)?;
221 return Ok((Response::Numeric(value), line_end + 2));
222 }
223
224 Err(ParseError::Protocol("unknown response"))
225 }
226
227 pub fn encode(&self, buf: &mut [u8]) -> usize {
235 match self {
236 Response::Stored => {
237 buf[..8].copy_from_slice(b"STORED\r\n");
238 8
239 }
240 Response::NotStored => {
241 buf[..12].copy_from_slice(b"NOT_STORED\r\n");
242 12
243 }
244 Response::Deleted => {
245 buf[..9].copy_from_slice(b"DELETED\r\n");
246 9
247 }
248 Response::NotFound => {
249 buf[..11].copy_from_slice(b"NOT_FOUND\r\n");
250 11
251 }
252 Response::Exists => {
253 buf[..8].copy_from_slice(b"EXISTS\r\n");
254 8
255 }
256 Response::Ok => {
257 buf[..4].copy_from_slice(b"OK\r\n");
258 4
259 }
260 Response::Numeric(value) => {
261 let mut cursor = std::io::Cursor::new(&mut buf[..]);
262 write!(cursor, "{}\r\n", value).unwrap();
263 cursor.position() as usize
264 }
265 Response::Error => {
266 buf[..7].copy_from_slice(b"ERROR\r\n");
267 7
268 }
269 Response::ClientError(msg) => {
270 let mut pos = 0;
271 buf[pos..pos + 13].copy_from_slice(b"CLIENT_ERROR ");
272 pos += 13;
273 buf[pos..pos + msg.len()].copy_from_slice(msg);
274 pos += msg.len();
275 buf[pos..pos + 2].copy_from_slice(b"\r\n");
276 pos + 2
277 }
278 Response::ServerError(msg) => {
279 let mut pos = 0;
280 buf[pos..pos + 13].copy_from_slice(b"SERVER_ERROR ");
281 pos += 13;
282 buf[pos..pos + msg.len()].copy_from_slice(msg);
283 pos += msg.len();
284 buf[pos..pos + 2].copy_from_slice(b"\r\n");
285 pos + 2
286 }
287 Response::Version(v) => {
288 let mut pos = 0;
289 buf[pos..pos + 8].copy_from_slice(b"VERSION ");
290 pos += 8;
291 buf[pos..pos + v.len()].copy_from_slice(v);
292 pos += v.len();
293 buf[pos..pos + 2].copy_from_slice(b"\r\n");
294 pos + 2
295 }
296 Response::Values(values) => encode_values(buf, values),
297 }
298 }
299
300 #[inline]
306 pub fn encode_stored(buf: &mut [u8]) -> usize {
307 buf[..8].copy_from_slice(b"STORED\r\n");
308 8
309 }
310
311 #[inline]
313 pub fn encode_not_stored(buf: &mut [u8]) -> usize {
314 buf[..12].copy_from_slice(b"NOT_STORED\r\n");
315 12
316 }
317
318 #[inline]
320 pub fn encode_deleted(buf: &mut [u8]) -> usize {
321 buf[..9].copy_from_slice(b"DELETED\r\n");
322 9
323 }
324
325 #[inline]
327 pub fn encode_not_found(buf: &mut [u8]) -> usize {
328 buf[..11].copy_from_slice(b"NOT_FOUND\r\n");
329 11
330 }
331
332 #[inline]
334 pub fn encode_end(buf: &mut [u8]) -> usize {
335 buf[..5].copy_from_slice(b"END\r\n");
336 5
337 }
338
339 #[inline]
341 pub fn encode_value(buf: &mut [u8], key: &[u8], flags: u32, data: &[u8]) -> usize {
342 let mut pos = 0;
343
344 buf[pos..pos + 6].copy_from_slice(b"VALUE ");
346 pos += 6;
347 buf[pos..pos + key.len()].copy_from_slice(key);
348 pos += key.len();
349 buf[pos] = b' ';
350 pos += 1;
351
352 let mut cursor = std::io::Cursor::new(&mut buf[pos..]);
353 write!(cursor, "{} {}\r\n", flags, data.len()).unwrap();
354 pos += cursor.position() as usize;
355
356 buf[pos..pos + data.len()].copy_from_slice(data);
358 pos += data.len();
359 buf[pos..pos + 2].copy_from_slice(b"\r\n");
360 pos += 2;
361
362 buf[pos..pos + 5].copy_from_slice(b"END\r\n");
364 pos + 5
365 }
366
367 #[inline]
371 pub fn encode_value_with_cas(
372 buf: &mut [u8],
373 key: &[u8],
374 flags: u32,
375 data: &[u8],
376 cas: u64,
377 ) -> usize {
378 let mut pos = 0;
379
380 buf[pos..pos + 6].copy_from_slice(b"VALUE ");
382 pos += 6;
383 buf[pos..pos + key.len()].copy_from_slice(key);
384 pos += key.len();
385 buf[pos] = b' ';
386 pos += 1;
387
388 let mut cursor = std::io::Cursor::new(&mut buf[pos..]);
389 write!(cursor, "{} {} {}\r\n", flags, data.len(), cas).unwrap();
390 pos += cursor.position() as usize;
391
392 buf[pos..pos + data.len()].copy_from_slice(data);
394 pos += data.len();
395 buf[pos..pos + 2].copy_from_slice(b"\r\n");
396 pos += 2;
397
398 buf[pos..pos + 5].copy_from_slice(b"END\r\n");
400 pos + 5
401 }
402
403 #[inline]
405 pub fn encode_exists(buf: &mut [u8]) -> usize {
406 buf[..8].copy_from_slice(b"EXISTS\r\n");
407 8
408 }
409
410 #[inline]
412 pub fn encode_numeric(buf: &mut [u8], value: u64) -> usize {
413 let mut cursor = std::io::Cursor::new(&mut buf[..]);
414 write!(cursor, "{}\r\n", value).unwrap();
415 cursor.position() as usize
416 }
417
418 #[inline]
420 pub fn encode_server_error(buf: &mut [u8], msg: &[u8]) -> usize {
421 let mut pos = 0;
422 buf[pos..pos + 13].copy_from_slice(b"SERVER_ERROR ");
423 pos += 13;
424 buf[pos..pos + msg.len()].copy_from_slice(msg);
425 pos += msg.len();
426 buf[pos..pos + 2].copy_from_slice(b"\r\n");
427 pos + 2
428 }
429}
430
431fn find_crlf(data: &[u8]) -> Option<usize> {
433 memchr::memchr(b'\r', data).and_then(|pos| {
434 if pos + 1 < data.len() && data[pos + 1] == b'\n' {
435 Some(pos)
436 } else {
437 None
438 }
439 })
440}
441
442fn parse_value_response(data: &[u8]) -> Result<(Response, usize), ParseError> {
444 let mut values = Vec::new();
445 let mut pos = 0;
446
447 loop {
448 let remaining = &data[pos..];
450 let line_end = find_crlf(remaining).ok_or(ParseError::Incomplete)?;
451 let line = &remaining[..line_end];
452
453 if line == b"END" {
455 pos += line_end + 2;
456 break;
457 }
458
459 if !line.starts_with(b"VALUE ") {
461 return Err(ParseError::Protocol("expected VALUE or END"));
462 }
463
464 let parts: Vec<&[u8]> = line[6..].split(|&b| b == b' ').collect();
465 if parts.len() < 3 {
466 return Err(ParseError::Protocol("invalid VALUE line"));
467 }
468
469 let key = parts[0].to_vec();
470 let flags = parse_u32(parts[1])?;
471 let bytes = parse_usize(parts[2])?;
472 let cas = if parts.len() >= 4 {
473 Some(parse_u64(parts[3])?)
474 } else {
475 None
476 };
477
478 pos += line_end + 2;
480
481 let data_end = pos + bytes;
483 if data.len() < data_end + 2 {
484 return Err(ParseError::Incomplete);
485 }
486
487 if data[data_end] != b'\r' || data[data_end + 1] != b'\n' {
489 return Err(ParseError::Protocol("missing data terminator"));
490 }
491
492 let value_data = data[pos..data_end].to_vec();
493 pos = data_end + 2;
494
495 values.push(Value {
496 key,
497 flags,
498 data: value_data,
499 cas,
500 });
501 }
502
503 Ok((Response::Values(values), pos))
504}
505
506#[derive(Debug, Clone, PartialEq, Eq)]
512pub struct ValueBytes {
513 pub key: Bytes,
514 pub flags: u32,
515 pub data: Bytes,
516 pub cas: Option<u64>,
518}
519
520#[derive(Debug, Clone, PartialEq, Eq)]
522pub enum ResponseBytes {
523 Values(Vec<ValueBytes>),
525 Stored,
527 NotStored,
529 Deleted,
531 NotFound,
533 Exists,
535 Ok,
537 Numeric(u64),
539 Version(Bytes),
541 Error,
543 ClientError(Bytes),
545 ServerError(Bytes),
547}
548
549impl ResponseBytes {
550 #[inline]
552 pub fn is_error(&self) -> bool {
553 matches!(
554 self,
555 ResponseBytes::Error | ResponseBytes::ClientError(_) | ResponseBytes::ServerError(_)
556 )
557 }
558
559 #[inline]
561 pub fn is_miss(&self) -> bool {
562 match self {
563 ResponseBytes::Values(values) => values.is_empty(),
564 ResponseBytes::NotFound => true,
565 _ => false,
566 }
567 }
568
569 #[inline]
571 pub fn is_stored(&self) -> bool {
572 matches!(self, ResponseBytes::Stored)
573 }
574
575 #[inline]
580 pub fn parse(data: Bytes) -> Result<(Self, usize), ParseError> {
581 let line_end = find_crlf(&data).ok_or(ParseError::Incomplete)?;
582 let line = &data[..line_end];
583
584 if line == b"STORED" {
585 return Ok((ResponseBytes::Stored, line_end + 2));
586 }
587 if line == b"NOT_STORED" {
588 return Ok((ResponseBytes::NotStored, line_end + 2));
589 }
590 if line == b"DELETED" {
591 return Ok((ResponseBytes::Deleted, line_end + 2));
592 }
593 if line == b"NOT_FOUND" {
594 return Ok((ResponseBytes::NotFound, line_end + 2));
595 }
596 if line == b"EXISTS" {
597 return Ok((ResponseBytes::Exists, line_end + 2));
598 }
599 if line == b"END" {
600 return Ok((ResponseBytes::Values(vec![]), line_end + 2));
601 }
602 if line == b"OK" {
603 return Ok((ResponseBytes::Ok, line_end + 2));
604 }
605 if line == b"ERROR" {
606 return Ok((ResponseBytes::Error, line_end + 2));
607 }
608 if line.starts_with(b"CLIENT_ERROR ") {
609 let msg = data.slice(13..line_end);
610 return Ok((ResponseBytes::ClientError(msg), line_end + 2));
611 }
612 if line.starts_with(b"SERVER_ERROR ") {
613 let msg = data.slice(13..line_end);
614 return Ok((ResponseBytes::ServerError(msg), line_end + 2));
615 }
616 if line.starts_with(b"VERSION ") {
617 let version = data.slice(8..line_end);
618 return Ok((ResponseBytes::Version(version), line_end + 2));
619 }
620
621 if line.starts_with(b"VALUE ") {
622 return parse_value_response_bytes(&data);
623 }
624
625 if !line.is_empty() && line.iter().all(|&b| b.is_ascii_digit()) {
626 let value = parse_u64(line)?;
627 return Ok((ResponseBytes::Numeric(value), line_end + 2));
628 }
629
630 Err(ParseError::Protocol("unknown response"))
631 }
632}
633
634fn parse_value_response_bytes(data: &Bytes) -> Result<(ResponseBytes, usize), ParseError> {
636 let mut values = Vec::new();
637 let mut pos = 0;
638
639 loop {
640 let remaining = &data[pos..];
641 let line_end = find_crlf(remaining).ok_or(ParseError::Incomplete)?;
642 let line = &remaining[..line_end];
643
644 if line == b"END" {
645 pos += line_end + 2;
646 break;
647 }
648
649 if !line.starts_with(b"VALUE ") {
650 return Err(ParseError::Protocol("expected VALUE or END"));
651 }
652
653 let header_start = pos + 6; let header_end = pos + line_end;
657 let header = &data[header_start..header_end];
658
659 let parts: Vec<&[u8]> = header.split(|&b| b == b' ').collect();
660 if parts.len() < 3 {
661 return Err(ParseError::Protocol("invalid VALUE line"));
662 }
663
664 let key_start = header_start;
666 let key_end = key_start + parts[0].len();
667 let key = data.slice(key_start..key_end);
668
669 let flags = parse_u32(parts[1])?;
670 let bytes = parse_usize(parts[2])?;
671 let cas = if parts.len() >= 4 {
672 Some(parse_u64(parts[3])?)
673 } else {
674 None
675 };
676
677 pos += line_end + 2;
679
680 let data_end = pos + bytes;
682 if data.len() < data_end + 2 {
683 return Err(ParseError::Incomplete);
684 }
685
686 if data[data_end] != b'\r' || data[data_end + 1] != b'\n' {
687 return Err(ParseError::Protocol("missing data terminator"));
688 }
689
690 let value_data = data.slice(pos..data_end);
691 pos = data_end + 2;
692
693 values.push(ValueBytes {
694 key,
695 flags,
696 data: value_data,
697 cas,
698 });
699 }
700
701 Ok((ResponseBytes::Values(values), pos))
702}
703
704fn encode_values(buf: &mut [u8], values: &[Value]) -> usize {
706 let mut pos = 0;
707
708 for value in values {
709 buf[pos..pos + 6].copy_from_slice(b"VALUE ");
711 pos += 6;
712 buf[pos..pos + value.key.len()].copy_from_slice(&value.key);
713 pos += value.key.len();
714 buf[pos] = b' ';
715 pos += 1;
716
717 let mut cursor = std::io::Cursor::new(&mut buf[pos..]);
718 if let Some(cas) = value.cas {
719 write!(cursor, "{} {} {}\r\n", value.flags, value.data.len(), cas).unwrap();
720 } else {
721 write!(cursor, "{} {}\r\n", value.flags, value.data.len()).unwrap();
722 }
723 pos += cursor.position() as usize;
724
725 buf[pos..pos + value.data.len()].copy_from_slice(&value.data);
727 pos += value.data.len();
728 buf[pos..pos + 2].copy_from_slice(b"\r\n");
729 pos += 2;
730 }
731
732 buf[pos..pos + 5].copy_from_slice(b"END\r\n");
734 pos + 5
735}
736
737fn parse_u32(data: &[u8]) -> Result<u32, ParseError> {
739 std::str::from_utf8(data)
740 .map_err(|_| ParseError::InvalidNumber)?
741 .parse()
742 .map_err(|_| ParseError::InvalidNumber)
743}
744
745fn parse_u64(data: &[u8]) -> Result<u64, ParseError> {
747 std::str::from_utf8(data)
748 .map_err(|_| ParseError::InvalidNumber)?
749 .parse()
750 .map_err(|_| ParseError::InvalidNumber)
751}
752
753const MAX_VALUE_DATA_LEN: usize = 1024 * 1024;
755
756fn parse_usize(data: &[u8]) -> Result<usize, ParseError> {
758 let value: usize = std::str::from_utf8(data)
759 .map_err(|_| ParseError::InvalidNumber)?
760 .parse()
761 .map_err(|_| ParseError::InvalidNumber)?;
762
763 if value > MAX_VALUE_DATA_LEN {
764 return Err(ParseError::Protocol("value data too large"));
765 }
766
767 Ok(value)
768}
769
770#[cfg(test)]
771mod tests {
772 use super::*;
773
774 #[test]
775 fn test_parse_stored() {
776 let (resp, consumed) = Response::parse(b"STORED\r\n").unwrap();
777 assert_eq!(resp, Response::Stored);
778 assert_eq!(consumed, 8);
779 }
780
781 #[test]
782 fn test_parse_not_stored() {
783 let (resp, consumed) = Response::parse(b"NOT_STORED\r\n").unwrap();
784 assert_eq!(resp, Response::NotStored);
785 assert_eq!(consumed, 12);
786 }
787
788 #[test]
789 fn test_parse_deleted() {
790 let (resp, consumed) = Response::parse(b"DELETED\r\n").unwrap();
791 assert_eq!(resp, Response::Deleted);
792 assert_eq!(consumed, 9);
793 }
794
795 #[test]
796 fn test_parse_not_found() {
797 let (resp, consumed) = Response::parse(b"NOT_FOUND\r\n").unwrap();
798 assert_eq!(resp, Response::NotFound);
799 assert_eq!(consumed, 11);
800 }
801
802 #[test]
803 fn test_parse_end() {
804 let (resp, consumed) = Response::parse(b"END\r\n").unwrap();
805 assert_eq!(resp, Response::Values(vec![]));
806 assert_eq!(consumed, 5);
807 assert!(resp.is_miss());
808 }
809
810 #[test]
811 fn test_parse_value() {
812 let data = b"VALUE mykey 0 7\r\nmyvalue\r\nEND\r\n";
813 let (resp, consumed) = Response::parse(data).unwrap();
814 assert_eq!(consumed, data.len());
815 match resp {
816 Response::Values(values) => {
817 assert_eq!(values.len(), 1);
818 assert_eq!(values[0].key, b"mykey");
819 assert_eq!(values[0].flags, 0);
820 assert_eq!(values[0].data, b"myvalue");
821 }
822 _ => panic!("expected Values"),
823 }
824 }
825
826 #[test]
827 fn test_parse_multi_value() {
828 let data = b"VALUE key1 0 3\r\nfoo\r\nVALUE key2 0 3\r\nbar\r\nEND\r\n";
829 let (resp, consumed) = Response::parse(data).unwrap();
830 assert_eq!(consumed, data.len());
831 match resp {
832 Response::Values(values) => {
833 assert_eq!(values.len(), 2);
834 assert_eq!(values[0].key, b"key1");
835 assert_eq!(values[0].data, b"foo");
836 assert_eq!(values[1].key, b"key2");
837 assert_eq!(values[1].data, b"bar");
838 }
839 _ => panic!("expected Values"),
840 }
841 }
842
843 #[test]
844 fn test_parse_error() {
845 let (resp, _) = Response::parse(b"ERROR\r\n").unwrap();
846 assert!(resp.is_error());
847 }
848
849 #[test]
850 fn test_parse_server_error() {
851 let (resp, _) = Response::parse(b"SERVER_ERROR out of memory\r\n").unwrap();
852 assert!(resp.is_error());
853 match resp {
854 Response::ServerError(msg) => assert_eq!(msg, b"out of memory"),
855 _ => panic!("expected ServerError"),
856 }
857 }
858
859 #[test]
860 fn test_parse_incomplete() {
861 assert!(matches!(
862 Response::parse(b"VALUE mykey 0 7\r\nmyval"),
863 Err(ParseError::Incomplete)
864 ));
865 }
866
867 #[test]
868 fn test_encode_stored() {
869 let mut buf = [0u8; 64];
870 let len = Response::stored().encode(&mut buf);
871 assert_eq!(&buf[..len], b"STORED\r\n");
872 }
873
874 #[test]
875 fn test_encode_deleted() {
876 let mut buf = [0u8; 64];
877 let len = Response::deleted().encode(&mut buf);
878 assert_eq!(&buf[..len], b"DELETED\r\n");
879 }
880
881 #[test]
882 fn test_encode_value() {
883 let mut buf = [0u8; 128];
884 let len = Response::encode_value(&mut buf, b"mykey", 0, b"myvalue");
885 assert_eq!(&buf[..len], b"VALUE mykey 0 7\r\nmyvalue\r\nEND\r\n");
886 }
887
888 #[test]
889 fn test_encode_miss() {
890 let mut buf = [0u8; 64];
891 let len = Response::miss().encode(&mut buf);
892 assert_eq!(&buf[..len], b"END\r\n");
893 }
894
895 #[test]
896 fn test_roundtrip() {
897 let mut buf = [0u8; 256];
898
899 let responses = vec![
901 Response::stored(),
902 Response::not_stored(),
903 Response::deleted(),
904 Response::not_found(),
905 Response::ok(),
906 Response::numeric(0),
907 Response::numeric(42),
908 Response::numeric(18446744073709551615),
909 Response::error(),
910 Response::miss(),
911 ];
912
913 for original in responses {
914 let len = original.encode(&mut buf);
915 let (parsed, consumed) = Response::parse(&buf[..len]).unwrap();
916 assert_eq!(original, parsed);
917 assert_eq!(len, consumed);
918 }
919 }
920
921 #[test]
924 fn test_parse_exists() {
925 let (resp, consumed) = Response::parse(b"EXISTS\r\n").unwrap();
926 assert_eq!(resp, Response::Exists);
927 assert_eq!(consumed, 8);
928 }
929
930 #[test]
931 fn test_parse_client_error() {
932 let (resp, consumed) = Response::parse(b"CLIENT_ERROR bad request\r\n").unwrap();
933 assert!(resp.is_error());
934 assert_eq!(consumed, 26);
935 match resp {
936 Response::ClientError(msg) => assert_eq!(msg, b"bad request"),
937 _ => panic!("expected ClientError"),
938 }
939 }
940
941 #[test]
942 fn test_parse_version() {
943 let (resp, consumed) = Response::parse(b"VERSION 1.6.9\r\n").unwrap();
944 assert_eq!(consumed, 15);
945 match resp {
946 Response::Version(v) => assert_eq!(v, b"1.6.9"),
947 _ => panic!("expected Version"),
948 }
949 }
950
951 #[test]
952 fn test_parse_unknown_response() {
953 let result = Response::parse(b"UNKNOWN\r\n");
954 assert!(matches!(
955 result,
956 Err(ParseError::Protocol("unknown response"))
957 ));
958 }
959
960 #[test]
961 fn test_parse_incomplete_no_crlf() {
962 assert!(matches!(
963 Response::parse(b"STORED"),
964 Err(ParseError::Incomplete)
965 ));
966 }
967
968 #[test]
969 fn test_parse_value_incomplete_data() {
970 assert!(matches!(
972 Response::parse(b"VALUE k 0 10\r\nshort\r\nEND\r\n"),
973 Err(ParseError::Incomplete)
974 ));
975 }
976
977 #[test]
978 fn test_parse_value_missing_terminator() {
979 assert!(matches!(
981 Response::parse(b"VALUE k 0 5\r\nhelloXXEND\r\n"),
982 Err(ParseError::Protocol("missing data terminator"))
983 ));
984 }
985
986 #[test]
987 fn test_parse_value_invalid_format() {
988 assert!(matches!(
990 Response::parse(b"VALUE k\r\nEND\r\n"),
991 Err(ParseError::Protocol("invalid VALUE line"))
992 ));
993 }
994
995 #[test]
996 fn test_parse_value_invalid_flags() {
997 assert!(matches!(
999 Response::parse(b"VALUE k abc 5\r\nhello\r\nEND\r\n"),
1000 Err(ParseError::InvalidNumber)
1001 ));
1002 }
1003
1004 #[test]
1005 fn test_parse_value_invalid_bytes() {
1006 assert!(matches!(
1008 Response::parse(b"VALUE k 0 xyz\r\nhello\r\nEND\r\n"),
1009 Err(ParseError::InvalidNumber)
1010 ));
1011 }
1012
1013 #[test]
1014 fn test_parse_value_expected_end() {
1015 assert!(matches!(
1017 Response::parse(b"VALUE k 0 5\r\nhello\r\nSTORED\r\n"),
1018 Err(ParseError::Protocol("expected VALUE or END"))
1019 ));
1020 }
1021
1022 #[test]
1023 fn test_parse_ok() {
1024 let (resp, consumed) = Response::parse(b"OK\r\n").unwrap();
1025 assert_eq!(resp, Response::Ok);
1026 assert_eq!(consumed, 4);
1027 }
1028
1029 #[test]
1030 fn test_encode_ok() {
1031 let mut buf = [0u8; 64];
1032 let len = Response::ok().encode(&mut buf);
1033 assert_eq!(&buf[..len], b"OK\r\n");
1034 }
1035
1036 #[test]
1037 fn test_parse_numeric() {
1038 let (resp, consumed) = Response::parse(b"42\r\n").unwrap();
1039 assert_eq!(resp, Response::Numeric(42));
1040 assert_eq!(consumed, 4);
1041 }
1042
1043 #[test]
1044 fn test_parse_numeric_zero() {
1045 let (resp, consumed) = Response::parse(b"0\r\n").unwrap();
1046 assert_eq!(resp, Response::Numeric(0));
1047 assert_eq!(consumed, 3);
1048 }
1049
1050 #[test]
1051 fn test_parse_numeric_large() {
1052 let (resp, consumed) = Response::parse(b"18446744073709551615\r\n").unwrap();
1053 assert_eq!(resp, Response::Numeric(u64::MAX));
1054 assert_eq!(consumed, 22);
1055 }
1056
1057 #[test]
1058 fn test_encode_numeric() {
1059 let mut buf = [0u8; 64];
1060 let len = Response::numeric(42).encode(&mut buf);
1061 assert_eq!(&buf[..len], b"42\r\n");
1062 }
1063
1064 #[test]
1065 fn test_encode_numeric_zero() {
1066 let mut buf = [0u8; 64];
1067 let len = Response::numeric(0).encode(&mut buf);
1068 assert_eq!(&buf[..len], b"0\r\n");
1069 }
1070
1071 #[test]
1072 fn test_direct_encode_numeric() {
1073 let mut buf = [0u8; 64];
1074 let len = Response::encode_numeric(&mut buf, 12345);
1075 assert_eq!(&buf[..len], b"12345\r\n");
1076 }
1077
1078 #[test]
1079 fn test_is_error_variants() {
1080 assert!(Response::Error.is_error());
1081 assert!(Response::ClientError(b"msg".to_vec()).is_error());
1082 assert!(Response::ServerError(b"msg".to_vec()).is_error());
1083 assert!(!Response::Stored.is_error());
1084 assert!(!Response::NotStored.is_error());
1085 assert!(!Response::Deleted.is_error());
1086 assert!(!Response::NotFound.is_error());
1087 assert!(!Response::Exists.is_error());
1088 assert!(!Response::Ok.is_error());
1089 assert!(!Response::Numeric(42).is_error());
1090 assert!(!Response::Values(vec![]).is_error());
1091 assert!(!Response::Version(b"1.0".to_vec()).is_error());
1092 }
1093
1094 #[test]
1095 fn test_is_miss_variants() {
1096 assert!(Response::Values(vec![]).is_miss());
1098 assert!(Response::NotFound.is_miss());
1100 assert!(
1102 !Response::Values(vec![Value {
1103 key: b"k".to_vec(),
1104 flags: 0,
1105 data: b"v".to_vec(),
1106 cas: None,
1107 }])
1108 .is_miss()
1109 );
1110 assert!(!Response::Stored.is_miss());
1112 assert!(!Response::Deleted.is_miss());
1113 assert!(!Response::Ok.is_miss());
1114 assert!(!Response::Numeric(0).is_miss());
1115 assert!(!Response::Error.is_miss());
1116 }
1117
1118 #[test]
1119 fn test_is_stored_variants() {
1120 assert!(Response::Stored.is_stored());
1121 assert!(!Response::NotStored.is_stored());
1122 assert!(!Response::Deleted.is_stored());
1123 assert!(!Response::Error.is_stored());
1124 }
1125
1126 #[test]
1127 fn test_encode_not_stored() {
1128 let mut buf = [0u8; 64];
1129 let len = Response::not_stored().encode(&mut buf);
1130 assert_eq!(&buf[..len], b"NOT_STORED\r\n");
1131 }
1132
1133 #[test]
1134 fn test_encode_not_found() {
1135 let mut buf = [0u8; 64];
1136 let len = Response::not_found().encode(&mut buf);
1137 assert_eq!(&buf[..len], b"NOT_FOUND\r\n");
1138 }
1139
1140 #[test]
1141 fn test_encode_exists() {
1142 let mut buf = [0u8; 64];
1143 let len = Response::Exists.encode(&mut buf);
1144 assert_eq!(&buf[..len], b"EXISTS\r\n");
1145 }
1146
1147 #[test]
1148 fn test_encode_error() {
1149 let mut buf = [0u8; 64];
1150 let len = Response::error().encode(&mut buf);
1151 assert_eq!(&buf[..len], b"ERROR\r\n");
1152 }
1153
1154 #[test]
1155 fn test_encode_client_error() {
1156 let mut buf = [0u8; 64];
1157 let len = Response::client_error(b"bad request").encode(&mut buf);
1158 assert_eq!(&buf[..len], b"CLIENT_ERROR bad request\r\n");
1159 }
1160
1161 #[test]
1162 fn test_encode_server_error() {
1163 let mut buf = [0u8; 64];
1164 let len = Response::server_error(b"out of memory").encode(&mut buf);
1165 assert_eq!(&buf[..len], b"SERVER_ERROR out of memory\r\n");
1166 }
1167
1168 #[test]
1169 fn test_encode_version() {
1170 let mut buf = [0u8; 64];
1171 let len = Response::Version(b"1.6.9".to_vec()).encode(&mut buf);
1172 assert_eq!(&buf[..len], b"VERSION 1.6.9\r\n");
1173 }
1174
1175 #[test]
1176 fn test_encode_hit() {
1177 let mut buf = [0u8; 128];
1178 let resp = Response::hit(b"mykey", 42, b"myvalue");
1179 let len = resp.encode(&mut buf);
1180 assert_eq!(&buf[..len], b"VALUE mykey 42 7\r\nmyvalue\r\nEND\r\n");
1181 }
1182
1183 #[test]
1184 fn test_encode_multi_values() {
1185 let mut buf = [0u8; 256];
1186 let resp = Response::Values(vec![
1187 Value {
1188 key: b"k1".to_vec(),
1189 flags: 0,
1190 data: b"v1".to_vec(),
1191 cas: None,
1192 },
1193 Value {
1194 key: b"k2".to_vec(),
1195 flags: 1,
1196 data: b"v2".to_vec(),
1197 cas: None,
1198 },
1199 ]);
1200 let len = resp.encode(&mut buf);
1201 assert_eq!(
1202 &buf[..len],
1203 b"VALUE k1 0 2\r\nv1\r\nVALUE k2 1 2\r\nv2\r\nEND\r\n"
1204 );
1205 }
1206
1207 #[test]
1208 fn test_direct_encode_stored() {
1209 let mut buf = [0u8; 64];
1210 let len = Response::encode_stored(&mut buf);
1211 assert_eq!(&buf[..len], b"STORED\r\n");
1212 }
1213
1214 #[test]
1215 fn test_direct_encode_not_stored() {
1216 let mut buf = [0u8; 64];
1217 let len = Response::encode_not_stored(&mut buf);
1218 assert_eq!(&buf[..len], b"NOT_STORED\r\n");
1219 }
1220
1221 #[test]
1222 fn test_direct_encode_deleted() {
1223 let mut buf = [0u8; 64];
1224 let len = Response::encode_deleted(&mut buf);
1225 assert_eq!(&buf[..len], b"DELETED\r\n");
1226 }
1227
1228 #[test]
1229 fn test_direct_encode_not_found() {
1230 let mut buf = [0u8; 64];
1231 let len = Response::encode_not_found(&mut buf);
1232 assert_eq!(&buf[..len], b"NOT_FOUND\r\n");
1233 }
1234
1235 #[test]
1236 fn test_direct_encode_end() {
1237 let mut buf = [0u8; 64];
1238 let len = Response::encode_end(&mut buf);
1239 assert_eq!(&buf[..len], b"END\r\n");
1240 }
1241
1242 #[test]
1243 fn test_direct_encode_server_error() {
1244 let mut buf = [0u8; 64];
1245 let len = Response::encode_server_error(&mut buf, b"error message");
1246 assert_eq!(&buf[..len], b"SERVER_ERROR error message\r\n");
1247 }
1248
1249 #[test]
1250 fn test_roundtrip_client_error() {
1251 let mut buf = [0u8; 256];
1252 let original = Response::client_error(b"test error");
1253 let len = original.encode(&mut buf);
1254 let (parsed, consumed) = Response::parse(&buf[..len]).unwrap();
1255 assert_eq!(original, parsed);
1256 assert_eq!(len, consumed);
1257 }
1258
1259 #[test]
1260 fn test_roundtrip_server_error() {
1261 let mut buf = [0u8; 256];
1262 let original = Response::server_error(b"test error");
1263 let len = original.encode(&mut buf);
1264 let (parsed, consumed) = Response::parse(&buf[..len]).unwrap();
1265 assert_eq!(original, parsed);
1266 assert_eq!(len, consumed);
1267 }
1268
1269 #[test]
1270 fn test_roundtrip_values() {
1271 let mut buf = [0u8; 256];
1272 let original = Response::hit(b"testkey", 123, b"testvalue");
1273 let len = original.encode(&mut buf);
1274 let (parsed, consumed) = Response::parse(&buf[..len]).unwrap();
1275 assert_eq!(original, parsed);
1276 assert_eq!(len, consumed);
1277 }
1278
1279 #[test]
1280 fn test_value_debug() {
1281 let v = Value {
1282 key: b"k".to_vec(),
1283 flags: 0,
1284 data: b"v".to_vec(),
1285 cas: None,
1286 };
1287 let debug_str = format!("{:?}", v);
1288 assert!(debug_str.contains("Value"));
1289 }
1290
1291 #[test]
1292 fn test_value_clone() {
1293 let v1 = Value {
1294 key: b"k".to_vec(),
1295 flags: 42,
1296 data: b"v".to_vec(),
1297 cas: None,
1298 };
1299 let v2 = v1.clone();
1300 assert_eq!(v1, v2);
1301 }
1302
1303 #[test]
1304 fn test_response_debug() {
1305 let resp = Response::Stored;
1306 let debug_str = format!("{:?}", resp);
1307 assert!(debug_str.contains("Stored"));
1308 }
1309
1310 #[test]
1311 fn test_response_clone() {
1312 let r1 = Response::Stored;
1313 let r2 = r1.clone();
1314 assert_eq!(r1, r2);
1315 }
1316
1317 #[test]
1318 fn test_parse_value_with_flags() {
1319 let data = b"VALUE mykey 12345 5\r\nhello\r\nEND\r\n";
1320 let (resp, _) = Response::parse(data).unwrap();
1321 match resp {
1322 Response::Values(values) => {
1323 assert_eq!(values[0].flags, 12345);
1324 }
1325 _ => panic!("expected Values"),
1326 }
1327 }
1328
1329 #[test]
1330 fn test_find_crlf_edge_cases() {
1331 assert!(Response::parse(b"STORED\r").is_err());
1333 }
1334
1335 #[test]
1336 fn test_parse_value_data_too_large() {
1337 let data = b"VALUE k 0 18446744073709551615\r\n";
1339 let result = Response::parse(data);
1340 assert!(matches!(
1341 result,
1342 Err(ParseError::Protocol("value data too large"))
1343 ));
1344 }
1345
1346 #[test]
1347 fn test_parse_value_with_cas() {
1348 let data = b"VALUE mykey 0 5 12345\r\nhello\r\nEND\r\n";
1349 let (resp, consumed) = Response::parse(data).unwrap();
1350 assert_eq!(consumed, data.len());
1351 match resp {
1352 Response::Values(values) => {
1353 assert_eq!(values.len(), 1);
1354 assert_eq!(values[0].key, b"mykey");
1355 assert_eq!(values[0].data, b"hello");
1356 assert_eq!(values[0].cas, Some(12345));
1357 }
1358 _ => panic!("expected Values"),
1359 }
1360 }
1361
1362 #[test]
1363 fn test_parse_value_without_cas() {
1364 let data = b"VALUE mykey 0 5\r\nhello\r\nEND\r\n";
1365 let (resp, _) = Response::parse(data).unwrap();
1366 match resp {
1367 Response::Values(values) => {
1368 assert_eq!(values[0].cas, None);
1369 }
1370 _ => panic!("expected Values"),
1371 }
1372 }
1373
1374 #[test]
1375 fn test_roundtrip_value_with_cas() {
1376 let mut buf = [0u8; 256];
1377 let original = Response::Values(vec![Value {
1378 key: b"testkey".to_vec(),
1379 flags: 0,
1380 data: b"testvalue".to_vec(),
1381 cas: Some(98765),
1382 }]);
1383 let len = original.encode(&mut buf);
1384 let (parsed, consumed) = Response::parse(&buf[..len]).unwrap();
1385 assert_eq!(original, parsed);
1386 assert_eq!(len, consumed);
1387 }
1388
1389 #[test]
1390 fn test_parse_multi_value_with_cas() {
1391 let data = b"VALUE k1 0 2 100\r\nv1\r\nVALUE k2 0 2 200\r\nv2\r\nEND\r\n";
1392 let (resp, consumed) = Response::parse(data).unwrap();
1393 assert_eq!(consumed, data.len());
1394 match resp {
1395 Response::Values(values) => {
1396 assert_eq!(values.len(), 2);
1397 assert_eq!(values[0].cas, Some(100));
1398 assert_eq!(values[1].cas, Some(200));
1399 }
1400 _ => panic!("expected Values"),
1401 }
1402 }
1403
1404 #[test]
1407 fn test_parse_bytes_stored() {
1408 let data = Bytes::from_static(b"STORED\r\n");
1409 let (resp, consumed) = ResponseBytes::parse(data).unwrap();
1410 assert_eq!(resp, ResponseBytes::Stored);
1411 assert_eq!(consumed, 8);
1412 }
1413
1414 #[test]
1415 fn test_parse_bytes_not_stored() {
1416 let data = Bytes::from_static(b"NOT_STORED\r\n");
1417 let (resp, consumed) = ResponseBytes::parse(data).unwrap();
1418 assert_eq!(resp, ResponseBytes::NotStored);
1419 assert_eq!(consumed, 12);
1420 }
1421
1422 #[test]
1423 fn test_parse_bytes_deleted() {
1424 let data = Bytes::from_static(b"DELETED\r\n");
1425 let (resp, consumed) = ResponseBytes::parse(data).unwrap();
1426 assert_eq!(resp, ResponseBytes::Deleted);
1427 assert_eq!(consumed, 9);
1428 }
1429
1430 #[test]
1431 fn test_parse_bytes_not_found() {
1432 let data = Bytes::from_static(b"NOT_FOUND\r\n");
1433 let (resp, consumed) = ResponseBytes::parse(data).unwrap();
1434 assert_eq!(resp, ResponseBytes::NotFound);
1435 assert_eq!(consumed, 11);
1436 }
1437
1438 #[test]
1439 fn test_parse_bytes_exists() {
1440 let data = Bytes::from_static(b"EXISTS\r\n");
1441 let (resp, consumed) = ResponseBytes::parse(data).unwrap();
1442 assert_eq!(resp, ResponseBytes::Exists);
1443 assert_eq!(consumed, 8);
1444 }
1445
1446 #[test]
1447 fn test_parse_bytes_end() {
1448 let data = Bytes::from_static(b"END\r\n");
1449 let (resp, consumed) = ResponseBytes::parse(data).unwrap();
1450 assert_eq!(resp, ResponseBytes::Values(vec![]));
1451 assert_eq!(consumed, 5);
1452 assert!(resp.is_miss());
1453 }
1454
1455 #[test]
1456 fn test_parse_bytes_ok() {
1457 let data = Bytes::from_static(b"OK\r\n");
1458 let (resp, consumed) = ResponseBytes::parse(data).unwrap();
1459 assert_eq!(resp, ResponseBytes::Ok);
1460 assert_eq!(consumed, 4);
1461 }
1462
1463 #[test]
1464 fn test_parse_bytes_error() {
1465 let data = Bytes::from_static(b"ERROR\r\n");
1466 let (resp, _) = ResponseBytes::parse(data).unwrap();
1467 assert!(resp.is_error());
1468 }
1469
1470 #[test]
1471 fn test_parse_bytes_numeric() {
1472 let data = Bytes::from_static(b"42\r\n");
1473 let (resp, consumed) = ResponseBytes::parse(data).unwrap();
1474 assert_eq!(resp, ResponseBytes::Numeric(42));
1475 assert_eq!(consumed, 4);
1476 }
1477
1478 #[test]
1479 fn test_parse_bytes_client_error() {
1480 let data = Bytes::from_static(b"CLIENT_ERROR bad request\r\n");
1481 let (resp, consumed) = ResponseBytes::parse(data).unwrap();
1482 assert!(resp.is_error());
1483 assert_eq!(consumed, 26);
1484 match resp {
1485 ResponseBytes::ClientError(msg) => assert_eq!(&msg[..], b"bad request"),
1486 _ => panic!("expected ClientError"),
1487 }
1488 }
1489
1490 #[test]
1491 fn test_parse_bytes_server_error() {
1492 let data = Bytes::from_static(b"SERVER_ERROR out of memory\r\n");
1493 let (resp, _) = ResponseBytes::parse(data).unwrap();
1494 assert!(resp.is_error());
1495 match resp {
1496 ResponseBytes::ServerError(msg) => assert_eq!(&msg[..], b"out of memory"),
1497 _ => panic!("expected ServerError"),
1498 }
1499 }
1500
1501 #[test]
1502 fn test_parse_bytes_version() {
1503 let data = Bytes::from_static(b"VERSION 1.6.9\r\n");
1504 let (resp, consumed) = ResponseBytes::parse(data).unwrap();
1505 assert_eq!(consumed, 15);
1506 match resp {
1507 ResponseBytes::Version(v) => assert_eq!(&v[..], b"1.6.9"),
1508 _ => panic!("expected Version"),
1509 }
1510 }
1511
1512 #[test]
1513 fn test_parse_bytes_value() {
1514 let data = Bytes::from_static(b"VALUE mykey 0 7\r\nmyvalue\r\nEND\r\n");
1515 let (resp, consumed) = ResponseBytes::parse(data).unwrap();
1516 assert_eq!(consumed, 31);
1517 match resp {
1518 ResponseBytes::Values(values) => {
1519 assert_eq!(values.len(), 1);
1520 assert_eq!(&values[0].key[..], b"mykey");
1521 assert_eq!(values[0].flags, 0);
1522 assert_eq!(&values[0].data[..], b"myvalue");
1523 assert_eq!(values[0].cas, None);
1524 }
1525 _ => panic!("expected Values"),
1526 }
1527 }
1528
1529 #[test]
1530 fn test_parse_bytes_multi_value() {
1531 let raw = b"VALUE key1 0 3\r\nfoo\r\nVALUE key2 0 3\r\nbar\r\nEND\r\n";
1532 let data = Bytes::from_static(raw);
1533 let (resp, consumed) = ResponseBytes::parse(data).unwrap();
1534 assert_eq!(consumed, raw.len());
1535 match resp {
1536 ResponseBytes::Values(values) => {
1537 assert_eq!(values.len(), 2);
1538 assert_eq!(&values[0].key[..], b"key1");
1539 assert_eq!(&values[0].data[..], b"foo");
1540 assert_eq!(&values[1].key[..], b"key2");
1541 assert_eq!(&values[1].data[..], b"bar");
1542 }
1543 _ => panic!("expected Values"),
1544 }
1545 }
1546
1547 #[test]
1548 fn test_parse_bytes_value_with_cas() {
1549 let data = Bytes::from_static(b"VALUE mykey 0 5 12345\r\nhello\r\nEND\r\n");
1550 let (resp, consumed) = ResponseBytes::parse(data).unwrap();
1551 assert_eq!(consumed, 35);
1552 match resp {
1553 ResponseBytes::Values(values) => {
1554 assert_eq!(values.len(), 1);
1555 assert_eq!(&values[0].key[..], b"mykey");
1556 assert_eq!(&values[0].data[..], b"hello");
1557 assert_eq!(values[0].cas, Some(12345));
1558 }
1559 _ => panic!("expected Values"),
1560 }
1561 }
1562
1563 #[test]
1564 fn test_parse_bytes_value_with_flags() {
1565 let data = Bytes::from_static(b"VALUE mykey 12345 5\r\nhello\r\nEND\r\n");
1566 let (resp, _) = ResponseBytes::parse(data).unwrap();
1567 match resp {
1568 ResponseBytes::Values(values) => {
1569 assert_eq!(values[0].flags, 12345);
1570 }
1571 _ => panic!("expected Values"),
1572 }
1573 }
1574
1575 #[test]
1576 fn test_parse_bytes_incomplete() {
1577 let data = Bytes::from_static(b"VALUE mykey 0 7\r\nmyval");
1578 assert!(matches!(
1579 ResponseBytes::parse(data),
1580 Err(ParseError::Incomplete)
1581 ));
1582 }
1583
1584 #[test]
1585 fn test_parse_bytes_unknown() {
1586 let data = Bytes::from_static(b"UNKNOWN\r\n");
1587 assert!(matches!(
1588 ResponseBytes::parse(data),
1589 Err(ParseError::Protocol("unknown response"))
1590 ));
1591 }
1592
1593 #[test]
1594 fn test_parse_bytes_zero_copy_slices() {
1595 let raw = b"VALUE mykey 0 7\r\nmyvalue\r\nEND\r\n";
1597 let data = Bytes::copy_from_slice(raw);
1598 let (resp, _) = ResponseBytes::parse(data.clone()).unwrap();
1599 match resp {
1600 ResponseBytes::Values(values) => {
1601 assert_eq!(&values[0].key[..], b"mykey");
1603 assert_eq!(&values[0].data[..], b"myvalue");
1604 }
1605 _ => panic!("expected Values"),
1606 }
1607 }
1608
1609 #[test]
1610 fn test_parse_bytes_is_stored() {
1611 assert!(ResponseBytes::Stored.is_stored());
1612 assert!(!ResponseBytes::NotStored.is_stored());
1613 }
1614}