resp_protocol/error/
mod.rs

1use crate::RespError;
2use bytes::{Buf, BufMut, Bytes, BytesMut};
3
4#[derive(Debug, Clone, PartialEq)]
5pub struct Error(Bytes);
6
7/// Error type
8impl Error {
9    /// Build a new Error
10    ///
11    /// # Example
12    /// ```
13    /// use resp_protocol::Error;
14    ///
15    /// let error = Error::new(b"Invalid type.");
16    /// ```
17    #[inline]
18    pub fn new(input: &[u8]) -> Self {
19        let mut bytes = BytesMut::with_capacity(input.len() + 3);
20        bytes.put_u8(0x2d); // "-"
21        bytes.put_slice(input);
22        bytes.put_u8(0x0d); // CR
23        bytes.put_u8(0x0a); // LF
24        Self::from_bytes(bytes.freeze())
25    }
26
27    #[inline]
28    pub fn bytes(&self) -> Bytes {
29        self.0.clone()
30    }
31
32    #[inline]
33    pub fn len(&self) -> usize {
34        self.0.len()
35    }
36
37    #[inline]
38    pub fn value(&self) -> Vec<u8> {
39        let length = self.0.len();
40        let mut bytes = self.0.slice(1..(length - 2));
41        let mut vector = Vec::<u8>::with_capacity(length - 3);
42        unsafe {
43            vector.set_len(length - 3);
44        }
45        bytes.copy_to_slice(vector.as_mut_slice());
46        vector
47    }
48
49    pub fn validate_value(input: &[u8]) -> Result<(), RespError> {
50        let mut index = 0;
51        let length = input.len();
52        while index < length && input[index] != 0x0d && input[index] != 0x0a {
53            index += 1;
54        }
55        if index != length {
56            return Err(RespError::InvalidValue);
57        }
58        Ok(())
59    }
60
61    #[inline]
62    pub fn from_bytes(input: Bytes) -> Self {
63        Self(input)
64    }
65
66    #[inline]
67    pub fn from_slice(input: &[u8]) -> Self {
68        let bytes = Bytes::copy_from_slice(input);
69        Self::from_bytes(bytes)
70    }
71
72    #[inline]
73    pub unsafe fn from_raw(ptr: *mut u8, length: usize) -> Self {
74        let vector = Vec::from_raw_parts(ptr, length, length);
75        let bytes = Bytes::from(vector);
76        Self::from_bytes(bytes)
77    }
78
79    pub fn while_valid(input: &[u8], start: &mut usize, end: &usize) -> Result<(), RespError> {
80        let mut index = *start;
81        if index >= *end || input[index] != 0x2d {
82            return Err(RespError::InvalidFirstChar);
83        }
84        index += 1;
85        while index < *end && input[index] != 0x0d && input[index] != 0x0a {
86            index += 1;
87        }
88        if index + 1 >= *end || input[index] != 0x0d || input[index + 1] != 0x0a {
89            return Err(RespError::InvalidTerminate);
90        }
91        *start = index + 2;
92        Ok(())
93    }
94
95    pub fn parse(input: &[u8], start: &mut usize, end: &usize) -> Result<Self, RespError> {
96        let mut index = *start;
97        Self::while_valid(input, &mut index, end)?;
98        let value = Self::from_slice(&input[*start..index]);
99        *start = index;
100        Ok(value)
101    }
102}
103
104#[cfg(test)]
105mod tests_error {
106    use crate::error::Error;
107    use bytes::Bytes;
108
109    #[test]
110    fn test_new() {
111        let string = "Error message";
112        let error = Error::new(string.as_bytes());
113        assert_eq!(error, Error(Bytes::from_static(b"-Error message\r\n")));
114    }
115
116    #[test]
117    fn test_value() {
118        let error = Error(Bytes::from_static(b"-Error message\r\n"));
119        assert_eq!(error.value(), Vec::from("Error message"));
120        assert_eq!(error.value(), Vec::from("Error message"));
121    }
122
123    #[test]
124    fn test_bytes() {
125        let error = Error(Bytes::from_static(b"-Error message\r\n"));
126        assert_eq!(error.bytes(), Bytes::from_static(b"-Error message\r\n"));
127        assert_eq!(error.bytes(), Bytes::from_static(b"-Error message\r\n"));
128    }
129
130    #[test]
131    fn test_validate_valid_value() {
132        let value = b"Error message";
133        assert_eq!(Error::validate_value(value).unwrap(), ())
134    }
135
136    #[test]
137    #[should_panic(expected = "InvalidValue")]
138    fn test_validate_invalid_value() {
139        let value = b"Error\r\n message";
140        assert_eq!(Error::validate_value(value).unwrap(), ())
141    }
142
143    #[test]
144    fn test_parse() {
145        let string = "-invalid length\r\n+bar\r\n";
146        let mut cursor = 0;
147        let end = string.len();
148        assert_eq!(
149            Error::parse(string.as_bytes(), &mut cursor, &end).unwrap(),
150            Error::new("invalid length".as_bytes())
151        );
152        assert_eq!(cursor, 17);
153    }
154}