1use crate::core::{
7 error::{RedisError, RedisResult},
8 value::RespValue,
9};
10use bytes::{Buf, BufMut, Bytes, BytesMut};
11use std::io::Cursor;
12
13const CRLF: &[u8] = b"\r\n";
14
15pub struct RespEncoder;
17
18impl RespEncoder {
19 pub fn encode(value: &RespValue, buf: &mut BytesMut) -> RedisResult<()> {
21 match value {
22 RespValue::SimpleString(s) => {
23 buf.put_u8(b'+');
24 buf.put_slice(s.as_bytes());
25 buf.put_slice(CRLF);
26 }
27 RespValue::Error(e) => {
28 buf.put_u8(b'-');
29 buf.put_slice(e.as_bytes());
30 buf.put_slice(CRLF);
31 }
32 RespValue::Integer(i) => {
33 buf.put_u8(b':');
34 buf.put_slice(i.to_string().as_bytes());
35 buf.put_slice(CRLF);
36 }
37 RespValue::BulkString(data) => {
38 buf.put_u8(b'$');
39 buf.put_slice(data.len().to_string().as_bytes());
40 buf.put_slice(CRLF);
41 buf.put_slice(data);
42 buf.put_slice(CRLF);
43 }
44 RespValue::Null => {
45 buf.put_slice(b"$-1\r\n");
46 }
47 RespValue::Array(arr) => {
48 buf.put_u8(b'*');
49 buf.put_slice(arr.len().to_string().as_bytes());
50 buf.put_slice(CRLF);
51 for item in arr {
52 Self::encode(item, buf)?;
53 }
54 }
55 }
56 Ok(())
57 }
58
59 pub fn encode_command(command: &str, args: &[RespValue]) -> RedisResult<Bytes> {
61 let mut buf = BytesMut::new();
62
63 let total_len = 1 + args.len();
65 buf.put_u8(b'*');
66 buf.put_slice(total_len.to_string().as_bytes());
67 buf.put_slice(CRLF);
68
69 buf.put_u8(b'$');
71 buf.put_slice(command.len().to_string().as_bytes());
72 buf.put_slice(CRLF);
73 buf.put_slice(command.as_bytes());
74 buf.put_slice(CRLF);
75
76 for arg in args {
78 Self::encode(arg, &mut buf)?;
79 }
80
81 Ok(buf.freeze())
82 }
83}
84
85pub struct RespDecoder;
87
88impl RespDecoder {
89 pub fn decode(buf: &mut Cursor<&[u8]>) -> RedisResult<Option<RespValue>> {
91 if !buf.has_remaining() {
92 return Ok(None);
93 }
94
95 let type_byte = buf.chunk()[0];
96
97 match type_byte {
98 b'+' => Self::decode_simple_string(buf),
99 b'-' => Self::decode_error(buf),
100 b':' => Self::decode_integer(buf),
101 b'$' => Self::decode_bulk_string(buf),
102 b'*' => Self::decode_array(buf),
103 _ => Err(RedisError::Protocol(format!(
104 "Invalid RESP type byte: {}",
105 type_byte as char
106 ))),
107 }
108 }
109
110 fn decode_simple_string(buf: &mut Cursor<&[u8]>) -> RedisResult<Option<RespValue>> {
111 buf.advance(1); if let Some(line) = Self::read_line(buf)? {
114 Ok(Some(RespValue::SimpleString(
115 String::from_utf8(line.to_vec())
116 .map_err(|e| RedisError::Protocol(format!("Invalid UTF-8: {}", e)))?,
117 )))
118 } else {
119 Ok(None)
120 }
121 }
122
123 fn decode_error(buf: &mut Cursor<&[u8]>) -> RedisResult<Option<RespValue>> {
124 buf.advance(1); if let Some(line) = Self::read_line(buf)? {
127 Ok(Some(RespValue::Error(
128 String::from_utf8(line.to_vec())
129 .map_err(|e| RedisError::Protocol(format!("Invalid UTF-8: {}", e)))?,
130 )))
131 } else {
132 Ok(None)
133 }
134 }
135
136 fn decode_integer(buf: &mut Cursor<&[u8]>) -> RedisResult<Option<RespValue>> {
137 buf.advance(1); if let Some(line) = Self::read_line(buf)? {
140 let num_str = String::from_utf8(line.to_vec())
141 .map_err(|e| RedisError::Protocol(format!("Invalid UTF-8: {}", e)))?;
142 let num = num_str
143 .parse::<i64>()
144 .map_err(|e| RedisError::Protocol(format!("Invalid integer: {}", e)))?;
145 Ok(Some(RespValue::Integer(num)))
146 } else {
147 Ok(None)
148 }
149 }
150
151 fn decode_bulk_string(buf: &mut Cursor<&[u8]>) -> RedisResult<Option<RespValue>> {
152 buf.advance(1); let len_line = match Self::read_line(buf)? {
155 Some(line) => line,
156 None => return Ok(None),
157 };
158
159 let len_str = String::from_utf8(len_line.to_vec())
160 .map_err(|e| RedisError::Protocol(format!("Invalid UTF-8: {}", e)))?;
161 let len = len_str
162 .parse::<i64>()
163 .map_err(|e| RedisError::Protocol(format!("Invalid bulk string length: {}", e)))?;
164
165 if len == -1 {
166 return Ok(Some(RespValue::Null));
167 }
168
169 let len = len as usize;
170
171 if buf.remaining() < len + 2 {
173 return Ok(None);
174 }
175
176 let data = buf.chunk()[..len].to_vec();
177 buf.advance(len);
178
179 if buf.remaining() < 2 {
181 return Ok(None);
182 }
183 buf.advance(2);
184
185 Ok(Some(RespValue::BulkString(Bytes::from(data))))
186 }
187
188 fn decode_array(buf: &mut Cursor<&[u8]>) -> RedisResult<Option<RespValue>> {
189 buf.advance(1); let len_line = match Self::read_line(buf)? {
192 Some(line) => line,
193 None => return Ok(None),
194 };
195
196 let len_str = String::from_utf8(len_line.to_vec())
197 .map_err(|e| RedisError::Protocol(format!("Invalid UTF-8: {}", e)))?;
198 let len = len_str
199 .parse::<i64>()
200 .map_err(|e| RedisError::Protocol(format!("Invalid array length: {}", e)))?;
201
202 if len == -1 {
203 return Ok(Some(RespValue::Null));
204 }
205
206 let len = len as usize;
207 let mut arr = Vec::with_capacity(len);
208
209 for _ in 0..len {
210 match Self::decode(buf)? {
211 Some(value) => arr.push(value),
212 None => return Ok(None),
213 }
214 }
215
216 Ok(Some(RespValue::Array(arr)))
217 }
218
219 fn read_line(buf: &mut Cursor<&[u8]>) -> RedisResult<Option<Vec<u8>>> {
220 let start = buf.position() as usize;
221 let slice = buf.get_ref();
222
223 for i in start..slice.len().saturating_sub(1) {
225 if slice[i] == b'\r' && slice[i + 1] == b'\n' {
226 let line = slice[start..i].to_vec();
227 buf.set_position((i + 2) as u64);
228 return Ok(Some(line));
229 }
230 }
231
232 Ok(None)
233 }
234}
235
236#[cfg(test)]
237mod tests {
238 use super::*;
239
240 #[test]
241 fn test_encode_simple_string() {
242 let mut buf = BytesMut::new();
243 let value = RespValue::SimpleString("OK".to_string());
244 RespEncoder::encode(&value, &mut buf).unwrap();
245 assert_eq!(&buf[..], b"+OK\r\n");
246 }
247
248 #[test]
249 fn test_encode_error() {
250 let mut buf = BytesMut::new();
251 let value = RespValue::Error("ERR unknown command".to_string());
252 RespEncoder::encode(&value, &mut buf).unwrap();
253 assert_eq!(&buf[..], b"-ERR unknown command\r\n");
254 }
255
256 #[test]
257 fn test_encode_integer() {
258 let mut buf = BytesMut::new();
259 let value = RespValue::Integer(1000);
260 RespEncoder::encode(&value, &mut buf).unwrap();
261 assert_eq!(&buf[..], b":1000\r\n");
262 }
263
264 #[test]
265 fn test_encode_bulk_string() {
266 let mut buf = BytesMut::new();
267 let value = RespValue::BulkString(Bytes::from("foobar"));
268 RespEncoder::encode(&value, &mut buf).unwrap();
269 assert_eq!(&buf[..], b"$6\r\nfoobar\r\n");
270 }
271
272 #[test]
273 fn test_encode_null() {
274 let mut buf = BytesMut::new();
275 let value = RespValue::Null;
276 RespEncoder::encode(&value, &mut buf).unwrap();
277 assert_eq!(&buf[..], b"$-1\r\n");
278 }
279
280 #[test]
281 fn test_encode_array() {
282 let mut buf = BytesMut::new();
283 let value = RespValue::Array(vec![
284 RespValue::BulkString(Bytes::from("foo")),
285 RespValue::BulkString(Bytes::from("bar")),
286 ]);
287 RespEncoder::encode(&value, &mut buf).unwrap();
288 assert_eq!(&buf[..], b"*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n");
289 }
290
291 #[test]
292 fn test_encode_command() {
293 let bytes =
294 RespEncoder::encode_command("GET", &[RespValue::BulkString(Bytes::from("mykey"))])
295 .unwrap();
296 assert_eq!(&bytes[..], b"*2\r\n$3\r\nGET\r\n$5\r\nmykey\r\n");
297 }
298
299 #[test]
300 fn test_decode_simple_string() {
301 let data = b"+OK\r\n";
302 let mut cursor = Cursor::new(&data[..]);
303 let value = RespDecoder::decode(&mut cursor).unwrap().unwrap();
304 assert_eq!(value, RespValue::SimpleString("OK".to_string()));
305 }
306
307 #[test]
308 fn test_decode_error() {
309 let data = b"-ERR unknown\r\n";
310 let mut cursor = Cursor::new(&data[..]);
311 let value = RespDecoder::decode(&mut cursor).unwrap().unwrap();
312 assert_eq!(value, RespValue::Error("ERR unknown".to_string()));
313 }
314
315 #[test]
316 fn test_decode_integer() {
317 let data = b":1000\r\n";
318 let mut cursor = Cursor::new(&data[..]);
319 let value = RespDecoder::decode(&mut cursor).unwrap().unwrap();
320 assert_eq!(value, RespValue::Integer(1000));
321 }
322
323 #[test]
324 fn test_decode_bulk_string() {
325 let data = b"$6\r\nfoobar\r\n";
326 let mut cursor = Cursor::new(&data[..]);
327 let value = RespDecoder::decode(&mut cursor).unwrap().unwrap();
328 assert_eq!(value, RespValue::BulkString(Bytes::from("foobar")));
329 }
330
331 #[test]
332 fn test_decode_null() {
333 let data = b"$-1\r\n";
334 let mut cursor = Cursor::new(&data[..]);
335 let value = RespDecoder::decode(&mut cursor).unwrap().unwrap();
336 assert_eq!(value, RespValue::Null);
337 }
338
339 #[test]
340 fn test_decode_array() {
341 let data = b"*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n";
342 let mut cursor = Cursor::new(&data[..]);
343 let value = RespDecoder::decode(&mut cursor).unwrap().unwrap();
344 assert_eq!(
345 value,
346 RespValue::Array(vec![
347 RespValue::BulkString(Bytes::from("foo")),
348 RespValue::BulkString(Bytes::from("bar")),
349 ])
350 );
351 }
352
353 #[test]
354 fn test_decode_incomplete_data() {
355 let data = b"+OK\r";
356 let mut cursor = Cursor::new(&data[..]);
357 let result = RespDecoder::decode(&mut cursor).unwrap();
358 assert!(result.is_none());
359 }
360
361 #[test]
362 fn test_roundtrip() {
363 let original = RespValue::Array(vec![
364 RespValue::SimpleString("OK".to_string()),
365 RespValue::Integer(42),
366 RespValue::BulkString(Bytes::from("test")),
367 RespValue::Null,
368 ]);
369
370 let mut buf = BytesMut::new();
371 RespEncoder::encode(&original, &mut buf).unwrap();
372
373 let mut cursor = Cursor::new(&buf[..]);
374 let decoded = RespDecoder::decode(&mut cursor).unwrap().unwrap();
375
376 assert_eq!(original, decoded);
377 }
378}