resp_protocol/integer/
mod.rs

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