1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use crate::RespError;
use bytes::{BufMut, Bytes, BytesMut};
#[derive(Debug, Clone, PartialEq)]
pub struct BulkString(Bytes);
impl BulkString {
pub fn new(input: &[u8]) -> Self {
let length_string = input.len().to_string();
let mut bytes = BytesMut::with_capacity(input.len() + length_string.len() + 5);
bytes.put_u8(0x24);
bytes.put_slice(length_string.as_bytes());
bytes.put_u8(0x0d);
bytes.put_u8(0x0a);
bytes.put_slice(input);
bytes.put_u8(0x0d);
bytes.put_u8(0x0a);
Self::from_bytes(bytes.freeze())
}
#[inline]
pub fn bytes(&self) -> Bytes {
self.0.clone()
}
#[inline]
pub fn len(&self) -> usize {
self.0.len()
}
#[inline]
pub fn from_bytes(input: Bytes) -> Self {
Self(input)
}
#[inline]
pub fn from_slice(input: &[u8]) -> Self {
let bytes = Bytes::copy_from_slice(input);
Self::from_bytes(bytes)
}
#[inline]
pub unsafe fn from_raw(ptr: *mut u8, length: usize) -> Self {
let vector = Vec::from_raw_parts(ptr, length, length);
let bytes = Bytes::from(vector);
Self::from_bytes(bytes)
}
pub fn while_valid(input: &[u8], start: &mut usize, end: &usize) -> Result<(), RespError> {
let mut index = *start;
if index >= *end || input[index] != 0x24 {
return Err(RespError::InvalidFirstChar);
}
index += 1;
if index + 1 >= *end
|| (input[index] == 0x30 && input[index + 1] >= 0x30 && input[index + 1] <= 0x39)
{
return Err(RespError::InvalidLength);
}
while index < *end && input[index] >= 0x30 && input[index] <= 0x39 {
index += 1;
}
if index + 1 >= *end || input[index] != 0x0d || input[index + 1] != 0x0a {
return Err(RespError::InvalidLengthSeparator);
}
let length = unsafe {
String::from_utf8_unchecked(input[*start + 1..index].to_vec())
.parse::<usize>()
.unwrap()
};
index += 2;
let value_start_index = index;
while index < *end
&& index - value_start_index <= length
&& input[index] != 0x0d
&& input[index] != 0x0a
{
index += 1;
}
if length != index - value_start_index {
return Err(RespError::LengthsNotMatch);
}
if index + 1 >= *end || input[index] != 0x0d || input[index + 1] != 0x0a {
return Err(RespError::InvalidTerminate);
}
*start = index + 2;
Ok(())
}
pub fn parse(input: &[u8], start: &mut usize, end: &usize) -> Result<Self, RespError> {
let mut index = *start;
Self::while_valid(input, &mut index, end)?;
let value = Self::from_slice(&input[*start..index]);
*start = index;
Ok(value)
}
}
#[cfg(test)]
mod tests_bulk_string {
use crate::BulkString;
#[test]
fn test_parse() {
let string = "$6\r\nfoobar\r\n:100\r\n";
let mut cursor = 0;
assert_eq!(
BulkString::parse(string.as_bytes(), &mut cursor, &string.len()).unwrap(),
BulkString::new(b"foobar")
);
assert_eq!(cursor, 12);
}
}