1#![allow(unknown_lints)]
5#![allow(
6 semicolon_in_expressions_from_non_local_macros,
7 reason = "This lint is on in nightly since 2026-07-16, but `combine-4.6.7` violates it in `opaque`. As we cannot decorate directly, we allow it for the whole module for now"
8)]
9use std::{
10 io::{self, Read},
11 str,
12};
13
14use crate::errors::{ParsingError, RedisError, Repr, ServerError, ServerErrorKind};
15use crate::types::{PushKind, RedisResult, Value, VerbatimFormat};
16
17use combine::{
18 ParseError, Parser as _, any,
19 error::StreamError,
20 opaque,
21 parser::{
22 byte::{crlf, take_until_bytes},
23 combinator::{AnySendSyncPartialState, any_send_sync_partial_state},
24 range::{recognize, take},
25 },
26 stream::{
27 PointerOffset, RangeStream, StreamErrorFor,
28 decoder::{self, Decoder},
29 },
30 unexpected_any,
31};
32
33const MAX_RECURSE_DEPTH: usize = 100;
34
35fn err_parser(line: &str) -> ServerError {
36 let mut pieces = line.splitn(2, ' ');
37 let kind = match pieces.next().unwrap() {
38 "ERR" => ServerErrorKind::ResponseError,
39 "EXECABORT" => ServerErrorKind::ExecAbort,
40 "LOADING" => ServerErrorKind::BusyLoading,
41 "NOSCRIPT" => ServerErrorKind::NoScript,
42 "MOVED" => ServerErrorKind::Moved,
43 "ASK" => ServerErrorKind::Ask,
44 "TRYAGAIN" => ServerErrorKind::TryAgain,
45 "CLUSTERDOWN" => ServerErrorKind::ClusterDown,
46 "CROSSSLOT" => ServerErrorKind::CrossSlot,
47 "MASTERDOWN" => ServerErrorKind::MasterDown,
48 "READONLY" => ServerErrorKind::ReadOnly,
49 "NOTBUSY" => ServerErrorKind::NotBusy,
50 "NOSUB" => ServerErrorKind::NoSub,
51 "NOPERM" => ServerErrorKind::NoPerm,
52 code => {
53 return ServerError(Repr::Extension {
54 code: code.into(),
55 detail: pieces.next().map(|str| str.into()),
56 });
57 }
58 };
59 let detail = pieces.next().map(|str| str.into());
60 ServerError(Repr::Known { kind, detail })
61}
62
63pub fn get_push_kind(kind: String) -> PushKind {
64 match kind.as_str() {
65 "invalidate" => PushKind::Invalidate,
66 "message" => PushKind::Message,
67 "pmessage" => PushKind::PMessage,
68 "smessage" => PushKind::SMessage,
69 "unsubscribe" => PushKind::Unsubscribe,
70 "punsubscribe" => PushKind::PUnsubscribe,
71 "sunsubscribe" => PushKind::SUnsubscribe,
72 "subscribe" => PushKind::Subscribe,
73 "psubscribe" => PushKind::PSubscribe,
74 "ssubscribe" => PushKind::SSubscribe,
75 _ => PushKind::Other(kind),
76 }
77}
78
79fn value<'a, I>(
80 count: Option<usize>,
81) -> impl combine::Parser<I, Output = Value, PartialState = AnySendSyncPartialState>
82where
83 I: RangeStream<Token = u8, Range = &'a [u8]>,
84 I::Error: combine::ParseError<u8, &'a [u8], I::Position>,
85{
86 let count = count.unwrap_or(1);
87
88 opaque!(any_send_sync_partial_state(
89 any()
90 .then_partial(move |&mut b| {
91 if count > MAX_RECURSE_DEPTH {
92 combine::unexpected_any("Maximum recursion depth exceeded").left()
93 } else {
94 combine::value(b).right()
95 }
96 })
97 .then_partial(move |&mut b| {
98 let line = || {
99 recognize(take_until_bytes(&b"\r\n"[..]).with(take(2).map(|_| ()))).and_then(
100 |line: &[u8]| {
101 str::from_utf8(&line[..line.len() - 2])
102 .map_err(StreamErrorFor::<I>::other)
103 },
104 )
105 };
106
107 let simple_string = || {
108 line().map(|line| {
109 if line == "OK" {
110 Value::Okay
111 } else {
112 Value::SimpleString(line.into())
113 }
114 })
115 };
116
117 let int = || {
118 line().and_then(|line| {
119 line.trim().parse::<i64>().map_err(|_| {
120 StreamErrorFor::<I>::message_static_message(
121 "Expected integer, got garbage",
122 )
123 })
124 })
125 };
126
127 let bulk_string = || {
128 int().then_partial(move |size| {
129 if *size < 0 {
130 combine::produce(|| Value::Nil).left()
131 } else {
132 take(*size as usize)
133 .map(|bs: &[u8]| Value::BulkString(bs.to_vec()))
134 .skip(crlf())
135 .right()
136 }
137 })
138 };
139 let blob = || {
140 int().then_partial(move |size| {
141 take(*size as usize)
142 .map(|bs: &[u8]| String::from_utf8_lossy(bs).to_string())
143 .skip(crlf())
144 })
145 };
146
147 let array = || {
148 int().then_partial(move |&mut length| {
149 if length < 0 {
150 combine::produce(|| Value::Nil).left()
151 } else {
152 let length = length as usize;
153 combine::count_min_max(length, length, value(Some(count + 1)))
154 .map(Value::Array)
155 .right()
156 }
157 })
158 };
159
160 let error = || line().map(err_parser);
161 let map = || {
162 int().then_partial(move |&mut kv_length| {
163 match (kv_length as usize).checked_mul(2) {
164 Some(length) => {
165 combine::count_min_max(length, length, value(Some(count + 1)))
166 .map(move |result: Vec<Value>| {
167 let mut it = result.into_iter();
168 let mut x = vec![];
169 for _ in 0..kv_length {
170 if let (Some(k), Some(v)) = (it.next(), it.next()) {
171 x.push((k, v));
172 }
173 }
174 Value::Map(x)
175 })
176 .left()
177 }
178 None => {
179 unexpected_any("Attribute key-value length is too large").right()
180 }
181 }
182 })
183 };
184 let attribute = || {
185 int().then_partial(move |&mut kv_length| {
186 match (kv_length as usize).checked_mul(2) {
187 Some(length) => {
188 let length = length + 1;
190 combine::count_min_max(length, length, value(Some(count + 1)))
191 .map(move |result: Vec<Value>| {
192 let mut it = result.into_iter();
193 let mut attributes = vec![];
194 for _ in 0..kv_length {
195 if let (Some(k), Some(v)) = (it.next(), it.next()) {
196 attributes.push((k, v));
197 }
198 }
199 Value::Attribute {
200 data: Box::new(it.next().unwrap()),
201 attributes,
202 }
203 })
204 .left()
205 }
206 None => {
207 unexpected_any("Attribute key-value length is too large").right()
208 }
209 }
210 })
211 };
212 let set = || {
213 int().then_partial(move |&mut length| {
214 if length < 0 {
215 combine::produce(|| Value::Nil).left()
216 } else {
217 let length = length as usize;
218 combine::count_min_max(length, length, value(Some(count + 1)))
219 .map(Value::Set)
220 .right()
221 }
222 })
223 };
224 let push = || {
225 int().then_partial(move |&mut length| {
226 if length <= 0 {
227 combine::produce(|| Value::Push {
228 kind: PushKind::Other("".to_string()),
229 data: vec![],
230 })
231 .left()
232 } else {
233 let length = length as usize;
234 combine::count_min_max(length, length, value(Some(count + 1)))
235 .and_then(|result: Vec<Value>| {
236 let mut it = result.into_iter();
237 let first = it.next().unwrap_or(Value::Nil);
238 if let Value::BulkString(kind) = first {
239 let push_kind = String::from_utf8(kind)
240 .map_err(StreamErrorFor::<I>::other)?;
241 Ok(Value::Push {
242 kind: get_push_kind(push_kind),
243 data: it.collect(),
244 })
245 } else if let Value::SimpleString(kind) = first {
246 Ok(Value::Push {
247 kind: get_push_kind(kind),
248 data: it.collect(),
249 })
250 } else {
251 Err(StreamErrorFor::<I>::message_static_message(
252 "parse error when decoding push",
253 ))
254 }
255 })
256 .right()
257 }
258 })
259 };
260 let null = || line().map(|_| Value::Nil);
261 let double = || {
262 line().and_then(|line| {
263 line.trim()
264 .parse::<f64>()
265 .map_err(StreamErrorFor::<I>::other)
266 })
267 };
268 let boolean = || {
269 line().and_then(|line: &str| match line {
270 "t" => Ok(true),
271 "f" => Ok(false),
272 _ => Err(StreamErrorFor::<I>::message_static_message(
273 "Expected boolean, got garbage",
274 )),
275 })
276 };
277 let blob_error = || blob().map(|line| err_parser(&line));
278 let verbatim = || {
279 blob().and_then(|line| {
280 if let Some((format, text)) = line.split_once(':') {
281 let format = match format {
282 "txt" => VerbatimFormat::Text,
283 "mkd" => VerbatimFormat::Markdown,
284 x => VerbatimFormat::Unknown(x.to_string()),
285 };
286 Ok(Value::VerbatimString {
287 format,
288 text: text.to_string(),
289 })
290 } else {
291 Err(StreamErrorFor::<I>::message_static_message(
292 "parse error when decoding verbatim string",
293 ))
294 }
295 })
296 };
297 let big_number = || {
298 line().and_then(|line| {
299 #[cfg(not(feature = "num-bigint"))]
300 return Ok::<_, StreamErrorFor<I>>(Value::BigNumber(
301 line.as_bytes().to_vec(),
302 ));
303 #[cfg(feature = "num-bigint")]
304 num_bigint::BigInt::parse_bytes(line.as_bytes(), 10)
305 .ok_or_else(|| {
306 StreamErrorFor::<I>::message_static_message(
307 "Expected bigint, got garbage",
308 )
309 })
310 .map(Value::BigNumber)
311 })
312 };
313 combine::dispatch!(b;
314 b'+' => simple_string(),
315 b':' => int().map(Value::Int),
316 b'$' => bulk_string(),
317 b'*' => array(),
318 b'%' => map(),
319 b'|' => attribute(),
320 b'~' => set(),
321 b'-' => error().map(Value::ServerError),
322 b'_' => null(),
323 b',' => double().map(Value::Double),
324 b'#' => boolean().map(Value::Boolean),
325 b'!' => blob_error().map(Value::ServerError),
326 b'=' => verbatim(),
327 b'(' => big_number(),
328 b'>' => push(),
329 b => combine::unexpected_any(combine::error::Token(b))
330 )
331 })
332 ))
333}
334
335macro_rules! to_redis_err {
337 ($err: expr, $decoder: expr) => {
338 match $err {
339 decoder::Error::Io { error, .. } => error.into(),
340 decoder::Error::Parse(err) => {
341 if err.is_unexpected_end_of_input() {
342 RedisError::from(io::Error::from(io::ErrorKind::UnexpectedEof))
343 } else {
344 let err = err
345 .map_range(|range| format!("{range:?}"))
346 .map_position(|pos| pos.translate_position($decoder.buffer()))
347 .to_string();
348 RedisError::from(ParsingError::from(err))
349 }
350 }
351 }
352 };
353}
354
355#[cfg(feature = "aio")]
356mod aio_support {
357 use super::*;
358
359 use bytes::{Buf, BytesMut};
360 use tokio::io::AsyncRead;
361 use tokio_util::codec::{Decoder, Encoder};
362
363 #[derive(Default)]
364 pub struct ValueCodec {
365 state: AnySendSyncPartialState,
366 }
367
368 impl ValueCodec {
369 fn decode_stream(&mut self, bytes: &mut BytesMut, eof: bool) -> RedisResult<Option<Value>> {
370 let (opt, removed_len) = {
371 let buffer = &bytes[..];
372 let mut stream =
373 combine::easy::Stream(combine::stream::MaybePartialStream(buffer, !eof));
374 match combine::stream::decode_tokio(value(None), &mut stream, &mut self.state) {
375 Ok(x) => x,
376 Err(err) => {
377 let err = err
378 .map_position(|pos| pos.translate_position(buffer))
379 .map_range(|range| format!("{range:?}"))
380 .to_string();
381 return Err(RedisError::from(ParsingError::from(err)));
382 }
383 }
384 };
385
386 bytes.advance(removed_len);
387 match opt {
388 Some(result) => Ok(Some(result)),
389 None => Ok(None),
390 }
391 }
392 }
393
394 impl Encoder<Vec<u8>> for ValueCodec {
395 type Error = RedisError;
396 fn encode(&mut self, item: Vec<u8>, dst: &mut BytesMut) -> Result<(), Self::Error> {
397 dst.extend_from_slice(item.as_ref());
398 Ok(())
399 }
400 }
401
402 impl Decoder for ValueCodec {
403 type Item = Value;
404 type Error = RedisError;
405
406 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
407 self.decode_stream(src, false)
408 }
409
410 fn decode_eof(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
411 self.decode_stream(buf, true)
412 }
413 }
414
415 pub async fn parse_redis_value_async<R>(
417 decoder: &mut combine::stream::Decoder<AnySendSyncPartialState, PointerOffset<[u8]>>,
418 read: &mut R,
419 ) -> RedisResult<Value>
420 where
421 R: AsyncRead + std::marker::Unpin,
422 {
423 let result = combine::decode_tokio!(*decoder, *read, value(None), |input, _| {
424 combine::stream::easy::Stream::from(input)
425 });
426 match result {
427 Err(err) => Err(to_redis_err!(err, decoder)),
428 Ok(result) => Ok(result),
429 }
430 }
431}
432
433#[cfg(feature = "aio")]
434#[cfg_attr(docsrs, doc(cfg(feature = "aio")))]
435pub use self::aio_support::*;
436
437pub struct Parser {
439 decoder: Decoder<AnySendSyncPartialState, PointerOffset<[u8]>>,
440}
441
442impl Default for Parser {
443 fn default() -> Self {
444 Self::new()
445 }
446}
447
448impl Parser {
453 pub fn new() -> Self {
458 Self {
459 decoder: Decoder::new(),
460 }
461 }
462
463 pub fn parse_value<T: Read>(&mut self, mut reader: T) -> RedisResult<Value> {
467 let mut decoder = &mut self.decoder;
468 let result = combine::decode!(decoder, reader, value(None), |input, _| {
469 combine::stream::easy::Stream::from(input)
470 });
471 match result {
472 Err(err) => Err(to_redis_err!(err, decoder)),
473 Ok(result) => Ok(result),
474 }
475 }
476}
477
478pub fn parse_redis_value(bytes: &[u8]) -> RedisResult<Value> {
483 let mut parser = Parser::new();
484 parser.parse_value(bytes)
485}
486
487#[cfg(test)]
488mod tests {
489 use super::*;
490 use crate::errors::ErrorKind;
491 use assert_matches::assert_matches;
492
493 #[cfg(feature = "aio")]
494 #[test]
495 fn decode_eof_returns_none_at_eof() {
496 use tokio_util::codec::Decoder;
497 let mut codec = ValueCodec::default();
498
499 let mut bytes = bytes::BytesMut::from(&b"+GET 123\r\n"[..]);
500 assert_eq!(
501 codec.decode_eof(&mut bytes),
502 Ok(Some(parse_redis_value(b"+GET 123\r\n").unwrap()))
503 );
504 assert_eq!(codec.decode_eof(&mut bytes), Ok(None));
505 assert_eq!(codec.decode_eof(&mut bytes), Ok(None));
506 }
507
508 #[cfg(feature = "aio")]
509 #[test]
510 fn decode_eof_returns_error_inside_array_and_can_parse_more_inputs() {
511 use tokio_util::codec::Decoder;
512 let mut codec = ValueCodec::default();
513
514 let mut bytes =
515 bytes::BytesMut::from(b"*3\r\n+OK\r\n-LOADING server is loading\r\n+OK\r\n".as_slice());
516 let result = codec.decode_eof(&mut bytes).unwrap().unwrap();
517
518 assert_eq!(
519 result,
520 Value::Array(vec![
521 Value::Okay,
522 Value::ServerError(ServerError(Repr::Known {
523 kind: ServerErrorKind::BusyLoading,
524 detail: Some(arcstr::literal!("server is loading"))
525 })),
526 Value::Okay
527 ])
528 );
529
530 let mut bytes = bytes::BytesMut::from(b"+OK\r\n".as_slice());
531 let result = codec.decode_eof(&mut bytes).unwrap().unwrap();
532
533 assert_eq!(result, Value::Okay);
534 }
535
536 #[test]
537 fn parse_nested_error_and_handle_more_inputs() {
538 let bytes = b"*3\r\n+OK\r\n-LOADING server is loading\r\n+OK\r\n";
542 let result = parse_redis_value(bytes);
543
544 assert_eq!(
545 result.unwrap(),
546 Value::Array(vec![
547 Value::Okay,
548 Value::ServerError(ServerError(Repr::Known {
549 kind: ServerErrorKind::BusyLoading,
550 detail: Some(arcstr::literal!("server is loading"))
551 })),
552 Value::Okay
553 ])
554 );
555
556 let result = parse_redis_value(b"+OK\r\n").unwrap();
557
558 assert_eq!(result, Value::Okay);
559 }
560
561 #[test]
562 fn decode_resp3_double() {
563 let val = parse_redis_value(b",1.23\r\n").unwrap();
564 assert_eq!(val, Value::Double(1.23));
565 let val = parse_redis_value(b",nan\r\n").unwrap();
566 if let Value::Double(val) = val {
567 assert!(val.is_sign_positive());
568 assert!(val.is_nan());
569 } else {
570 panic!("expected double");
571 }
572 let val = parse_redis_value(b",-nan\r\n").unwrap();
574 if let Value::Double(val) = val {
575 assert!(val.is_sign_negative());
576 assert!(val.is_nan());
577 } else {
578 panic!("expected double");
579 }
580 let val = parse_redis_value(b",2.67923e+8\r\n").unwrap();
582 assert_eq!(val, Value::Double(267923000.0));
583 let val = parse_redis_value(b",2.67923E+8\r\n").unwrap();
584 assert_eq!(val, Value::Double(267923000.0));
585 let val = parse_redis_value(b",-2.67923E+8\r\n").unwrap();
586 assert_eq!(val, Value::Double(-267923000.0));
587 let val = parse_redis_value(b",2.1E-2\r\n").unwrap();
588 assert_eq!(val, Value::Double(0.021));
589
590 let val = parse_redis_value(b",-inf\r\n").unwrap();
591 assert_eq!(val, Value::Double(-f64::INFINITY));
592 let val = parse_redis_value(b",inf\r\n").unwrap();
593 assert_eq!(val, Value::Double(f64::INFINITY));
594 }
595
596 #[test]
597 fn decode_resp3_map() {
598 let val = parse_redis_value(b"%2\r\n+first\r\n:1\r\n+second\r\n:2\r\n").unwrap();
599 let mut v = val.as_map_iter().unwrap();
600 assert_eq!(
601 (&Value::SimpleString("first".to_string()), &Value::Int(1)),
602 v.next().unwrap()
603 );
604 assert_eq!(
605 (&Value::SimpleString("second".to_string()), &Value::Int(2)),
606 v.next().unwrap()
607 );
608 }
609
610 #[test]
611 fn decode_resp3_boolean() {
612 let val = parse_redis_value(b"#t\r\n").unwrap();
613 assert_eq!(val, Value::Boolean(true));
614 let val = parse_redis_value(b"#f\r\n").unwrap();
615 assert_eq!(val, Value::Boolean(false));
616 let val = parse_redis_value(b"#x\r\n");
617 assert_matches!(val, Err(_));
618 let val = parse_redis_value(b"#\r\n");
619 assert_matches!(val, Err(_));
620 }
621
622 #[test]
623 fn decode_resp3_blob_error() {
624 let val = parse_redis_value(b"!21\r\nSYNTAX invalid syntax\r\n");
625 assert_eq!(
626 val.unwrap(),
627 Value::ServerError(ServerError(Repr::Extension {
628 code: arcstr::literal!("SYNTAX"),
629 detail: Some(arcstr::literal!("invalid syntax"))
630 }))
631 );
632 }
633
634 #[test]
635 fn decode_resp3_big_number() {
636 let val = parse_redis_value(b"(3492890328409238509324850943850943825024385\r\n").unwrap();
637 #[cfg(feature = "num-bigint")]
638 let expected = Value::BigNumber(
639 num_bigint::BigInt::parse_bytes(b"3492890328409238509324850943850943825024385", 10)
640 .unwrap(),
641 );
642 #[cfg(not(feature = "num-bigint"))]
643 let expected = Value::BigNumber(b"3492890328409238509324850943850943825024385".to_vec());
644 assert_eq!(val, expected);
645 }
646
647 #[test]
648 fn decode_resp3_set() {
649 let val = parse_redis_value(b"~5\r\n+orange\r\n+apple\r\n#t\r\n:100\r\n:999\r\n").unwrap();
650 let v = val.as_sequence().unwrap();
651 assert!(v.len() >= 5);
652 assert_eq!(Value::SimpleString("orange".to_string()), v[0]);
653 assert_eq!(Value::SimpleString("apple".to_string()), v[1]);
654 assert_eq!(Value::Boolean(true), v[2]);
655 assert_eq!(Value::Int(100), v[3]);
656 assert_eq!(Value::Int(999), v[4]);
657 }
658
659 #[test]
660 fn decode_resp3_push() {
661 let val = parse_redis_value(b">3\r\n+message\r\n+somechannel\r\n+this is the message\r\n")
662 .unwrap();
663 if let Value::Push { ref kind, ref data } = val {
664 assert_eq!(&PushKind::Message, kind);
665 assert_eq!(Value::SimpleString("somechannel".to_string()), data[0]);
666 assert_eq!(
667 Value::SimpleString("this is the message".to_string()),
668 data[1]
669 );
670 } else {
671 panic!("Expected Value::Push")
672 }
673 }
674
675 #[test]
676 fn test_max_recursion_depth_set_and_array() {
677 for test_byte in ["*", "~"] {
678 let initial = format!("{test_byte}1\r\n").as_bytes().to_vec();
679 let end = format!("{test_byte}0\r\n").as_bytes().to_vec();
680
681 let mut ba = initial.repeat(MAX_RECURSE_DEPTH - 1).to_vec();
682 ba.extend(end.clone());
683 match parse_redis_value(&ba) {
684 Ok(Value::Array(a)) => assert_eq!(a.len(), 1),
685 Ok(Value::Set(s)) => assert_eq!(s.len(), 1),
686 _ => panic!("Expected valid array or set"),
687 }
688
689 let mut ba = initial.repeat(MAX_RECURSE_DEPTH).to_vec();
690 ba.extend(end);
691 match parse_redis_value(&ba) {
692 Ok(_) => panic!("Expected ParseError"),
693 Err(e) => assert_matches!(e.kind(), ErrorKind::Parse),
694 }
695 }
696 }
697
698 #[test]
699 fn test_max_recursion_depth_map() {
700 let initial = b"%1\r\n+a\r\n";
701 let end = b"%0\r\n";
702
703 let mut ba = initial.repeat(MAX_RECURSE_DEPTH - 1).to_vec();
704 ba.extend(*end);
705 match parse_redis_value(&ba) {
706 Ok(Value::Map(m)) => assert_eq!(m.len(), 1),
707 Ok(Value::Set(s)) => assert_eq!(s.len(), 1),
708 _ => panic!("Expected valid array or set"),
709 }
710
711 let mut ba = initial.repeat(MAX_RECURSE_DEPTH).to_vec();
712 ba.extend(end);
713 match parse_redis_value(&ba) {
714 Ok(_) => panic!("Expected ParseError"),
715 Err(e) => assert_matches!(e.kind(), ErrorKind::Parse),
716 }
717 }
718}