1use crate::error::ParseError;
24use bytes::Bytes;
25use std::io::Write;
26
27pub const DEFAULT_MAX_KEY_LEN: usize = 250;
31
32pub const DEFAULT_MAX_COLLECTION_ELEMENTS: usize = 1024;
38
39pub const DEFAULT_MAX_BULK_STRING_LEN: usize = 1024 * 1024;
48
49pub const DEFAULT_MAX_DEPTH: usize = 8;
58
59pub const DEFAULT_MAX_TOTAL_ITEMS: usize = 1024;
67
68#[derive(Debug, Clone, Copy)]
74pub struct ParseOptions {
75 pub max_key_len: usize,
77 pub max_collection_elements: usize,
79 pub max_bulk_string_len: usize,
81 pub max_depth: usize,
83 pub max_total_items: usize,
89}
90
91impl Default for ParseOptions {
92 fn default() -> Self {
93 Self {
94 max_key_len: DEFAULT_MAX_KEY_LEN,
95 max_collection_elements: DEFAULT_MAX_COLLECTION_ELEMENTS,
96 max_bulk_string_len: DEFAULT_MAX_BULK_STRING_LEN,
97 max_depth: DEFAULT_MAX_DEPTH,
98 max_total_items: DEFAULT_MAX_TOTAL_ITEMS,
99 }
100 }
101}
102
103impl ParseOptions {
104 pub const fn new() -> Self {
106 Self {
107 max_key_len: DEFAULT_MAX_KEY_LEN,
108 max_collection_elements: DEFAULT_MAX_COLLECTION_ELEMENTS,
109 max_bulk_string_len: DEFAULT_MAX_BULK_STRING_LEN,
110 max_depth: DEFAULT_MAX_DEPTH,
111 max_total_items: DEFAULT_MAX_TOTAL_ITEMS,
112 }
113 }
114
115 pub const fn max_key_len(mut self, len: usize) -> Self {
117 self.max_key_len = len;
118 self
119 }
120
121 pub const fn max_collection_elements(mut self, count: usize) -> Self {
123 self.max_collection_elements = count;
124 self
125 }
126
127 pub const fn max_bulk_string_len(mut self, len: usize) -> Self {
129 self.max_bulk_string_len = len;
130 self
131 }
132
133 pub const fn max_depth(mut self, depth: usize) -> Self {
135 self.max_depth = depth;
136 self
137 }
138
139 pub const fn max_total_items(mut self, count: usize) -> Self {
141 self.max_total_items = count;
142 self
143 }
144}
145
146#[derive(Debug, Clone, PartialEq)]
151pub enum Value {
152 SimpleString(Bytes),
154 Error(Bytes),
156 Integer(i64),
158 BulkString(Bytes),
160 Null,
164 Array(Vec<Value>),
166
167 #[cfg(feature = "resp3")]
172 Boolean(bool),
173 #[cfg(feature = "resp3")]
175 Double(f64),
176 #[cfg(feature = "resp3")]
179 BigNumber(Bytes),
180 #[cfg(feature = "resp3")]
182 BulkError(Bytes),
183 #[cfg(feature = "resp3")]
186 VerbatimString {
187 format: [u8; 3],
189 data: Bytes,
191 },
192 #[cfg(feature = "resp3")]
194 Map(Vec<(Value, Value)>),
195 #[cfg(feature = "resp3")]
197 Set(Vec<Value>),
198 #[cfg(feature = "resp3")]
200 Push(Vec<Value>),
201 #[cfg(feature = "resp3")]
203 Attribute {
204 attrs: Vec<(Value, Value)>,
206 value: Box<Value>,
208 },
209}
210
211impl Value {
212 #[inline]
218 pub fn simple_string(s: &[u8]) -> Self {
219 Value::SimpleString(Bytes::copy_from_slice(s))
220 }
221
222 #[inline]
224 pub fn error(msg: &[u8]) -> Self {
225 Value::Error(Bytes::copy_from_slice(msg))
226 }
227
228 #[inline]
230 pub fn integer(n: i64) -> Self {
231 Value::Integer(n)
232 }
233
234 #[inline]
236 pub fn bulk_string(data: &[u8]) -> Self {
237 Value::BulkString(Bytes::copy_from_slice(data))
238 }
239
240 #[inline]
242 pub fn null() -> Self {
243 Value::Null
244 }
245
246 #[inline]
248 pub fn array(elements: Vec<Value>) -> Self {
249 Value::Array(elements)
250 }
251
252 #[cfg(feature = "resp3")]
256 #[inline]
257 pub fn boolean(b: bool) -> Self {
258 Value::Boolean(b)
259 }
260
261 #[cfg(feature = "resp3")]
263 #[inline]
264 pub fn double(d: f64) -> Self {
265 Value::Double(d)
266 }
267
268 #[cfg(feature = "resp3")]
270 #[inline]
271 pub fn big_number(num: &[u8]) -> Self {
272 Value::BigNumber(Bytes::copy_from_slice(num))
273 }
274
275 #[cfg(feature = "resp3")]
277 #[inline]
278 pub fn bulk_error(msg: &[u8]) -> Self {
279 Value::BulkError(Bytes::copy_from_slice(msg))
280 }
281
282 #[cfg(feature = "resp3")]
284 #[inline]
285 pub fn verbatim_string(format: [u8; 3], data: &[u8]) -> Self {
286 Value::VerbatimString {
287 format,
288 data: Bytes::copy_from_slice(data),
289 }
290 }
291
292 #[cfg(feature = "resp3")]
294 #[inline]
295 pub fn map(entries: Vec<(Value, Value)>) -> Self {
296 Value::Map(entries)
297 }
298
299 #[cfg(feature = "resp3")]
301 #[inline]
302 pub fn set(elements: Vec<Value>) -> Self {
303 Value::Set(elements)
304 }
305
306 #[cfg(feature = "resp3")]
308 #[inline]
309 pub fn push(elements: Vec<Value>) -> Self {
310 Value::Push(elements)
311 }
312
313 #[cfg(feature = "resp3")]
315 #[inline]
316 pub fn attribute(attrs: Vec<(Value, Value)>, value: Value) -> Self {
317 Value::Attribute {
318 attrs,
319 value: Box::new(value),
320 }
321 }
322
323 #[inline]
329 pub fn is_null(&self) -> bool {
330 matches!(self, Value::Null)
331 }
332
333 #[inline]
335 pub fn is_error(&self) -> bool {
336 matches!(self, Value::Error(_))
337 }
338
339 #[inline]
341 pub fn is_simple_string(&self) -> bool {
342 matches!(self, Value::SimpleString(_))
343 }
344
345 #[inline]
347 pub fn is_bulk_string(&self) -> bool {
348 matches!(self, Value::BulkString(_))
349 }
350
351 #[inline]
353 pub fn is_integer(&self) -> bool {
354 matches!(self, Value::Integer(_))
355 }
356
357 #[inline]
359 pub fn is_array(&self) -> bool {
360 matches!(self, Value::Array(_))
361 }
362
363 #[cfg(feature = "resp3")]
367 #[inline]
368 pub fn is_boolean(&self) -> bool {
369 matches!(self, Value::Boolean(_))
370 }
371
372 #[cfg(feature = "resp3")]
374 #[inline]
375 pub fn is_double(&self) -> bool {
376 matches!(self, Value::Double(_))
377 }
378
379 #[cfg(feature = "resp3")]
381 #[inline]
382 pub fn is_big_number(&self) -> bool {
383 matches!(self, Value::BigNumber(_))
384 }
385
386 #[cfg(feature = "resp3")]
388 #[inline]
389 pub fn is_bulk_error(&self) -> bool {
390 matches!(self, Value::BulkError(_))
391 }
392
393 #[cfg(feature = "resp3")]
395 #[inline]
396 pub fn is_verbatim_string(&self) -> bool {
397 matches!(self, Value::VerbatimString { .. })
398 }
399
400 #[cfg(feature = "resp3")]
402 #[inline]
403 pub fn is_map(&self) -> bool {
404 matches!(self, Value::Map(_))
405 }
406
407 #[cfg(feature = "resp3")]
409 #[inline]
410 pub fn is_set(&self) -> bool {
411 matches!(self, Value::Set(_))
412 }
413
414 #[cfg(feature = "resp3")]
416 #[inline]
417 pub fn is_push(&self) -> bool {
418 matches!(self, Value::Push(_))
419 }
420
421 #[cfg(feature = "resp3")]
423 #[inline]
424 pub fn is_attribute(&self) -> bool {
425 matches!(self, Value::Attribute { .. })
426 }
427
428 #[inline]
434 pub fn as_bytes(&self) -> Option<&[u8]> {
435 match self {
436 Value::SimpleString(s) | Value::BulkString(s) | Value::Error(s) => Some(s),
437 _ => None,
438 }
439 }
440
441 #[inline]
443 pub fn as_integer(&self) -> Option<i64> {
444 match self {
445 Value::Integer(i) => Some(*i),
446 _ => None,
447 }
448 }
449
450 #[inline]
452 pub fn as_array(&self) -> Option<&[Value]> {
453 match self {
454 Value::Array(arr) => Some(arr),
455 _ => None,
456 }
457 }
458
459 #[cfg(feature = "resp3")]
463 #[inline]
464 pub fn as_bool(&self) -> Option<bool> {
465 match self {
466 Value::Boolean(b) => Some(*b),
467 _ => None,
468 }
469 }
470
471 #[cfg(feature = "resp3")]
473 #[inline]
474 pub fn as_double(&self) -> Option<f64> {
475 match self {
476 Value::Double(d) => Some(*d),
477 _ => None,
478 }
479 }
480
481 #[cfg(feature = "resp3")]
483 #[inline]
484 pub fn as_big_number(&self) -> Option<&[u8]> {
485 match self {
486 Value::BigNumber(n) => Some(n),
487 _ => None,
488 }
489 }
490
491 #[cfg(feature = "resp3")]
493 #[inline]
494 pub fn as_map(&self) -> Option<&[(Value, Value)]> {
495 match self {
496 Value::Map(m) => Some(m),
497 _ => None,
498 }
499 }
500
501 #[cfg(feature = "resp3")]
503 #[inline]
504 pub fn as_set(&self) -> Option<&[Value]> {
505 match self {
506 Value::Set(s) => Some(s),
507 _ => None,
508 }
509 }
510
511 #[cfg(feature = "resp3")]
513 #[inline]
514 pub fn as_push(&self) -> Option<&[Value]> {
515 match self {
516 Value::Push(p) => Some(p),
517 _ => None,
518 }
519 }
520
521 #[cfg(feature = "resp3")]
523 #[inline]
524 pub fn as_verbatim_string(&self) -> Option<(&[u8; 3], &[u8])> {
525 match self {
526 Value::VerbatimString { format, data } => Some((format, data)),
527 _ => None,
528 }
529 }
530
531 #[inline]
544 pub fn parse(data: &[u8]) -> Result<(Self, usize), ParseError> {
545 Self::parse_with_options(data, &ParseOptions::default())
546 }
547
548 pub fn parse_with_options(
553 data: &[u8],
554 options: &ParseOptions,
555 ) -> Result<(Self, usize), ParseError> {
556 let mut total_items = 0;
557 Self::parse_internal(data, options, 0, &mut total_items)
558 }
559
560 #[inline]
566 pub fn parse_bytes(data: Bytes) -> Result<(Self, usize), ParseError> {
567 Self::parse_bytes_with_options(data, &ParseOptions::default())
568 }
569
570 pub fn parse_bytes_with_options(
572 data: Bytes,
573 options: &ParseOptions,
574 ) -> Result<(Self, usize), ParseError> {
575 let mut total_items = 0;
576 Self::parse_bytes_internal(&data, options, 0, &mut total_items)
577 }
578
579 fn parse_bytes_internal(
581 data: &Bytes,
582 options: &ParseOptions,
583 depth: usize,
584 total_items: &mut usize,
585 ) -> Result<(Self, usize), ParseError> {
586 if data.is_empty() {
587 return Err(ParseError::Incomplete);
588 }
589
590 match data[0] {
591 b'+' => parse_simple_string_bytes(data),
592 b'-' => parse_error_bytes(data),
593 b':' => parse_integer(&data[..]),
594 b'$' => parse_bulk_string_bytes(data, options),
595 b'*' => parse_array_bytes(data, options, depth, total_items),
596 #[cfg(feature = "resp3")]
597 b'_' => parse_null(&data[..]),
598 #[cfg(feature = "resp3")]
599 b'#' => parse_boolean(&data[..]),
600 #[cfg(feature = "resp3")]
601 b',' => parse_double(&data[..]),
602 #[cfg(feature = "resp3")]
603 b'(' => parse_big_number_bytes(data),
604 #[cfg(feature = "resp3")]
605 b'!' => parse_bulk_error_bytes(data, options),
606 #[cfg(feature = "resp3")]
607 b'=' => parse_verbatim_string_bytes(data, options),
608 #[cfg(feature = "resp3")]
609 b'%' => parse_map_bytes(data, options, depth, total_items),
610 #[cfg(feature = "resp3")]
611 b'~' => parse_set_bytes(data, options, depth, total_items),
612 #[cfg(feature = "resp3")]
613 b'>' => parse_push_bytes(data, options, depth, total_items),
614 #[cfg(feature = "resp3")]
615 b'|' => parse_attribute_bytes(data, options, depth, total_items),
616 other => Err(ParseError::InvalidPrefix(other)),
617 }
618 }
619
620 fn parse_internal(
622 data: &[u8],
623 options: &ParseOptions,
624 depth: usize,
625 total_items: &mut usize,
626 ) -> Result<(Self, usize), ParseError> {
627 if data.is_empty() {
628 return Err(ParseError::Incomplete);
629 }
630
631 match data[0] {
632 b'+' => parse_simple_string(data),
634 b'-' => parse_error(data),
635 b':' => parse_integer(data),
636 b'$' => parse_bulk_string(data, options),
637 b'*' => parse_array(data, options, depth, total_items),
638 #[cfg(feature = "resp3")]
640 b'_' => parse_null(data),
641 #[cfg(feature = "resp3")]
642 b'#' => parse_boolean(data),
643 #[cfg(feature = "resp3")]
644 b',' => parse_double(data),
645 #[cfg(feature = "resp3")]
646 b'(' => parse_big_number(data),
647 #[cfg(feature = "resp3")]
648 b'!' => parse_bulk_error(data, options),
649 #[cfg(feature = "resp3")]
650 b'=' => parse_verbatim_string(data, options),
651 #[cfg(feature = "resp3")]
652 b'%' => parse_map(data, options, depth, total_items),
653 #[cfg(feature = "resp3")]
654 b'~' => parse_set(data, options, depth, total_items),
655 #[cfg(feature = "resp3")]
656 b'>' => parse_push(data, options, depth, total_items),
657 #[cfg(feature = "resp3")]
658 b'|' => parse_attribute(data, options, depth, total_items),
659 other => Err(ParseError::InvalidPrefix(other)),
660 }
661 }
662
663 #[inline]
675 pub fn encode(&self, buf: &mut [u8]) -> usize {
676 match self {
677 Value::SimpleString(s) => encode_simple_string(buf, s),
678 Value::Error(msg) => encode_error(buf, msg),
679 Value::Integer(n) => encode_integer(buf, *n),
680 Value::BulkString(data) => encode_bulk_string(buf, data),
681 Value::Null => encode_resp2_null(buf),
682 Value::Array(elements) => encode_array(buf, elements),
683 #[cfg(feature = "resp3")]
684 Value::Boolean(b) => encode_boolean(buf, *b),
685 #[cfg(feature = "resp3")]
686 Value::Double(d) => encode_double(buf, *d),
687 #[cfg(feature = "resp3")]
688 Value::BigNumber(n) => encode_big_number(buf, n),
689 #[cfg(feature = "resp3")]
690 Value::BulkError(msg) => encode_bulk_error(buf, msg),
691 #[cfg(feature = "resp3")]
692 Value::VerbatimString { format, data } => encode_verbatim_string(buf, format, data),
693 #[cfg(feature = "resp3")]
694 Value::Map(entries) => encode_map(buf, entries),
695 #[cfg(feature = "resp3")]
696 Value::Set(elements) => encode_set(buf, elements),
697 #[cfg(feature = "resp3")]
698 Value::Push(elements) => encode_push(buf, elements),
699 #[cfg(feature = "resp3")]
700 Value::Attribute { attrs, value } => encode_attribute(buf, attrs, value),
701 }
702 }
703
704 pub fn encoded_len(&self) -> usize {
706 match self {
707 Value::SimpleString(s) => 1 + s.len() + 2, Value::Error(msg) => 1 + msg.len() + 2, Value::Integer(n) => {
710 let mut buf = itoa::Buffer::new();
711 1 + buf.format(*n).len() + 2 }
713 Value::BulkString(data) => {
714 let mut buf = itoa::Buffer::new();
715 1 + buf.format(data.len()).len() + 2 + data.len() + 2 }
717 Value::Null => 5, Value::Array(elements) => {
719 let mut buf = itoa::Buffer::new();
720 let header_len = 1 + buf.format(elements.len()).len() + 2;
721 header_len + elements.iter().map(|e| e.encoded_len()).sum::<usize>()
722 }
723 #[cfg(feature = "resp3")]
725 Value::Boolean(_) => 4, #[cfg(feature = "resp3")]
727 Value::Double(d) => {
728 let mut buf = ryu::Buffer::new();
730 1 + buf.format(*d).len() + 2
731 }
732 #[cfg(feature = "resp3")]
733 Value::BigNumber(n) => 1 + n.len() + 2, #[cfg(feature = "resp3")]
735 Value::BulkError(msg) => {
736 let mut buf = itoa::Buffer::new();
737 1 + buf.format(msg.len()).len() + 2 + msg.len() + 2 }
739 #[cfg(feature = "resp3")]
740 Value::VerbatimString { data, .. } => {
741 let mut buf = itoa::Buffer::new();
742 let total_len = 4 + data.len(); 1 + buf.format(total_len).len() + 2 + total_len + 2
745 }
746 #[cfg(feature = "resp3")]
747 Value::Map(entries) => {
748 let mut buf = itoa::Buffer::new();
749 let header_len = 1 + buf.format(entries.len()).len() + 2;
750 header_len
751 + entries
752 .iter()
753 .map(|(k, v)| k.encoded_len() + v.encoded_len())
754 .sum::<usize>()
755 }
756 #[cfg(feature = "resp3")]
757 Value::Set(elements) => {
758 let mut buf = itoa::Buffer::new();
759 let header_len = 1 + buf.format(elements.len()).len() + 2;
760 header_len + elements.iter().map(|e| e.encoded_len()).sum::<usize>()
761 }
762 #[cfg(feature = "resp3")]
763 Value::Push(elements) => {
764 let mut buf = itoa::Buffer::new();
765 let header_len = 1 + buf.format(elements.len()).len() + 2;
766 header_len + elements.iter().map(|e| e.encoded_len()).sum::<usize>()
767 }
768 #[cfg(feature = "resp3")]
769 Value::Attribute { attrs, value } => {
770 let mut buf = itoa::Buffer::new();
771 let header_len = 1 + buf.format(attrs.len()).len() + 2;
772 let attrs_len = attrs
773 .iter()
774 .map(|(k, v)| k.encoded_len() + v.encoded_len())
775 .sum::<usize>();
776 header_len + attrs_len + value.encoded_len()
777 }
778 }
779 }
780
781 #[cfg(feature = "resp3")]
783 #[inline]
784 pub fn encode_resp3_null(buf: &mut [u8]) -> usize {
785 buf[..3].copy_from_slice(b"_\r\n");
786 3
787 }
788}
789
790#[inline]
796fn find_crlf(data: &[u8]) -> Option<usize> {
797 memchr::memchr(b'\r', data).and_then(|pos| {
798 if pos + 1 < data.len() && data[pos + 1] == b'\n' {
799 Some(pos)
800 } else {
801 None
802 }
803 })
804}
805
806fn parse_simple_string(data: &[u8]) -> Result<(Value, usize), ParseError> {
808 let end = find_crlf(data).ok_or(ParseError::Incomplete)?;
809 let content = Bytes::copy_from_slice(&data[1..end]);
810 Ok((Value::SimpleString(content), end + 2))
811}
812
813fn parse_error(data: &[u8]) -> Result<(Value, usize), ParseError> {
815 let end = find_crlf(data).ok_or(ParseError::Incomplete)?;
816 let content = Bytes::copy_from_slice(&data[1..end]);
817 Ok((Value::Error(content), end + 2))
818}
819
820fn parse_integer(data: &[u8]) -> Result<(Value, usize), ParseError> {
822 let end = find_crlf(data).ok_or(ParseError::Incomplete)?;
823 let s = std::str::from_utf8(&data[1..end])
824 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
825 let value: i64 = s
826 .parse()
827 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
828 Ok((Value::Integer(value), end + 2))
829}
830
831fn parse_bulk_string(data: &[u8], options: &ParseOptions) -> Result<(Value, usize), ParseError> {
833 let len_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
834 let len_str = std::str::from_utf8(&data[1..len_end])
835 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
836 let len: i64 = len_str
837 .parse()
838 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
839
840 if len < 0 {
841 return Ok((Value::Null, len_end + 2));
843 }
844
845 let len = len as usize;
846 if len > options.max_bulk_string_len {
847 return Err(ParseError::Protocol("bulk string too large".to_string()));
848 }
849
850 let data_start = len_end + 2;
851 let data_end = data_start
852 .checked_add(len)
853 .ok_or_else(|| ParseError::InvalidInteger("length overflow".to_string()))?;
854 let total_end = data_end
855 .checked_add(2)
856 .ok_or_else(|| ParseError::InvalidInteger("length overflow".to_string()))?;
857
858 if data.len() < total_end {
859 return Err(ParseError::Incomplete);
860 }
861
862 if data[data_end] != b'\r' || data[data_end + 1] != b'\n' {
864 return Err(ParseError::Protocol("missing trailing CRLF".to_string()));
865 }
866
867 let content = Bytes::copy_from_slice(&data[data_start..data_end]);
868 Ok((Value::BulkString(content), total_end))
869}
870
871fn parse_array(
873 data: &[u8],
874 options: &ParseOptions,
875 depth: usize,
876 total_items: &mut usize,
877) -> Result<(Value, usize), ParseError> {
878 if depth >= options.max_depth {
879 return Err(ParseError::NestingTooDeep(depth));
880 }
881
882 let len_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
883 let len_str = std::str::from_utf8(&data[1..len_end])
884 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
885 let len: i64 = len_str
886 .parse()
887 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
888
889 if len < 0 {
890 return Ok((Value::Null, len_end + 2));
892 }
893
894 let len = len as usize;
895 if len > options.max_collection_elements {
896 return Err(ParseError::CollectionTooLarge(len));
897 }
898
899 *total_items = total_items
901 .checked_add(len)
902 .ok_or(ParseError::CollectionTooLarge(usize::MAX))?;
903 if *total_items > options.max_total_items {
904 return Err(ParseError::CollectionTooLarge(*total_items));
905 }
906
907 let mut pos = len_end + 2;
908 let mut elements = Vec::with_capacity(len);
909
910 for _ in 0..len {
911 if pos >= data.len() {
912 return Err(ParseError::Incomplete);
913 }
914 let (value, consumed) =
915 Value::parse_internal(&data[pos..], options, depth + 1, total_items)?;
916 elements.push(value);
917 pos += consumed;
918 }
919
920 Ok((Value::Array(elements), pos))
921}
922
923fn parse_simple_string_bytes(data: &Bytes) -> Result<(Value, usize), ParseError> {
929 let end = find_crlf(data).ok_or(ParseError::Incomplete)?;
930 let content = data.slice(1..end);
931 Ok((Value::SimpleString(content), end + 2))
932}
933
934fn parse_error_bytes(data: &Bytes) -> Result<(Value, usize), ParseError> {
936 let end = find_crlf(data).ok_or(ParseError::Incomplete)?;
937 let content = data.slice(1..end);
938 Ok((Value::Error(content), end + 2))
939}
940
941fn parse_bulk_string_bytes(
943 data: &Bytes,
944 options: &ParseOptions,
945) -> Result<(Value, usize), ParseError> {
946 let len_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
947 let len_str = std::str::from_utf8(&data[1..len_end])
948 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
949 let len: i64 = len_str
950 .parse()
951 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
952
953 if len < 0 {
954 return Ok((Value::Null, len_end + 2));
955 }
956
957 let len = len as usize;
958 if len > options.max_bulk_string_len {
959 return Err(ParseError::Protocol("bulk string too large".to_string()));
960 }
961
962 let data_start = len_end + 2;
963 let data_end = data_start
964 .checked_add(len)
965 .ok_or_else(|| ParseError::InvalidInteger("length overflow".to_string()))?;
966 let total_end = data_end
967 .checked_add(2)
968 .ok_or_else(|| ParseError::InvalidInteger("length overflow".to_string()))?;
969
970 if data.len() < total_end {
971 return Err(ParseError::Incomplete);
972 }
973
974 if data[data_end] != b'\r' || data[data_end + 1] != b'\n' {
975 return Err(ParseError::Protocol("missing trailing CRLF".to_string()));
976 }
977
978 let content = data.slice(data_start..data_end);
979 Ok((Value::BulkString(content), total_end))
980}
981
982fn parse_array_bytes(
984 data: &Bytes,
985 options: &ParseOptions,
986 depth: usize,
987 total_items: &mut usize,
988) -> Result<(Value, usize), ParseError> {
989 if depth >= options.max_depth {
990 return Err(ParseError::NestingTooDeep(depth));
991 }
992
993 let len_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
994 let len_str = std::str::from_utf8(&data[1..len_end])
995 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
996 let len: i64 = len_str
997 .parse()
998 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
999
1000 if len < 0 {
1001 return Ok((Value::Null, len_end + 2));
1002 }
1003
1004 let len = len as usize;
1005 if len > options.max_collection_elements {
1006 return Err(ParseError::CollectionTooLarge(len));
1007 }
1008
1009 *total_items = total_items
1010 .checked_add(len)
1011 .ok_or(ParseError::CollectionTooLarge(usize::MAX))?;
1012 if *total_items > options.max_total_items {
1013 return Err(ParseError::CollectionTooLarge(*total_items));
1014 }
1015
1016 let mut pos = len_end + 2;
1017 let mut elements = Vec::with_capacity(len);
1018
1019 for _ in 0..len {
1020 if pos >= data.len() {
1021 return Err(ParseError::Incomplete);
1022 }
1023 let sub = data.slice(pos..);
1024 let (value, consumed) = Value::parse_bytes_internal(&sub, options, depth + 1, total_items)?;
1025 elements.push(value);
1026 pos += consumed;
1027 }
1028
1029 Ok((Value::Array(elements), pos))
1030}
1031
1032#[cfg(feature = "resp3")]
1034fn parse_big_number_bytes(data: &Bytes) -> Result<(Value, usize), ParseError> {
1035 let end = find_crlf(data).ok_or(ParseError::Incomplete)?;
1036 let content = data.slice(1..end);
1037 Ok((Value::BigNumber(content), end + 2))
1038}
1039
1040#[cfg(feature = "resp3")]
1042fn parse_bulk_error_bytes(
1043 data: &Bytes,
1044 options: &ParseOptions,
1045) -> Result<(Value, usize), ParseError> {
1046 let len_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
1047 let len_str = std::str::from_utf8(&data[1..len_end])
1048 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
1049 let len: usize = len_str
1050 .parse()
1051 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
1052
1053 if len > options.max_bulk_string_len {
1054 return Err(ParseError::Protocol("bulk error too large".to_string()));
1055 }
1056
1057 let data_start = len_end + 2;
1058 let data_end = data_start
1059 .checked_add(len)
1060 .ok_or_else(|| ParseError::InvalidInteger("length overflow".to_string()))?;
1061 let total_end = data_end
1062 .checked_add(2)
1063 .ok_or_else(|| ParseError::InvalidInteger("length overflow".to_string()))?;
1064
1065 if data.len() < total_end {
1066 return Err(ParseError::Incomplete);
1067 }
1068
1069 if data[data_end] != b'\r' || data[data_end + 1] != b'\n' {
1070 return Err(ParseError::Protocol("missing trailing CRLF".to_string()));
1071 }
1072
1073 let content = data.slice(data_start..data_end);
1074 Ok((Value::BulkError(content), total_end))
1075}
1076
1077#[cfg(feature = "resp3")]
1079fn parse_verbatim_string_bytes(
1080 data: &Bytes,
1081 options: &ParseOptions,
1082) -> Result<(Value, usize), ParseError> {
1083 let len_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
1084 let len_str = std::str::from_utf8(&data[1..len_end])
1085 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
1086 let len: usize = len_str
1087 .parse()
1088 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
1089
1090 if len > options.max_bulk_string_len {
1091 return Err(ParseError::Protocol(
1092 "verbatim string too large".to_string(),
1093 ));
1094 }
1095
1096 let data_start = len_end + 2;
1097 let data_end = data_start
1098 .checked_add(len)
1099 .ok_or_else(|| ParseError::InvalidInteger("length overflow".to_string()))?;
1100 let total_end = data_end
1101 .checked_add(2)
1102 .ok_or_else(|| ParseError::InvalidInteger("length overflow".to_string()))?;
1103
1104 if data.len() < total_end {
1105 return Err(ParseError::Incomplete);
1106 }
1107
1108 if len < 4 || data[data_start + 3] != b':' {
1109 return Err(ParseError::InvalidVerbatimFormat);
1110 }
1111
1112 if data[data_end] != b'\r' || data[data_end + 1] != b'\n' {
1113 return Err(ParseError::Protocol("missing trailing CRLF".to_string()));
1114 }
1115
1116 let format: [u8; 3] = data[data_start..data_start + 3]
1117 .try_into()
1118 .map_err(|_| ParseError::InvalidVerbatimFormat)?;
1119 let content = data.slice(data_start + 4..data_end);
1120
1121 Ok((
1122 Value::VerbatimString {
1123 format,
1124 data: content,
1125 },
1126 total_end,
1127 ))
1128}
1129
1130#[cfg(feature = "resp3")]
1132fn parse_map_bytes(
1133 data: &Bytes,
1134 options: &ParseOptions,
1135 depth: usize,
1136 total_items: &mut usize,
1137) -> Result<(Value, usize), ParseError> {
1138 if depth >= options.max_depth {
1139 return Err(ParseError::NestingTooDeep(depth));
1140 }
1141
1142 let len_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
1143 let len_str = std::str::from_utf8(&data[1..len_end])
1144 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
1145 let len: usize = len_str
1146 .parse()
1147 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
1148
1149 if len > options.max_collection_elements {
1150 return Err(ParseError::CollectionTooLarge(len));
1151 }
1152
1153 let items_to_add = len
1154 .checked_mul(2)
1155 .ok_or(ParseError::CollectionTooLarge(usize::MAX))?;
1156 *total_items = total_items
1157 .checked_add(items_to_add)
1158 .ok_or(ParseError::CollectionTooLarge(usize::MAX))?;
1159 if *total_items > options.max_total_items {
1160 return Err(ParseError::CollectionTooLarge(*total_items));
1161 }
1162
1163 let mut pos = len_end + 2;
1164 let mut entries = Vec::with_capacity(len);
1165
1166 for _ in 0..len {
1167 if pos >= data.len() {
1168 return Err(ParseError::Incomplete);
1169 }
1170 let sub = data.slice(pos..);
1171 let (key, key_consumed) =
1172 Value::parse_bytes_internal(&sub, options, depth + 1, total_items)?;
1173 pos += key_consumed;
1174
1175 if pos >= data.len() {
1176 return Err(ParseError::Incomplete);
1177 }
1178 let sub = data.slice(pos..);
1179 let (value, val_consumed) =
1180 Value::parse_bytes_internal(&sub, options, depth + 1, total_items)?;
1181 pos += val_consumed;
1182
1183 entries.push((key, value));
1184 }
1185
1186 Ok((Value::Map(entries), pos))
1187}
1188
1189#[cfg(feature = "resp3")]
1191fn parse_set_bytes(
1192 data: &Bytes,
1193 options: &ParseOptions,
1194 depth: usize,
1195 total_items: &mut usize,
1196) -> Result<(Value, usize), ParseError> {
1197 if depth >= options.max_depth {
1198 return Err(ParseError::NestingTooDeep(depth));
1199 }
1200
1201 let len_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
1202 let len_str = std::str::from_utf8(&data[1..len_end])
1203 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
1204 let len: usize = len_str
1205 .parse()
1206 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
1207
1208 if len > options.max_collection_elements {
1209 return Err(ParseError::CollectionTooLarge(len));
1210 }
1211
1212 *total_items = total_items
1213 .checked_add(len)
1214 .ok_or(ParseError::CollectionTooLarge(usize::MAX))?;
1215 if *total_items > options.max_total_items {
1216 return Err(ParseError::CollectionTooLarge(*total_items));
1217 }
1218
1219 let mut pos = len_end + 2;
1220 let mut elements = Vec::with_capacity(len);
1221
1222 for _ in 0..len {
1223 if pos >= data.len() {
1224 return Err(ParseError::Incomplete);
1225 }
1226 let sub = data.slice(pos..);
1227 let (value, consumed) = Value::parse_bytes_internal(&sub, options, depth + 1, total_items)?;
1228 elements.push(value);
1229 pos += consumed;
1230 }
1231
1232 Ok((Value::Set(elements), pos))
1233}
1234
1235#[cfg(feature = "resp3")]
1237fn parse_push_bytes(
1238 data: &Bytes,
1239 options: &ParseOptions,
1240 depth: usize,
1241 total_items: &mut usize,
1242) -> Result<(Value, usize), ParseError> {
1243 if depth >= options.max_depth {
1244 return Err(ParseError::NestingTooDeep(depth));
1245 }
1246
1247 let len_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
1248 let len_str = std::str::from_utf8(&data[1..len_end])
1249 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
1250 let len: usize = len_str
1251 .parse()
1252 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
1253
1254 if len > options.max_collection_elements {
1255 return Err(ParseError::CollectionTooLarge(len));
1256 }
1257
1258 *total_items = total_items
1259 .checked_add(len)
1260 .ok_or(ParseError::CollectionTooLarge(usize::MAX))?;
1261 if *total_items > options.max_total_items {
1262 return Err(ParseError::CollectionTooLarge(*total_items));
1263 }
1264
1265 let mut pos = len_end + 2;
1266 let mut elements = Vec::with_capacity(len);
1267
1268 for _ in 0..len {
1269 if pos >= data.len() {
1270 return Err(ParseError::Incomplete);
1271 }
1272 let sub = data.slice(pos..);
1273 let (value, consumed) = Value::parse_bytes_internal(&sub, options, depth + 1, total_items)?;
1274 elements.push(value);
1275 pos += consumed;
1276 }
1277
1278 Ok((Value::Push(elements), pos))
1279}
1280
1281#[cfg(feature = "resp3")]
1283fn parse_attribute_bytes(
1284 data: &Bytes,
1285 options: &ParseOptions,
1286 depth: usize,
1287 total_items: &mut usize,
1288) -> Result<(Value, usize), ParseError> {
1289 if depth >= options.max_depth {
1290 return Err(ParseError::NestingTooDeep(depth));
1291 }
1292
1293 let len_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
1294 let len_str = std::str::from_utf8(&data[1..len_end])
1295 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
1296 let len: usize = len_str
1297 .parse()
1298 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
1299
1300 if len > options.max_collection_elements {
1301 return Err(ParseError::CollectionTooLarge(len));
1302 }
1303
1304 let items_to_add = len
1305 .checked_mul(2)
1306 .and_then(|n| n.checked_add(1))
1307 .ok_or(ParseError::CollectionTooLarge(usize::MAX))?;
1308 *total_items = total_items
1309 .checked_add(items_to_add)
1310 .ok_or(ParseError::CollectionTooLarge(usize::MAX))?;
1311 if *total_items > options.max_total_items {
1312 return Err(ParseError::CollectionTooLarge(*total_items));
1313 }
1314
1315 let mut pos = len_end + 2;
1316 let mut attrs = Vec::with_capacity(len);
1317
1318 for _ in 0..len {
1319 if pos >= data.len() {
1320 return Err(ParseError::Incomplete);
1321 }
1322 let sub = data.slice(pos..);
1323 let (key, key_consumed) =
1324 Value::parse_bytes_internal(&sub, options, depth + 1, total_items)?;
1325 pos += key_consumed;
1326
1327 if pos >= data.len() {
1328 return Err(ParseError::Incomplete);
1329 }
1330 let sub = data.slice(pos..);
1331 let (val, val_consumed) =
1332 Value::parse_bytes_internal(&sub, options, depth + 1, total_items)?;
1333 pos += val_consumed;
1334
1335 attrs.push((key, val));
1336 }
1337
1338 if pos >= data.len() {
1339 return Err(ParseError::Incomplete);
1340 }
1341 let sub = data.slice(pos..);
1342 let (value, val_consumed) = Value::parse_bytes_internal(&sub, options, depth + 1, total_items)?;
1343 pos += val_consumed;
1344
1345 Ok((
1346 Value::Attribute {
1347 attrs,
1348 value: Box::new(value),
1349 },
1350 pos,
1351 ))
1352}
1353
1354fn encode_simple_string(buf: &mut [u8], s: &[u8]) -> usize {
1360 buf[0] = b'+';
1361 buf[1..1 + s.len()].copy_from_slice(s);
1362 buf[1 + s.len()] = b'\r';
1363 buf[2 + s.len()] = b'\n';
1364 3 + s.len()
1365}
1366
1367fn encode_error(buf: &mut [u8], msg: &[u8]) -> usize {
1369 buf[0] = b'-';
1370 buf[1..1 + msg.len()].copy_from_slice(msg);
1371 buf[1 + msg.len()] = b'\r';
1372 buf[2 + msg.len()] = b'\n';
1373 3 + msg.len()
1374}
1375
1376fn encode_integer(buf: &mut [u8], n: i64) -> usize {
1378 buf[0] = b':';
1379 let mut cursor = std::io::Cursor::new(&mut buf[1..]);
1380 write!(cursor, "{}\r\n", n).unwrap();
1381 1 + cursor.position() as usize
1382}
1383
1384fn encode_bulk_string(buf: &mut [u8], data: &[u8]) -> usize {
1386 buf[0] = b'$';
1387 let mut cursor = std::io::Cursor::new(&mut buf[1..]);
1388 write!(cursor, "{}\r\n", data.len()).unwrap();
1389 let header_len = 1 + cursor.position() as usize;
1390
1391 buf[header_len..header_len + data.len()].copy_from_slice(data);
1392 buf[header_len + data.len()] = b'\r';
1393 buf[header_len + data.len() + 1] = b'\n';
1394 header_len + data.len() + 2
1395}
1396
1397fn encode_resp2_null(buf: &mut [u8]) -> usize {
1399 buf[..5].copy_from_slice(b"$-1\r\n");
1400 5
1401}
1402
1403fn encode_array(buf: &mut [u8], elements: &[Value]) -> usize {
1405 buf[0] = b'*';
1406 let mut cursor = std::io::Cursor::new(&mut buf[1..]);
1407 write!(cursor, "{}\r\n", elements.len()).unwrap();
1408 let mut pos = 1 + cursor.position() as usize;
1409
1410 for element in elements {
1411 pos += element.encode(&mut buf[pos..]);
1412 }
1413 pos
1414}
1415
1416#[cfg(feature = "resp3")]
1422fn parse_null(data: &[u8]) -> Result<(Value, usize), ParseError> {
1423 if data.len() < 3 {
1424 return Err(ParseError::Incomplete);
1425 }
1426 if data[1] != b'\r' || data[2] != b'\n' {
1427 return Err(ParseError::Protocol("expected CRLF after null".to_string()));
1428 }
1429 Ok((Value::Null, 3))
1430}
1431
1432#[cfg(feature = "resp3")]
1434fn parse_boolean(data: &[u8]) -> Result<(Value, usize), ParseError> {
1435 if data.len() < 4 {
1436 return Err(ParseError::Incomplete);
1437 }
1438 let value = match data[1] {
1439 b't' => true,
1440 b'f' => false,
1441 _ => return Err(ParseError::InvalidBoolean),
1442 };
1443 if data[2] != b'\r' || data[3] != b'\n' {
1444 return Err(ParseError::Protocol(
1445 "expected CRLF after boolean".to_string(),
1446 ));
1447 }
1448 Ok((Value::Boolean(value), 4))
1449}
1450
1451#[cfg(feature = "resp3")]
1453fn parse_double(data: &[u8]) -> Result<(Value, usize), ParseError> {
1454 let end = find_crlf(data).ok_or(ParseError::Incomplete)?;
1455 let s =
1456 std::str::from_utf8(&data[1..end]).map_err(|e| ParseError::InvalidDouble(e.to_string()))?;
1457
1458 let value = match s {
1460 "inf" => f64::INFINITY,
1461 "-inf" => f64::NEG_INFINITY,
1462 "nan" => f64::NAN,
1463 _ => s
1464 .parse()
1465 .map_err(|e: std::num::ParseFloatError| ParseError::InvalidDouble(e.to_string()))?,
1466 };
1467 Ok((Value::Double(value), end + 2))
1468}
1469
1470#[cfg(feature = "resp3")]
1472fn parse_big_number(data: &[u8]) -> Result<(Value, usize), ParseError> {
1473 let end = find_crlf(data).ok_or(ParseError::Incomplete)?;
1474 let content = Bytes::copy_from_slice(&data[1..end]);
1475 Ok((Value::BigNumber(content), end + 2))
1476}
1477
1478#[cfg(feature = "resp3")]
1480fn parse_bulk_error(data: &[u8], options: &ParseOptions) -> Result<(Value, usize), ParseError> {
1481 let len_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
1482 let len_str = std::str::from_utf8(&data[1..len_end])
1483 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
1484 let len: usize = len_str
1485 .parse()
1486 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
1487
1488 if len > options.max_bulk_string_len {
1489 return Err(ParseError::Protocol("bulk error too large".to_string()));
1490 }
1491
1492 let data_start = len_end + 2;
1493 let data_end = data_start
1494 .checked_add(len)
1495 .ok_or_else(|| ParseError::InvalidInteger("length overflow".to_string()))?;
1496 let total_end = data_end
1497 .checked_add(2)
1498 .ok_or_else(|| ParseError::InvalidInteger("length overflow".to_string()))?;
1499
1500 if data.len() < total_end {
1501 return Err(ParseError::Incomplete);
1502 }
1503
1504 if data[data_end] != b'\r' || data[data_end + 1] != b'\n' {
1505 return Err(ParseError::Protocol("missing trailing CRLF".to_string()));
1506 }
1507
1508 let content = Bytes::copy_from_slice(&data[data_start..data_end]);
1509 Ok((Value::BulkError(content), total_end))
1510}
1511
1512#[cfg(feature = "resp3")]
1514fn parse_verbatim_string(
1515 data: &[u8],
1516 options: &ParseOptions,
1517) -> Result<(Value, usize), ParseError> {
1518 let len_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
1519 let len_str = std::str::from_utf8(&data[1..len_end])
1520 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
1521 let len: usize = len_str
1522 .parse()
1523 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
1524
1525 if len > options.max_bulk_string_len {
1526 return Err(ParseError::Protocol(
1527 "verbatim string too large".to_string(),
1528 ));
1529 }
1530
1531 let data_start = len_end + 2;
1532 let data_end = data_start
1533 .checked_add(len)
1534 .ok_or_else(|| ParseError::InvalidInteger("length overflow".to_string()))?;
1535 let total_end = data_end
1536 .checked_add(2)
1537 .ok_or_else(|| ParseError::InvalidInteger("length overflow".to_string()))?;
1538
1539 if data.len() < total_end {
1540 return Err(ParseError::Incomplete);
1541 }
1542
1543 if len < 4 || data[data_start + 3] != b':' {
1545 return Err(ParseError::InvalidVerbatimFormat);
1546 }
1547
1548 if data[data_end] != b'\r' || data[data_end + 1] != b'\n' {
1549 return Err(ParseError::Protocol("missing trailing CRLF".to_string()));
1550 }
1551
1552 let format: [u8; 3] = data[data_start..data_start + 3]
1553 .try_into()
1554 .map_err(|_| ParseError::InvalidVerbatimFormat)?;
1555 let content = Bytes::copy_from_slice(&data[data_start + 4..data_end]);
1556
1557 Ok((
1558 Value::VerbatimString {
1559 format,
1560 data: content,
1561 },
1562 total_end,
1563 ))
1564}
1565
1566#[cfg(feature = "resp3")]
1568fn parse_map(
1569 data: &[u8],
1570 options: &ParseOptions,
1571 depth: usize,
1572 total_items: &mut usize,
1573) -> Result<(Value, usize), ParseError> {
1574 if depth >= options.max_depth {
1575 return Err(ParseError::NestingTooDeep(depth));
1576 }
1577
1578 let len_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
1579 let len_str = std::str::from_utf8(&data[1..len_end])
1580 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
1581 let len: usize = len_str
1582 .parse()
1583 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
1584
1585 if len > options.max_collection_elements {
1586 return Err(ParseError::CollectionTooLarge(len));
1587 }
1588
1589 let items_to_add = len
1591 .checked_mul(2)
1592 .ok_or(ParseError::CollectionTooLarge(usize::MAX))?;
1593 *total_items = total_items
1594 .checked_add(items_to_add)
1595 .ok_or(ParseError::CollectionTooLarge(usize::MAX))?;
1596 if *total_items > options.max_total_items {
1597 return Err(ParseError::CollectionTooLarge(*total_items));
1598 }
1599
1600 let mut pos = len_end + 2;
1601 let mut entries = Vec::with_capacity(len);
1602
1603 for _ in 0..len {
1604 if pos >= data.len() {
1605 return Err(ParseError::Incomplete);
1606 }
1607 let (key, key_consumed) =
1608 Value::parse_internal(&data[pos..], options, depth + 1, total_items)?;
1609 pos += key_consumed;
1610
1611 if pos >= data.len() {
1612 return Err(ParseError::Incomplete);
1613 }
1614 let (value, val_consumed) =
1615 Value::parse_internal(&data[pos..], options, depth + 1, total_items)?;
1616 pos += val_consumed;
1617
1618 entries.push((key, value));
1619 }
1620
1621 Ok((Value::Map(entries), pos))
1622}
1623
1624#[cfg(feature = "resp3")]
1626fn parse_set(
1627 data: &[u8],
1628 options: &ParseOptions,
1629 depth: usize,
1630 total_items: &mut usize,
1631) -> Result<(Value, usize), ParseError> {
1632 if depth >= options.max_depth {
1633 return Err(ParseError::NestingTooDeep(depth));
1634 }
1635
1636 let len_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
1637 let len_str = std::str::from_utf8(&data[1..len_end])
1638 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
1639 let len: usize = len_str
1640 .parse()
1641 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
1642
1643 if len > options.max_collection_elements {
1644 return Err(ParseError::CollectionTooLarge(len));
1645 }
1646
1647 *total_items = total_items
1649 .checked_add(len)
1650 .ok_or(ParseError::CollectionTooLarge(usize::MAX))?;
1651 if *total_items > options.max_total_items {
1652 return Err(ParseError::CollectionTooLarge(*total_items));
1653 }
1654
1655 let mut pos = len_end + 2;
1656 let mut elements = Vec::with_capacity(len);
1657
1658 for _ in 0..len {
1659 if pos >= data.len() {
1660 return Err(ParseError::Incomplete);
1661 }
1662 let (value, consumed) =
1663 Value::parse_internal(&data[pos..], options, depth + 1, total_items)?;
1664 elements.push(value);
1665 pos += consumed;
1666 }
1667
1668 Ok((Value::Set(elements), pos))
1669}
1670
1671#[cfg(feature = "resp3")]
1673fn parse_push(
1674 data: &[u8],
1675 options: &ParseOptions,
1676 depth: usize,
1677 total_items: &mut usize,
1678) -> Result<(Value, usize), ParseError> {
1679 if depth >= options.max_depth {
1680 return Err(ParseError::NestingTooDeep(depth));
1681 }
1682
1683 let len_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
1684 let len_str = std::str::from_utf8(&data[1..len_end])
1685 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
1686 let len: usize = len_str
1687 .parse()
1688 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
1689
1690 if len > options.max_collection_elements {
1691 return Err(ParseError::CollectionTooLarge(len));
1692 }
1693
1694 *total_items = total_items
1696 .checked_add(len)
1697 .ok_or(ParseError::CollectionTooLarge(usize::MAX))?;
1698 if *total_items > options.max_total_items {
1699 return Err(ParseError::CollectionTooLarge(*total_items));
1700 }
1701
1702 let mut pos = len_end + 2;
1703 let mut elements = Vec::with_capacity(len);
1704
1705 for _ in 0..len {
1706 if pos >= data.len() {
1707 return Err(ParseError::Incomplete);
1708 }
1709 let (value, consumed) =
1710 Value::parse_internal(&data[pos..], options, depth + 1, total_items)?;
1711 elements.push(value);
1712 pos += consumed;
1713 }
1714
1715 Ok((Value::Push(elements), pos))
1716}
1717
1718#[cfg(feature = "resp3")]
1720fn parse_attribute(
1721 data: &[u8],
1722 options: &ParseOptions,
1723 depth: usize,
1724 total_items: &mut usize,
1725) -> Result<(Value, usize), ParseError> {
1726 if depth >= options.max_depth {
1727 return Err(ParseError::NestingTooDeep(depth));
1728 }
1729
1730 let len_end = find_crlf(data).ok_or(ParseError::Incomplete)?;
1731 let len_str = std::str::from_utf8(&data[1..len_end])
1732 .map_err(|e| ParseError::InvalidInteger(e.to_string()))?;
1733 let len: usize = len_str
1734 .parse()
1735 .map_err(|e: std::num::ParseIntError| ParseError::InvalidInteger(e.to_string()))?;
1736
1737 if len > options.max_collection_elements {
1738 return Err(ParseError::CollectionTooLarge(len));
1739 }
1740
1741 let items_to_add = len
1743 .checked_mul(2)
1744 .and_then(|n| n.checked_add(1))
1745 .ok_or(ParseError::CollectionTooLarge(usize::MAX))?;
1746 *total_items = total_items
1747 .checked_add(items_to_add)
1748 .ok_or(ParseError::CollectionTooLarge(usize::MAX))?;
1749 if *total_items > options.max_total_items {
1750 return Err(ParseError::CollectionTooLarge(*total_items));
1751 }
1752
1753 let mut pos = len_end + 2;
1754 let mut attrs = Vec::with_capacity(len);
1755
1756 for _ in 0..len {
1757 if pos >= data.len() {
1758 return Err(ParseError::Incomplete);
1759 }
1760 let (key, key_consumed) =
1761 Value::parse_internal(&data[pos..], options, depth + 1, total_items)?;
1762 pos += key_consumed;
1763
1764 if pos >= data.len() {
1765 return Err(ParseError::Incomplete);
1766 }
1767 let (val, val_consumed) =
1768 Value::parse_internal(&data[pos..], options, depth + 1, total_items)?;
1769 pos += val_consumed;
1770
1771 attrs.push((key, val));
1772 }
1773
1774 if pos >= data.len() {
1776 return Err(ParseError::Incomplete);
1777 }
1778 let (value, val_consumed) =
1779 Value::parse_internal(&data[pos..], options, depth + 1, total_items)?;
1780 pos += val_consumed;
1781
1782 Ok((
1783 Value::Attribute {
1784 attrs,
1785 value: Box::new(value),
1786 },
1787 pos,
1788 ))
1789}
1790
1791#[cfg(feature = "resp3")]
1797fn encode_boolean(buf: &mut [u8], b: bool) -> usize {
1798 buf[0] = b'#';
1799 buf[1] = if b { b't' } else { b'f' };
1800 buf[2] = b'\r';
1801 buf[3] = b'\n';
1802 4
1803}
1804
1805#[cfg(feature = "resp3")]
1807fn encode_double(buf: &mut [u8], d: f64) -> usize {
1808 buf[0] = b',';
1809 let s = if d.is_infinite() {
1810 if d.is_sign_positive() { "inf" } else { "-inf" }
1811 } else if d.is_nan() {
1812 "nan"
1813 } else {
1814 let mut ryu_buf = ryu::Buffer::new();
1816 let formatted = ryu_buf.format(d);
1817 buf[1..1 + formatted.len()].copy_from_slice(formatted.as_bytes());
1818 buf[1 + formatted.len()] = b'\r';
1819 buf[2 + formatted.len()] = b'\n';
1820 return 3 + formatted.len();
1821 };
1822 buf[1..1 + s.len()].copy_from_slice(s.as_bytes());
1823 buf[1 + s.len()] = b'\r';
1824 buf[2 + s.len()] = b'\n';
1825 3 + s.len()
1826}
1827
1828#[cfg(feature = "resp3")]
1830fn encode_big_number(buf: &mut [u8], n: &[u8]) -> usize {
1831 buf[0] = b'(';
1832 buf[1..1 + n.len()].copy_from_slice(n);
1833 buf[1 + n.len()] = b'\r';
1834 buf[2 + n.len()] = b'\n';
1835 3 + n.len()
1836}
1837
1838#[cfg(feature = "resp3")]
1840fn encode_bulk_error(buf: &mut [u8], msg: &[u8]) -> usize {
1841 buf[0] = b'!';
1842 let mut cursor = std::io::Cursor::new(&mut buf[1..]);
1843 write!(cursor, "{}\r\n", msg.len()).unwrap();
1844 let header_len = 1 + cursor.position() as usize;
1845
1846 buf[header_len..header_len + msg.len()].copy_from_slice(msg);
1847 buf[header_len + msg.len()] = b'\r';
1848 buf[header_len + msg.len() + 1] = b'\n';
1849 header_len + msg.len() + 2
1850}
1851
1852#[cfg(feature = "resp3")]
1854fn encode_verbatim_string(buf: &mut [u8], format: &[u8; 3], data: &[u8]) -> usize {
1855 buf[0] = b'=';
1856 let total_len = 4 + data.len(); let mut cursor = std::io::Cursor::new(&mut buf[1..]);
1858 write!(cursor, "{}\r\n", total_len).unwrap();
1859 let header_len = 1 + cursor.position() as usize;
1860
1861 buf[header_len..header_len + 3].copy_from_slice(format);
1862 buf[header_len + 3] = b':';
1863 buf[header_len + 4..header_len + 4 + data.len()].copy_from_slice(data);
1864 buf[header_len + 4 + data.len()] = b'\r';
1865 buf[header_len + 5 + data.len()] = b'\n';
1866 header_len + 6 + data.len()
1867}
1868
1869#[cfg(feature = "resp3")]
1871fn encode_map(buf: &mut [u8], entries: &[(Value, Value)]) -> usize {
1872 buf[0] = b'%';
1873 let mut cursor = std::io::Cursor::new(&mut buf[1..]);
1874 write!(cursor, "{}\r\n", entries.len()).unwrap();
1875 let mut pos = 1 + cursor.position() as usize;
1876
1877 for (key, value) in entries {
1878 pos += key.encode(&mut buf[pos..]);
1879 pos += value.encode(&mut buf[pos..]);
1880 }
1881 pos
1882}
1883
1884#[cfg(feature = "resp3")]
1886fn encode_set(buf: &mut [u8], elements: &[Value]) -> usize {
1887 buf[0] = b'~';
1888 let mut cursor = std::io::Cursor::new(&mut buf[1..]);
1889 write!(cursor, "{}\r\n", elements.len()).unwrap();
1890 let mut pos = 1 + cursor.position() as usize;
1891
1892 for element in elements {
1893 pos += element.encode(&mut buf[pos..]);
1894 }
1895 pos
1896}
1897
1898#[cfg(feature = "resp3")]
1900fn encode_push(buf: &mut [u8], elements: &[Value]) -> usize {
1901 buf[0] = b'>';
1902 let mut cursor = std::io::Cursor::new(&mut buf[1..]);
1903 write!(cursor, "{}\r\n", elements.len()).unwrap();
1904 let mut pos = 1 + cursor.position() as usize;
1905
1906 for element in elements {
1907 pos += element.encode(&mut buf[pos..]);
1908 }
1909 pos
1910}
1911
1912#[cfg(feature = "resp3")]
1914fn encode_attribute(buf: &mut [u8], attrs: &[(Value, Value)], value: &Value) -> usize {
1915 buf[0] = b'|';
1916 let mut cursor = std::io::Cursor::new(&mut buf[1..]);
1917 write!(cursor, "{}\r\n", attrs.len()).unwrap();
1918 let mut pos = 1 + cursor.position() as usize;
1919
1920 for (key, val) in attrs {
1921 pos += key.encode(&mut buf[pos..]);
1922 pos += val.encode(&mut buf[pos..]);
1923 }
1924 pos += value.encode(&mut buf[pos..]);
1925 pos
1926}
1927
1928impl Value {
1933 pub const OK: &'static [u8] = b"+OK\r\n";
1935
1936 pub const PONG: &'static [u8] = b"+PONG\r\n";
1938
1939 pub const NULL_BULK: &'static [u8] = b"$-1\r\n";
1941
1942 pub const EMPTY_ARRAY: &'static [u8] = b"*0\r\n";
1944
1945 #[inline]
1947 pub fn encode_ok(buf: &mut [u8]) -> usize {
1948 buf[..5].copy_from_slice(Self::OK);
1949 5
1950 }
1951
1952 #[inline]
1954 pub fn encode_pong(buf: &mut [u8]) -> usize {
1955 buf[..7].copy_from_slice(Self::PONG);
1956 7
1957 }
1958
1959 #[inline]
1961 pub fn encode_null_bulk(buf: &mut [u8]) -> usize {
1962 buf[..5].copy_from_slice(Self::NULL_BULK);
1963 5
1964 }
1965
1966 #[inline]
1968 pub fn encode_int(buf: &mut [u8], n: i64) -> usize {
1969 encode_integer(buf, n)
1970 }
1971
1972 #[inline]
1974 pub fn encode_bulk(buf: &mut [u8], data: &[u8]) -> usize {
1975 encode_bulk_string(buf, data)
1976 }
1977
1978 #[inline]
1980 pub fn encode_err(buf: &mut [u8], msg: &[u8]) -> usize {
1981 encode_error(buf, msg)
1982 }
1983}
1984
1985#[cfg(test)]
1986mod tests {
1987 use super::*;
1988
1989 #[test]
1990 fn test_parse_simple_string() {
1991 let (value, consumed) = Value::parse(b"+OK\r\n").unwrap();
1992 assert_eq!(value, Value::SimpleString(Bytes::from_static(b"OK")));
1993 assert_eq!(consumed, 5);
1994 }
1995
1996 #[test]
1997 fn test_parse_error() {
1998 let (value, consumed) = Value::parse(b"-ERR unknown command\r\n").unwrap();
1999 assert_eq!(
2000 value,
2001 Value::Error(Bytes::from_static(b"ERR unknown command"))
2002 );
2003 assert_eq!(consumed, 22);
2004 }
2005
2006 #[test]
2007 fn test_parse_integer() {
2008 let (value, consumed) = Value::parse(b":1000\r\n").unwrap();
2009 assert_eq!(value, Value::Integer(1000));
2010 assert_eq!(consumed, 7);
2011
2012 let (value, _) = Value::parse(b":-42\r\n").unwrap();
2013 assert_eq!(value, Value::Integer(-42));
2014 }
2015
2016 #[test]
2017 fn test_parse_bulk_string() {
2018 let (value, consumed) = Value::parse(b"$6\r\nfoobar\r\n").unwrap();
2019 assert_eq!(value, Value::BulkString(Bytes::from_static(b"foobar")));
2020 assert_eq!(consumed, 12);
2021 }
2022
2023 #[test]
2024 fn test_parse_null() {
2025 let (value, consumed) = Value::parse(b"$-1\r\n").unwrap();
2026 assert_eq!(value, Value::Null);
2027 assert_eq!(consumed, 5);
2028 }
2029
2030 #[test]
2031 fn test_parse_array() {
2032 let (value, consumed) = Value::parse(b"*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n").unwrap();
2033 assert_eq!(
2034 value,
2035 Value::Array(vec![
2036 Value::BulkString(Bytes::from_static(b"foo")),
2037 Value::BulkString(Bytes::from_static(b"bar")),
2038 ])
2039 );
2040 assert_eq!(consumed, 22);
2041 }
2042
2043 #[test]
2044 fn test_parse_empty_array() {
2045 let (value, consumed) = Value::parse(b"*0\r\n").unwrap();
2046 assert_eq!(value, Value::Array(vec![]));
2047 assert_eq!(consumed, 4);
2048 }
2049
2050 #[test]
2051 fn test_parse_incomplete() {
2052 assert!(matches!(
2053 Value::parse(b"$6\r\nfoo"),
2054 Err(ParseError::Incomplete)
2055 ));
2056 assert!(matches!(Value::parse(b"+OK"), Err(ParseError::Incomplete)));
2057 assert!(matches!(Value::parse(b""), Err(ParseError::Incomplete)));
2058 }
2059
2060 #[test]
2061 fn test_encode_simple_string() {
2062 let mut buf = [0u8; 64];
2063 let len = Value::simple_string(b"OK").encode(&mut buf);
2064 assert_eq!(&buf[..len], b"+OK\r\n");
2065 }
2066
2067 #[test]
2068 fn test_encode_error() {
2069 let mut buf = [0u8; 64];
2070 let len = Value::error(b"ERR unknown").encode(&mut buf);
2071 assert_eq!(&buf[..len], b"-ERR unknown\r\n");
2072 }
2073
2074 #[test]
2075 fn test_encode_integer() {
2076 let mut buf = [0u8; 64];
2077 let len = Value::integer(42).encode(&mut buf);
2078 assert_eq!(&buf[..len], b":42\r\n");
2079
2080 let len = Value::integer(-100).encode(&mut buf);
2081 assert_eq!(&buf[..len], b":-100\r\n");
2082 }
2083
2084 #[test]
2085 fn test_encode_bulk_string() {
2086 let mut buf = [0u8; 64];
2087 let len = Value::bulk_string(b"hello").encode(&mut buf);
2088 assert_eq!(&buf[..len], b"$5\r\nhello\r\n");
2089 }
2090
2091 #[test]
2092 fn test_encode_null() {
2093 let mut buf = [0u8; 64];
2094 let len = Value::null().encode(&mut buf);
2095 assert_eq!(&buf[..len], b"$-1\r\n");
2096 }
2097
2098 #[test]
2099 fn test_encode_array() {
2100 let mut buf = [0u8; 64];
2101 let arr = Value::array(vec![Value::bulk_string(b"foo"), Value::bulk_string(b"bar")]);
2102 let len = arr.encode(&mut buf);
2103 assert_eq!(&buf[..len], b"*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n");
2104 }
2105
2106 #[test]
2107 fn test_roundtrip() {
2108 let values = vec![
2109 Value::simple_string(b"OK"),
2110 Value::error(b"ERR test"),
2111 Value::integer(12345),
2112 Value::bulk_string(b"hello world"),
2113 Value::null(),
2114 Value::array(vec![
2115 Value::integer(1),
2116 Value::bulk_string(b"two"),
2117 Value::null(),
2118 ]),
2119 ];
2120
2121 for original in values {
2122 let mut buf = [0u8; 256];
2123 let len = original.encode(&mut buf);
2124 let (parsed, consumed) = Value::parse(&buf[..len]).unwrap();
2125 assert_eq!(original, parsed);
2126 assert_eq!(len, consumed);
2127 }
2128 }
2129
2130 #[test]
2131 fn test_encoded_len() {
2132 let values = vec![
2133 Value::simple_string(b"OK"),
2134 Value::error(b"ERR test"),
2135 Value::integer(12345),
2136 Value::bulk_string(b"hello world"),
2137 Value::null(),
2138 Value::array(vec![Value::integer(1), Value::bulk_string(b"two")]),
2139 ];
2140
2141 for value in values {
2142 let mut buf = [0u8; 256];
2143 let actual_len = value.encode(&mut buf);
2144 assert_eq!(value.encoded_len(), actual_len);
2145 }
2146 }
2147
2148 #[test]
2153 fn test_is_null() {
2154 assert!(Value::Null.is_null());
2155 assert!(!Value::integer(1).is_null());
2156 }
2157
2158 #[test]
2159 fn test_is_error() {
2160 assert!(Value::error(b"ERR").is_error());
2161 assert!(!Value::simple_string(b"OK").is_error());
2162 }
2163
2164 #[test]
2165 fn test_is_simple_string() {
2166 assert!(Value::simple_string(b"OK").is_simple_string());
2167 assert!(!Value::bulk_string(b"OK").is_simple_string());
2168 }
2169
2170 #[test]
2171 fn test_is_bulk_string() {
2172 assert!(Value::bulk_string(b"data").is_bulk_string());
2173 assert!(!Value::simple_string(b"data").is_bulk_string());
2174 }
2175
2176 #[test]
2177 fn test_is_integer() {
2178 assert!(Value::integer(42).is_integer());
2179 assert!(!Value::bulk_string(b"42").is_integer());
2180 }
2181
2182 #[test]
2183 fn test_is_array() {
2184 assert!(Value::array(vec![]).is_array());
2185 assert!(!Value::null().is_array());
2186 }
2187
2188 #[test]
2193 fn test_as_bytes() {
2194 assert_eq!(Value::simple_string(b"OK").as_bytes(), Some(&b"OK"[..]));
2195 assert_eq!(Value::bulk_string(b"data").as_bytes(), Some(&b"data"[..]));
2196 assert_eq!(Value::error(b"ERR").as_bytes(), Some(&b"ERR"[..]));
2197 assert_eq!(Value::integer(42).as_bytes(), None);
2198 assert_eq!(Value::null().as_bytes(), None);
2199 }
2200
2201 #[test]
2202 fn test_as_integer() {
2203 assert_eq!(Value::integer(42).as_integer(), Some(42));
2204 assert_eq!(Value::integer(-100).as_integer(), Some(-100));
2205 assert_eq!(Value::bulk_string(b"42").as_integer(), None);
2206 }
2207
2208 #[test]
2209 fn test_as_array() {
2210 let arr = Value::array(vec![Value::integer(1), Value::integer(2)]);
2211 assert_eq!(arr.as_array().map(|a| a.len()), Some(2));
2212 assert_eq!(Value::null().as_array(), None);
2213 }
2214
2215 #[test]
2220 fn test_encode_ok() {
2221 let mut buf = [0u8; 16];
2222 let len = Value::encode_ok(&mut buf);
2223 assert_eq!(&buf[..len], b"+OK\r\n");
2224 }
2225
2226 #[test]
2227 fn test_encode_pong() {
2228 let mut buf = [0u8; 16];
2229 let len = Value::encode_pong(&mut buf);
2230 assert_eq!(&buf[..len], b"+PONG\r\n");
2231 }
2232
2233 #[test]
2234 fn test_encode_null_bulk() {
2235 let mut buf = [0u8; 16];
2236 let len = Value::encode_null_bulk(&mut buf);
2237 assert_eq!(&buf[..len], b"$-1\r\n");
2238 }
2239
2240 #[test]
2241 fn test_encode_int() {
2242 let mut buf = [0u8; 32];
2243 let len = Value::encode_int(&mut buf, 42);
2244 assert_eq!(&buf[..len], b":42\r\n");
2245
2246 let len = Value::encode_int(&mut buf, -100);
2247 assert_eq!(&buf[..len], b":-100\r\n");
2248 }
2249
2250 #[test]
2251 fn test_encode_bulk() {
2252 let mut buf = [0u8; 32];
2253 let len = Value::encode_bulk(&mut buf, b"hello");
2254 assert_eq!(&buf[..len], b"$5\r\nhello\r\n");
2255 }
2256
2257 #[test]
2258 fn test_encode_err() {
2259 let mut buf = [0u8; 64];
2260 let len = Value::encode_err(&mut buf, b"ERR unknown command");
2261 assert_eq!(&buf[..len], b"-ERR unknown command\r\n");
2262 }
2263
2264 #[test]
2269 fn test_static_constants() {
2270 assert_eq!(Value::OK, b"+OK\r\n");
2271 assert_eq!(Value::PONG, b"+PONG\r\n");
2272 assert_eq!(Value::NULL_BULK, b"$-1\r\n");
2273 assert_eq!(Value::EMPTY_ARRAY, b"*0\r\n");
2274 }
2275
2276 #[test]
2281 fn test_parse_invalid_prefix() {
2282 let result = Value::parse(b"Q12345\r\n");
2284 assert!(matches!(result, Err(ParseError::InvalidPrefix(b'Q'))));
2285 }
2286
2287 #[test]
2288 fn test_parse_bulk_string_missing_crlf() {
2289 let result = Value::parse(b"$5\r\nhelloXY");
2291 assert!(matches!(result, Err(ParseError::Protocol(_))));
2292 }
2293
2294 #[test]
2295 fn test_parse_null_array() {
2296 let (value, consumed) = Value::parse(b"*-1\r\n").unwrap();
2298 assert_eq!(value, Value::Null);
2299 assert_eq!(consumed, 5);
2300 }
2301
2302 #[test]
2303 fn test_parse_array_collection_too_large() {
2304 let result = Value::parse(b"*99999999\r\n");
2306 assert!(matches!(result, Err(ParseError::CollectionTooLarge(_))));
2307 }
2308
2309 #[test]
2310 fn test_parse_nested_array() {
2311 let data = b"*2\r\n*2\r\n:1\r\n:2\r\n*2\r\n:3\r\n:4\r\n";
2313 let (value, consumed) = Value::parse(data).unwrap();
2314 assert_eq!(
2315 value,
2316 Value::Array(vec![
2317 Value::Array(vec![Value::Integer(1), Value::Integer(2)]),
2318 Value::Array(vec![Value::Integer(3), Value::Integer(4)]),
2319 ])
2320 );
2321 assert_eq!(consumed, data.len());
2322 }
2323
2324 #[test]
2325 fn test_value_clone() {
2326 let v1 = Value::array(vec![Value::integer(1), Value::bulk_string(b"test")]);
2327 let v2 = v1.clone();
2328 assert_eq!(v1, v2);
2329 }
2330
2331 #[test]
2332 fn test_value_debug() {
2333 let value = Value::integer(42);
2334 let debug_str = format!("{:?}", value);
2335 assert!(debug_str.contains("Integer"));
2336 assert!(debug_str.contains("42"));
2337 }
2338
2339 #[test]
2340 fn test_large_integer() {
2341 let (value, _) = Value::parse(b":9223372036854775807\r\n").unwrap();
2342 assert_eq!(value, Value::Integer(i64::MAX));
2343
2344 let (value, _) = Value::parse(b":-9223372036854775808\r\n").unwrap();
2345 assert_eq!(value, Value::Integer(i64::MIN));
2346 }
2347
2348 #[test]
2349 fn test_empty_bulk_string() {
2350 let (value, consumed) = Value::parse(b"$0\r\n\r\n").unwrap();
2351 assert_eq!(value, Value::BulkString(Bytes::new()));
2352 assert_eq!(consumed, 6);
2353 }
2354
2355 #[test]
2356 fn test_binary_bulk_string() {
2357 let (value, _) = Value::parse(b"$5\r\n\x00\x01\x02\x03\x04\r\n").unwrap();
2359 assert_eq!(
2360 value,
2361 Value::BulkString(Bytes::from_static(&[0, 1, 2, 3, 4]))
2362 );
2363 }
2364
2365 #[cfg(feature = "resp3")]
2370 mod resp3_tests {
2371 use super::*;
2372
2373 #[test]
2374 fn test_parse_resp3_null() {
2375 let (value, consumed) = Value::parse(b"_\r\n").unwrap();
2376 assert_eq!(value, Value::Null);
2377 assert_eq!(consumed, 3);
2378 }
2379
2380 #[test]
2381 fn test_parse_boolean() {
2382 let (value, consumed) = Value::parse(b"#t\r\n").unwrap();
2383 assert_eq!(value, Value::Boolean(true));
2384 assert_eq!(consumed, 4);
2385
2386 let (value, consumed) = Value::parse(b"#f\r\n").unwrap();
2387 assert_eq!(value, Value::Boolean(false));
2388 assert_eq!(consumed, 4);
2389 }
2390
2391 #[test]
2392 fn test_parse_double() {
2393 let (value, consumed) = Value::parse(b",1.23456\r\n").unwrap();
2394 if let Value::Double(d) = value {
2395 assert!((d - 1.23456).abs() < 0.00001);
2396 } else {
2397 panic!("Expected Double");
2398 }
2399 assert_eq!(consumed, 10);
2400
2401 let (value, _) = Value::parse(b",inf\r\n").unwrap();
2403 assert_eq!(value, Value::Double(f64::INFINITY));
2404
2405 let (value, _) = Value::parse(b",-inf\r\n").unwrap();
2406 assert_eq!(value, Value::Double(f64::NEG_INFINITY));
2407
2408 let (value, _) = Value::parse(b",nan\r\n").unwrap();
2409 if let Value::Double(d) = value {
2410 assert!(d.is_nan());
2411 } else {
2412 panic!("Expected Double");
2413 }
2414 }
2415
2416 #[test]
2417 fn test_parse_big_number() {
2418 let (value, consumed) = Value::parse(b"(12345678901234567890\r\n").unwrap();
2419 assert_eq!(
2420 value,
2421 Value::BigNumber(Bytes::from_static(b"12345678901234567890"))
2422 );
2423 assert_eq!(consumed, 23);
2424 }
2425
2426 #[test]
2427 fn test_parse_bulk_error() {
2428 let (value, consumed) = Value::parse(b"!21\r\nSYNTAX invalid syntax\r\n").unwrap();
2429 assert_eq!(
2430 value,
2431 Value::BulkError(Bytes::from_static(b"SYNTAX invalid syntax"))
2432 );
2433 assert_eq!(consumed, 28);
2434 }
2435
2436 #[test]
2437 fn test_parse_verbatim_string() {
2438 let (value, consumed) = Value::parse(b"=15\r\ntxt:Hello World\r\n").unwrap();
2439 assert_eq!(
2440 value,
2441 Value::VerbatimString {
2442 format: *b"txt",
2443 data: Bytes::from_static(b"Hello World"),
2444 }
2445 );
2446 assert_eq!(consumed, 22);
2447 }
2448
2449 #[test]
2450 fn test_parse_map() {
2451 let (value, consumed) =
2454 Value::parse(b"%2\r\n+first\r\n:1\r\n+second\r\n:2\r\n").unwrap();
2455 assert_eq!(
2456 value,
2457 Value::Map(vec![
2458 (
2459 Value::SimpleString(Bytes::from_static(b"first")),
2460 Value::Integer(1)
2461 ),
2462 (
2463 Value::SimpleString(Bytes::from_static(b"second")),
2464 Value::Integer(2)
2465 ),
2466 ])
2467 );
2468 assert_eq!(consumed, 29);
2469 }
2470
2471 #[test]
2472 fn test_parse_set() {
2473 let (value, consumed) = Value::parse(b"~3\r\n:1\r\n:2\r\n:3\r\n").unwrap();
2475 assert_eq!(
2476 value,
2477 Value::Set(vec![
2478 Value::Integer(1),
2479 Value::Integer(2),
2480 Value::Integer(3),
2481 ])
2482 );
2483 assert_eq!(consumed, 16);
2484 }
2485
2486 #[test]
2487 fn test_parse_push() {
2488 let (value, consumed) = Value::parse(b">2\r\n+message\r\n+hello\r\n").unwrap();
2489 assert_eq!(
2490 value,
2491 Value::Push(vec![
2492 Value::SimpleString(Bytes::from_static(b"message")),
2493 Value::SimpleString(Bytes::from_static(b"hello")),
2494 ])
2495 );
2496 assert_eq!(consumed, 22);
2497 }
2498
2499 #[test]
2500 fn test_parse_attribute() {
2501 let (value, consumed) = Value::parse(b"|1\r\n+key\r\n+value\r\n+actual\r\n").unwrap();
2504 assert_eq!(
2505 value,
2506 Value::Attribute {
2507 attrs: vec![(
2508 Value::SimpleString(Bytes::from_static(b"key")),
2509 Value::SimpleString(Bytes::from_static(b"value"))
2510 )],
2511 value: Box::new(Value::SimpleString(Bytes::from_static(b"actual"))),
2512 }
2513 );
2514 assert_eq!(consumed, 27);
2515 }
2516
2517 #[test]
2518 fn test_encode_boolean() {
2519 let mut buf = [0u8; 64];
2520 let len = Value::boolean(true).encode(&mut buf);
2521 assert_eq!(&buf[..len], b"#t\r\n");
2522
2523 let len = Value::boolean(false).encode(&mut buf);
2524 assert_eq!(&buf[..len], b"#f\r\n");
2525 }
2526
2527 #[test]
2528 fn test_encode_double() {
2529 let mut buf = [0u8; 64];
2530 let len = Value::double(1.5).encode(&mut buf);
2531 assert_eq!(buf[0], b',');
2533 assert!(buf[len - 2] == b'\r' && buf[len - 1] == b'\n');
2534
2535 let len = Value::double(f64::INFINITY).encode(&mut buf);
2537 assert_eq!(&buf[..len], b",inf\r\n");
2538
2539 let len = Value::double(f64::NEG_INFINITY).encode(&mut buf);
2540 assert_eq!(&buf[..len], b",-inf\r\n");
2541 }
2542
2543 #[test]
2544 fn test_encode_big_number() {
2545 let mut buf = [0u8; 64];
2546 let len = Value::big_number(b"12345678901234567890").encode(&mut buf);
2547 assert_eq!(&buf[..len], b"(12345678901234567890\r\n");
2548 }
2549
2550 #[test]
2551 fn test_encode_bulk_error() {
2552 let mut buf = [0u8; 64];
2553 let len = Value::bulk_error(b"SYNTAX error").encode(&mut buf);
2554 assert_eq!(&buf[..len], b"!12\r\nSYNTAX error\r\n");
2555 }
2556
2557 #[test]
2558 fn test_encode_verbatim_string() {
2559 let mut buf = [0u8; 64];
2560 let len = Value::verbatim_string(*b"txt", b"Hello").encode(&mut buf);
2561 assert_eq!(&buf[..len], b"=9\r\ntxt:Hello\r\n");
2562 }
2563
2564 #[test]
2565 fn test_encode_map() {
2566 let mut buf = [0u8; 64];
2567 let len =
2568 Value::map(vec![(Value::simple_string(b"a"), Value::integer(1))]).encode(&mut buf);
2569 assert_eq!(&buf[..len], b"%1\r\n+a\r\n:1\r\n");
2570 }
2571
2572 #[test]
2573 fn test_encode_set() {
2574 let mut buf = [0u8; 64];
2575 let len = Value::set(vec![Value::integer(1), Value::integer(2)]).encode(&mut buf);
2576 assert_eq!(&buf[..len], b"~2\r\n:1\r\n:2\r\n");
2577 }
2578
2579 #[test]
2580 fn test_encode_push() {
2581 let mut buf = [0u8; 64];
2582 let len = Value::push(vec![
2583 Value::simple_string(b"message"),
2584 Value::simple_string(b"hello"),
2585 ])
2586 .encode(&mut buf);
2587 assert_eq!(&buf[..len], b">2\r\n+message\r\n+hello\r\n");
2588 }
2589
2590 #[test]
2591 fn test_resp3_roundtrip() {
2592 let values = vec![
2593 Value::boolean(true),
2594 Value::boolean(false),
2595 Value::double(3.5), Value::double(100.0),
2597 Value::double(f64::INFINITY),
2598 Value::double(f64::NEG_INFINITY),
2599 Value::big_number(b"99999999999999999999"),
2600 Value::bulk_error(b"ERR something went wrong"),
2601 Value::verbatim_string(*b"txt", b"Hello World"),
2602 Value::map(vec![
2603 (Value::simple_string(b"key1"), Value::integer(1)),
2604 (Value::simple_string(b"key2"), Value::integer(2)),
2605 ]),
2606 Value::set(vec![
2607 Value::integer(1),
2608 Value::integer(2),
2609 Value::integer(3),
2610 ]),
2611 Value::push(vec![
2612 Value::simple_string(b"subscribe"),
2613 Value::simple_string(b"channel"),
2614 ]),
2615 ];
2616
2617 for original in values {
2618 let mut buf = [0u8; 512];
2619 let len = original.encode(&mut buf);
2620 let (parsed, consumed) = Value::parse(&buf[..len]).unwrap();
2621 if let (Value::Double(d1), Value::Double(d2)) = (&original, &parsed) {
2623 if d1.is_nan() {
2624 assert!(d2.is_nan());
2625 } else if d1.is_infinite() {
2626 assert_eq!(d1, d2, "Infinities should be exactly equal");
2627 } else {
2628 let diff = (d1 - d2).abs();
2630 let tolerance = d1.abs() * 1e-10;
2631 assert!(diff <= tolerance, "Doubles differ: {} vs {}", d1, d2);
2632 }
2633 } else {
2634 assert_eq!(original, parsed);
2635 }
2636 assert_eq!(len, consumed);
2637 }
2638 }
2639
2640 #[test]
2641 fn test_resp3_encoded_len() {
2642 let values = vec![
2643 Value::boolean(true),
2644 Value::double(1.23456),
2645 Value::big_number(b"12345"),
2646 Value::bulk_error(b"ERR test"),
2647 Value::verbatim_string(*b"txt", b"hello"),
2648 Value::map(vec![(Value::simple_string(b"a"), Value::integer(1))]),
2649 Value::set(vec![Value::integer(1), Value::integer(2)]),
2650 Value::push(vec![Value::simple_string(b"msg")]),
2651 ];
2652
2653 for value in values {
2654 let mut buf = [0u8; 512];
2655 let actual_len = value.encode(&mut buf);
2656 assert_eq!(
2657 value.encoded_len(),
2658 actual_len,
2659 "Length mismatch for {:?}",
2660 value
2661 );
2662 }
2663 }
2664 }
2665
2666 #[test]
2671 fn test_parse_cr_without_lf() {
2672 let result = Value::parse(b"+OK\rX");
2674 assert!(matches!(result, Err(ParseError::Incomplete)));
2675 }
2676
2677 #[test]
2678 fn test_parse_array_incomplete_elements() {
2679 let result = Value::parse(b"*3\r\n:1\r\n:2\r\n");
2681 assert!(matches!(result, Err(ParseError::Incomplete)));
2682 }
2683
2684 #[test]
2685 fn test_parse_array_truncated_after_length() {
2686 let result = Value::parse(b"*2\r\n");
2688 assert!(matches!(result, Err(ParseError::Incomplete)));
2689 }
2690
2691 #[test]
2692 fn test_parse_bulk_string_truncated_content() {
2693 let result = Value::parse(b"$10\r\nhello");
2695 assert!(matches!(result, Err(ParseError::Incomplete)));
2696 }
2697
2698 #[test]
2699 fn test_parse_nested_array_incomplete() {
2700 let result = Value::parse(b"*2\r\n*1\r\n:1\r\n");
2702 assert!(matches!(result, Err(ParseError::Incomplete)));
2703 }
2704
2705 #[test]
2706 fn test_parse_integer_no_crlf() {
2707 let result = Value::parse(b":12345");
2709 assert!(matches!(result, Err(ParseError::Incomplete)));
2710 }
2711
2712 #[test]
2713 fn test_parse_error_no_crlf() {
2714 let result = Value::parse(b"-ERR something");
2716 assert!(matches!(result, Err(ParseError::Incomplete)));
2717 }
2718
2719 #[test]
2720 fn test_parse_simple_string_only_cr() {
2721 let result = Value::parse(b"+OK\r");
2723 assert!(matches!(result, Err(ParseError::Incomplete)));
2724 }
2725
2726 #[test]
2731 fn test_parse_bulk_string_too_large() {
2732 let data = b"$536870913\r\n"; let result = Value::parse(data);
2736 assert!(matches!(result, Err(ParseError::Protocol(_))));
2737 }
2738
2739 #[test]
2740 fn test_parse_bulk_string_huge_length() {
2741 let data = b"$99999999999999\r\n";
2743 let result = Value::parse(data);
2744 assert!(result.is_err());
2746 }
2747
2748 #[test]
2749 fn test_parse_array_at_limit() {
2750 let data = b"*1000001\r\n"; let result = Value::parse(data);
2754 assert!(matches!(result, Err(ParseError::CollectionTooLarge(_))));
2755 }
2756
2757 #[test]
2758 fn test_parse_integer_overflow_protection() {
2759 let data = b":99999999999999999999\r\n";
2761 let result = Value::parse(data);
2762 assert!(matches!(result, Err(ParseError::InvalidInteger(_))));
2763 }
2764
2765 #[test]
2766 fn test_custom_parse_options() {
2767 let options = ParseOptions::new()
2769 .max_collection_elements(2)
2770 .max_bulk_string_len(10);
2771
2772 let data = b"*2\r\n:1\r\n:2\r\n";
2774 let result = Value::parse_with_options(data, &options);
2775 assert!(result.is_ok());
2776
2777 let data = b"*3\r\n:1\r\n:2\r\n:3\r\n";
2779 let result = Value::parse_with_options(data, &options);
2780 assert!(matches!(result, Err(ParseError::CollectionTooLarge(3))));
2781
2782 let data = b"$10\r\n0123456789\r\n";
2784 let result = Value::parse_with_options(data, &options);
2785 assert!(result.is_ok());
2786
2787 let data = b"$11\r\n01234567890\r\n";
2789 let result = Value::parse_with_options(data, &options);
2790 assert!(matches!(result, Err(ParseError::Protocol(_))));
2791 }
2792
2793 #[test]
2794 fn test_total_items_budget_flat_array() {
2795 let options = ParseOptions::new()
2797 .max_collection_elements(100)
2798 .max_total_items(10);
2799
2800 let data = b"*5\r\n:1\r\n:2\r\n:3\r\n:4\r\n:5\r\n";
2802 let result = Value::parse_with_options(data, &options);
2803 assert!(result.is_ok());
2804
2805 let data = b"*11\r\n:1\r\n:2\r\n:3\r\n:4\r\n:5\r\n:6\r\n:7\r\n:8\r\n:9\r\n:10\r\n:11\r\n";
2807 let result = Value::parse_with_options(data, &options);
2808 assert!(matches!(result, Err(ParseError::CollectionTooLarge(_))));
2809 }
2810
2811 #[test]
2812 fn test_total_items_budget_nested_arrays() {
2813 let options = ParseOptions::new()
2816 .max_collection_elements(100)
2817 .max_total_items(10)
2818 .max_depth(8);
2819
2820 let data = b"*2\r\n*3\r\n:1\r\n:2\r\n:3\r\n*3\r\n:4\r\n:5\r\n:6\r\n";
2823 let result = Value::parse_with_options(data, &options);
2824 assert!(result.is_ok());
2825
2826 let data =
2830 b"*3\r\n*3\r\n:1\r\n:2\r\n:3\r\n*3\r\n:4\r\n:5\r\n:6\r\n*3\r\n:7\r\n:8\r\n:9\r\n";
2831 let result = Value::parse_with_options(data, &options);
2832 assert!(matches!(result, Err(ParseError::CollectionTooLarge(_))));
2833 }
2834
2835 #[test]
2836 fn test_nesting_depth_limit() {
2837 let options = ParseOptions::new()
2839 .max_collection_elements(100)
2840 .max_total_items(1000)
2841 .max_depth(2);
2842
2843 let data = b"*1\r\n:1\r\n";
2845 let result = Value::parse_with_options(data, &options);
2846 assert!(result.is_ok());
2847
2848 let data = b"*1\r\n*1\r\n:1\r\n";
2850 let result = Value::parse_with_options(data, &options);
2851 assert!(result.is_ok());
2852
2853 let data = b"*1\r\n*1\r\n*1\r\n:1\r\n";
2855 let result = Value::parse_with_options(data, &options);
2856 assert!(matches!(result, Err(ParseError::NestingTooDeep(_))));
2857 }
2858
2859 #[test]
2860 fn test_exponential_attack_prevented() {
2861 let options = ParseOptions::new()
2865 .max_collection_elements(100)
2866 .max_total_items(1000)
2867 .max_depth(8);
2868
2869 let mut data = Vec::new();
2879 data.extend_from_slice(b"*100\r\n");
2881 data.extend_from_slice(b"*100\r\n");
2883 data.extend_from_slice(b"*100\r\n");
2885 for i in 0..100 {
2887 let s = format!(":{}\r\n", i);
2888 data.extend_from_slice(s.as_bytes());
2889 }
2890 for i in 0..99 {
2892 let s = format!(":{}\r\n", i);
2893 data.extend_from_slice(s.as_bytes());
2894 }
2895 for i in 0..99 {
2897 let s = format!(":{}\r\n", i);
2898 data.extend_from_slice(s.as_bytes());
2899 }
2900
2901 let result = Value::parse_with_options(&data, &options);
2902 assert!(result.is_ok());
2909
2910 let strict_options = ParseOptions::new()
2912 .max_collection_elements(100)
2913 .max_total_items(250) .max_depth(8);
2915
2916 let result = Value::parse_with_options(&data, &strict_options);
2917 assert!(matches!(result, Err(ParseError::CollectionTooLarge(_))));
2918 }
2919}