Skip to content

Commit 50f6744

Browse files
committed
feature: use winnow to parse resp protocol
1 parent 9f24708 commit 50f6744

File tree

8 files changed

+397
-1
lines changed

8 files changed

+397
-1
lines changed

Cargo.lock

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ tokio-stream = "0.1.15"
1818
tokio-util = { version = "0.7.10", features = ["codec"] }
1919
tracing = "0.1.40"
2020
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
21+
winnow = { version = "0.6.8", features = ["simd"] }

src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
mod backend;
22
mod resp;
3+
mod respv2;
34

45
pub mod cmd;
56
pub mod network;
67

78
pub use backend::*;
89
pub use resp::*;
10+
pub use respv2::*;

src/network.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
cmd::{Command, CommandExecutor},
3-
Backend, RespDecode, RespEncode, RespError, RespFrame,
3+
Backend, RespDecodeV2, RespEncode, RespError, RespFrame,
44
};
55
use anyhow::Result;
66
use futures::SinkExt;

src/resp/array.rs

+6
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ impl Deref for RespArray {
8686
}
8787
}
8888

89+
impl From<Vec<RespFrame>> for RespArray {
90+
fn from(s: Vec<RespFrame>) -> Self {
91+
RespArray(s)
92+
}
93+
}
94+
8995
#[cfg(test)]
9096
mod tests {
9197
use super::*;

src/resp/map.rs

+6
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ impl DerefMut for RespMap {
8080
}
8181
}
8282

