mini_redis/
parse.rs

1use crate::Frame;
2
3use bytes::Bytes;
4use std::{fmt, str, vec};
5
6/// Utility for parsing a command
7///
8/// Commands are represented as array frames. Each entry in the frame is a
9/// "token". A `Parse` is initialized with the array frame and provides a
10/// cursor-like API. Each command struct includes a `parse_frame` method that
11/// uses a `Parse` to extract its fields.
12#[derive(Debug)]
13pub(crate) struct Parse {
14    /// Array frame iterator.
15    parts: vec::IntoIter<Frame>,
16}
17
18/// Error encountered while parsing a frame.
19///
20/// Only `EndOfStream` errors are handled at runtime. All other errors result in
21/// the connection being terminated.
22#[derive(Debug)]
23pub(crate) enum ParseError {
24    /// Attempting to extract a value failed due to the frame being fully
25    /// consumed.
26    EndOfStream,
27
28    /// All other errors
29    Other(crate::Error),
30}
31
32impl Parse {
33    /// Create a new `Parse` to parse the contents of `frame`.
34    ///
35    /// Returns `Err` if `frame` is not an array frame.
36    pub(crate) fn new(frame: Frame) -> Result<Parse, ParseError> {
37        let array = match frame {
38            Frame::Array(array) => array,
39            frame => return Err(format!("protocol error; expected array, got {:?}", frame).into()),
40        };
41
42        Ok(Parse {
43            parts: array.into_iter(),
44        })
45    }
46
47    /// Return the next entry. Array frames are arrays of frames, so the next
48    /// entry is a frame.
49    fn next(&mut self) -> Result<Frame, ParseError> {
50        self.parts.next().ok_or(ParseError::EndOfStream)
51    }
52
53    /// Return the next entry as a string.
54    ///
55    /// If the next entry cannot be represented as a String, then an error is returned.
56    pub(crate) fn next_string(&mut self) -> Result<String, ParseError> {
57        match self.next()? {
58            // Both `Simple` and `Bulk` representation may be strings. Strings
59            // are parsed to UTF-8.
60            //
61            // While errors are stored as strings, they are considered separate
62            // types.
63            Frame::Simple(s) => Ok(s),
64            Frame::Bulk(data) => str::from_utf8(&data[..])
65                .map(|s| s.to_string())
66                .map_err(|_| "protocol error; invalid string".into()),
67            frame => Err(format!(
68                "protocol error; expected simple frame or bulk frame, got {:?}",
69                frame
70            )
71            .into()),
72        }
73    }
74
75    /// Return the next entry as raw bytes.
76    ///
77    /// If the next entry cannot be represented as raw bytes, an error is
78    /// returned.
79    pub(crate) fn next_bytes(&mut self) -> Result<Bytes, ParseError> {
80        match self.next()? {
81            // Both `Simple` and `Bulk` representation may be raw bytes.
82            //
83            // Although errors are stored as strings and could be represented as
84            // raw bytes, they are considered separate types.
85            Frame::Simple(s) => Ok(Bytes::from(s.into_bytes())),
86            Frame::Bulk(data) => Ok(data),
87            frame => Err(format!(
88                "protocol error; expected simple frame or bulk frame, got {:?}",
89                frame
90            )
91            .into()),
92        }
93    }
94
95    /// Return the next entry as an integer.
96    ///
97    /// This includes `Simple`, `Bulk`, and `Integer` frame types. `Simple` and
98    /// `Bulk` frame types are parsed.
99    ///
100    /// If the next entry cannot be represented as an integer, then an error is
101    /// returned.
102    pub(crate) fn next_int(&mut self) -> Result<u64, ParseError> {
103        use atoi::atoi;
104
105        const MSG: &str = "protocol error; invalid number";
106
107        match self.next()? {
108            // An integer frame type is already stored as an integer.
109            Frame::Integer(v) => Ok(v),
110            // Simple and bulk frames must be parsed as integers. If the parsing
111            // fails, an error is returned.
112            Frame::Simple(data) => atoi::<u64>(data.as_bytes()).ok_or_else(|| MSG.into()),
113            Frame::Bulk(data) => atoi::<u64>(&data).ok_or_else(|| MSG.into()),
114            frame => Err(format!("protocol error; expected int frame but got {:?}", frame).into()),
115        }
116    }
117
118    /// Ensure there are no more entries in the array
119    pub(crate) fn finish(&mut self) -> Result<(), ParseError> {
120        if self.parts.next().is_none() {
121            Ok(())
122        } else {
123            Err("protocol error; expected end of frame, but there was more".into())
124        }
125    }
126}
127
128impl From<String> for ParseError {
129    fn from(src: String) -> ParseError {
130        ParseError::Other(src.into())
131    }
132}
133
134impl From<&str> for ParseError {
135    fn from(src: &str) -> ParseError {
136        src.to_string().into()
137    }
138}
139
140impl fmt::Display for ParseError {
141    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142        match self {
143            ParseError::EndOfStream => "protocol error; unexpected end of stream".fmt(f),
144            ParseError::Other(err) => err.fmt(f),
145        }
146    }
147}
148
149impl std::error::Error for ParseError {}