resp_protocol/bulk_string/
mod.rs1use crate::RespError;
2use bytes::{BufMut, Bytes, BytesMut};
3
4pub const EMPTY_BULK_STRING: BulkString = BulkString(Bytes::from_static(b"$0\r\n\r\n"));
5pub const NULL_BULK_STRING: BulkString = BulkString(Bytes::from_static(b"$-1\r\n"));
6
7#[derive(Debug, Clone, PartialEq)]
8pub struct BulkString(Bytes);
9
10impl BulkString {
11 pub fn new(input: &[u8]) -> Self {
20 let length = input.len();
21 if length == 0 {
22 return EMPTY_BULK_STRING;
23 }
24 let length_string = length.to_string();
25 let mut bytes = BytesMut::with_capacity(input.len() + length_string.len() + 5);
26 bytes.put_u8(0x24); bytes.put_slice(length_string.as_bytes());
28 bytes.put_u8(0x0d); bytes.put_u8(0x0a); bytes.put_slice(input);
31 bytes.put_u8(0x0d); bytes.put_u8(0x0a); Self::from_bytes(bytes.freeze())
34 }
35
36 #[inline]
46 pub fn is_empty(&self) -> bool {
47 self == EMPTY_BULK_STRING
48 }
49
50 #[inline]
60 pub fn is_null(&self) -> bool {
61 self == NULL_BULK_STRING
62 }
63
64 #[inline]
65 pub fn bytes(&self) -> Bytes {
66 self.0.clone()
67 }
68
69 #[inline]
70 pub fn len(&self) -> usize {
71 self.0.len()
72 }
73
74 #[inline]
75 pub fn from_bytes(input: Bytes) -> Self {
76 Self(input)
77 }
78
79 #[inline]
80 pub fn from_slice(input: &[u8]) -> Self {
81 let bytes = Bytes::copy_from_slice(input);
82 Self::from_bytes(bytes)
83 }
84
85 #[inline]
86 pub unsafe fn from_raw(ptr: *mut u8, length: usize) -> Self {
87 let vector = Vec::from_raw_parts(ptr, length, length);
88 let bytes = Bytes::from(vector);
89 Self::from_bytes(bytes)
90 }
91
92 pub fn while_valid(input: &[u8], start: &mut usize, end: &usize) -> Result<(), RespError> {
93 let mut index = *start;
94 if index + 4 >= *end {
95 return Err(RespError::InvalidValue);
96 }
97 if input[index] != 0x24 {
98 return Err(RespError::InvalidFirstChar);
99 }
100 index += 1;
101 if input[index] == 0x2d {
102 if input[index + 1] != 0x31 || input[index + 2] != 0x0d || input[index + 3] != 0x0a {
103 return Err(RespError::InvalidNullValue);
104 }
105 *start = index + 4;
106 return Ok(());
107 }
108 if input[index] == 0x30 && input[index + 1] >= 0x30 && input[index + 1] <= 0x39 {
109 return Err(RespError::InvalidLength);
110 }
111 while index < *end && input[index] >= 0x30 && input[index] <= 0x39 {
112 index += 1;
113 }
114 if index + 1 >= *end || input[index] != 0x0d || input[index + 1] != 0x0a {
115 return Err(RespError::InvalidLengthSeparator);
116 }
117 let length = unsafe {
118 String::from_utf8_unchecked(input[*start + 1..index].to_vec())
119 .parse::<usize>()
120 .unwrap()
121 };
122 index += 2;
123 let value_start_index = index;
124 while index < *end
125 && index - value_start_index <= length
126 && input[index] != 0x0d
127 && input[index] != 0x0a
128 {
129 index += 1;
130 }
131 if length != index - value_start_index {
132 return Err(RespError::LengthsNotMatch);
133 }
134 if index + 1 >= *end || input[index] != 0x0d || input[index + 1] != 0x0a {
135 return Err(RespError::InvalidTerminate);
136 }
137 *start = index + 2;
138 Ok(())
139 }
140
141 pub fn parse(input: &[u8], start: &mut usize, end: &usize) -> Result<Self, RespError> {
142 let mut index = *start;
143 Self::while_valid(input, &mut index, end)?;
144 let value = Self::from_slice(&input[*start..index]);
145 *start = index;
146 Ok(value)
147 }
148}
149
150impl<'a> PartialEq<BulkString> for &'a BulkString {
151 fn eq(&self, other: &BulkString) -> bool {
152 self.0 == other.bytes()
153 }
154 fn ne(&self, other: &BulkString) -> bool {
155 self.0 != other.bytes()
156 }
157}
158
159#[cfg(test)]
160mod tests_bulk_string {
161 use crate::{BulkString, EMPTY_BULK_STRING, NULL_BULK_STRING};
162 use bytes::Bytes;
163
164 #[test]
165 fn test_new() {
166 let bulk_string: BulkString = BulkString::new(b"foobar");
167 assert_eq!(bulk_string.bytes(), Bytes::from_static(b"$6\r\nfoobar\r\n"));
168 }
169
170 #[test]
171 fn test_new_empty() {
172 let bulk_string: BulkString = BulkString::new(b"");
173 assert_eq!(bulk_string.bytes(), Bytes::from_static(b"$0\r\n\r\n"));
174 }
175
176 #[test]
177 fn test_from_bytes() {
178 let bulk_string: BulkString =
179 BulkString::from_bytes(Bytes::from_static(b"$6\r\nfoobar\r\n"));
180 assert_eq!(bulk_string.bytes(), Bytes::from_static(b"$6\r\nfoobar\r\n"));
181 }
182
183 #[test]
184 fn test_from_slice() {
185 let bulk_string: BulkString =
186 BulkString::from_slice(Vec::from("$6\r\nfoobar\r\n").as_slice());
187 assert_eq!(bulk_string.bytes(), Bytes::from_static(b"$6\r\nfoobar\r\n"));
188 }
189
190 #[test]
191 fn test_is_empty() {
192 assert_eq!(EMPTY_BULK_STRING.is_empty(), true)
193 }
194
195 #[test]
196 fn test_is_null() {
197 assert_eq!(NULL_BULK_STRING.is_null(), true)
198 }
199
200 #[test]
201 fn test_parse() {
202 let string = "$6\r\nfoobar\r\n";
203 let mut cursor = 0;
204 assert_eq!(
205 BulkString::parse(string.as_bytes(), &mut cursor, &string.len()).unwrap(),
206 BulkString::new(b"foobar")
207 );
208 assert_eq!(cursor, 12);
209 }
210
211 #[test]
212 fn test_parse_empty() {
213 let string = "$0\r\n\r\n";
214 let mut cursor = 0;
215 assert_eq!(
216 BulkString::parse(string.as_bytes(), &mut cursor, &string.len()).unwrap(),
217 EMPTY_BULK_STRING
218 );
219 assert_eq!(cursor, 6);
220 }
221
222 #[test]
223 fn test_parse_null() {
224 let string = "$-1\r\n";
225 let mut cursor = 0;
226 assert_eq!(
227 BulkString::parse(string.as_bytes(), &mut cursor, &string.len()).unwrap(),
228 NULL_BULK_STRING
229 );
230 assert_eq!(cursor, 5);
231 }
232}