83+
impl From<BTreeMap<String, RespFrame>> for RespMap {
84+
fn from(map: BTreeMap<String, RespFrame>) -> Self {
85+
RespMap(map)
86+
}
87+
}
88+
8389
#[cfg(test)]
8490
mod tests {
8591
use super::*;

src/respv2/mod.rs

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
mod parser;
2+
3+
use self::parser::parse_frame_length;
4+
use crate::{RespError, RespFrame};
5+
use bytes::BytesMut;
6+
use parser::parse_frame;
7+
8+
pub trait RespDecodeV2: Sized {
9+
fn decode(buf: &mut BytesMut) -> Result<Self, RespError>;
10+
fn expect_length(buf: &[u8]) -> Result<usize, RespError>;
11+
}
12+
13+
impl RespDecodeV2 for RespFrame {
14+
fn decode(buf: &mut BytesMut) -> Result<Self, RespError> {
15+
let len = Self::expect_length(buf)?;
16+
let data = buf.split_to(len);
17+
18+
parse_frame(&mut data.as_ref()).map_err(|e| RespError::InvalidFrame(e.to_string()))
19+
}
20+
21+
fn expect_length(buf: &[u8]) -> Result<usize, RespError> {
22+
parse_frame_length(buf)
23+
}
24+
}
25+
26+
#[cfg(test)]
27+
mod tests {
28+
use super::*;
29+
use crate::{RespNullArray, RespNullBulkString};
30+
use std::collections::BTreeMap;
31+
32+
#[test]
33+
fn respv2_simple_string_length_should_work() {
34+
let buf = b"+OK\r\n";
35+
let len = RespFrame::expect_length(buf).unwrap();
36+
assert_eq!(len, buf.len());
37+
}
38+
39+
#[test]
40+
fn respv2_simple_string_bad_length_should_fail() {
41+
let buf = b"+OK\r";
42+
let err = RespFrame::expect_length(buf).unwrap_err();
43+
assert_eq!(err, RespError::NotComplete);
44+
}
45+
46+
#[test]
47+
fn respv2_simple_string_should_work() {
48+
let mut buf = BytesMut::from("+OK\r\n");
49+
let frame = RespFrame::decode(&mut buf).unwrap();
50+
assert_eq!(frame, RespFrame::SimpleString("OK".into()));
51+
}
52+
53+
#[test]
54+
fn respv2_simple_error_length_should_work() {
55+
let buf = b"-ERR\r\n";
56+
let len = RespFrame::expect_length(buf).unwrap();
57+
assert_eq!(len, buf.len());
58+
}
59+
60+
#[test]
61+
fn respv2_simple_error_should_work() {
62+
let mut buf = BytesMut::from("-ERR\r\n");
63+
let frame = RespFrame::decode(&mut buf).unwrap();
64+
assert_eq!(frame, RespFrame::Error("ERR".into()));
65+
}
66+
67+
#[test]
68+
fn respv2_integer_length_should_work() {
69+
let buf = b":1000\r\n";
70+
let len = RespFrame::expect_length(buf).unwrap();
71+
assert_eq!(len, buf.len());
72+
}
73+
74+
#[test]
75+
fn respv2_integer_should_work() {
76+
let mut buf = BytesMut::from(":1000\r\n");
77+
let frame = RespFrame::decode(&mut buf).unwrap();
78+
assert_eq!(frame, RespFrame::Integer(1000));
79+
}
80+
81+
#[test]
82+
fn respv2_bulk_string_length_should_work() {
83+
let buf = b"$6\r\nfoobar\r\n";
84+
let len = RespFrame::expect_length(buf).unwrap();
85+
assert_eq!(len, buf.len());
86+
}
87+
88+
#[test]
89+
fn respv2_bulk_string_should_work() {
90+
let mut buf = BytesMut::from("$6\r\nfoobar\r\n");
91+
let frame = RespFrame::decode(&mut buf).unwrap();
92+
assert_eq!(frame, RespFrame::BulkString("foobar".into()));
93+
}
94+
95+
#[test]
96+
fn respv2_null_bulk_string_length_should_work() {
97+
let buf = b"$-1\r\n";
98+
let len = RespFrame::expect_length(buf).unwrap();
99+
assert_eq!(len, buf.len());
100+
}
101+
102+
#[test]
103+
fn respv2_null_bulk_string_should_work() {
104+
let mut buf = BytesMut::from("$-1\r\n");
105+
let frame = RespFrame::decode(&mut buf).unwrap();
106+
assert_eq!(frame, RespFrame::NullBulkString(RespNullBulkString));
107+
}
108+
109+
#[test]
110+
fn respv2_array_length_should_work() {
111+
let buf = b"*2\r\n+OK\r\n-ERR\r\n";
112+
let len = RespFrame::expect_length(buf).unwrap();
113+
assert_eq!(len, buf.len());
114+
}
115+
116+
#[test]
117+
fn respv2_array_should_work() {
118+
let mut buf = BytesMut::from("*2\r\n+OK\r\n-ERR\r\n");
119+
let frame = RespFrame::decode(&mut buf).unwrap();
120+
assert_eq!(
121+
frame,
122+
RespFrame::Array(
123+
vec![
124+
RespFrame::SimpleString("OK".into()),
125+
RespFrame::Error("ERR".into())
126+
]
127+
.into()
128+
)
129+
);
130+
}
131+
132+
#[test]
133+
fn respv2_null_array_length_should_work() {
134+
let buf = b"*-1\r\n";
135+
let len = RespFrame::expect_length(buf).unwrap();
136+
assert_eq!(len, buf.len());
137+
}
138+
139+
#[test]
140+
fn respv2_null_array_should_work() {
141+
let mut buf = BytesMut::from("*-1\r\n");
142+
let frame = RespFrame::decode(&mut buf).unwrap();
143+
assert_eq!(frame, RespFrame::NullArray(RespNullArray));
144+
}
145+
146+
#[test]
147+
fn respv2_map_length_should_work() {
148+
let buf = b"%2\r\n+OK\r\n-ERR\r\n";
149+
let len = RespFrame::expect_length(buf).unwrap();
150+
assert_eq!(len, buf.len());
151+
}
152+
153+
#[test]
154+
fn respv2_map_should_work() {
155+
let mut buf = BytesMut::from("%2\r\n+OK\r\n-ERR\r\n");
156+
let frame = RespFrame::decode(&mut buf).unwrap();
157+
let items: BTreeMap<String, RespFrame> =
158+
[("OK".to_string(), RespFrame::Error("ERR".into()))]
159+
.into_iter()
160+
.collect();
161+
assert_eq!(frame, RespFrame::Map(items.into()));
162+
}
163+
}

0 commit comments

Comments
 (0)