Skip to content

Commit

Permalink
commit
Browse files Browse the repository at this point in the history
  • Loading branch information
kindywu committed Aug 2, 2024
1 parent 780631a commit 1b636ca
Show file tree
Hide file tree
Showing 6 changed files with 580 additions and 43 deletions.
18 changes: 17 additions & 1 deletion benches/resp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ use simple_redis::RespFrame;
// cmd 4 response: value
// cmd 5: sadd key member
// cmd 5 response: 1
const DATA: &str = "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n*1\r\n+OK\r\n*2\r\n$3\r\nGET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n*4\r\n$4\r\nHSET\r\n$3\r\nkey\r\n$5\r\nfield\r\n$5\r\nvalue\r\n*1\r\n-ERR\r\n*3\r\n$4\r\nHGET\r\n$3\r\nkey\r\n$5\r\nfield\r\n$5\r\nvalue\r\n*3\r\n$4\r\nSADD\r\n$3\r\nkey\r\n$6\r\nmember\r\n:1\r\n";
// const DATA: &str = "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n*1\r\n+OK\r\n*2\r\n$3\r\nGET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n*4\r\n$4\r\nHSET\r\n$3\r\nkey\r\n$5\r\nfield\r\n$5\r\nvalue\r\n*1\r\n-ERR\r\n*3\r\n$4\r\nHGET\r\n$3\r\nkey\r\n$5\r\nfield\r\n$5\r\nvalue\r\n*3\r\n$4\r\nSADD\r\n$3\r\nkey\r\n$6\r\nmember\r\n:1\r\n";

const DATA: &str = "*3\r\n$4\r\necho\r\n$5\r\nhello\r\n+OK\r\n";

fn v1_decode(buf: &mut BytesMut) -> Result<Vec<RespFrame>> {
use simple_redis::RespDecode;
Expand All @@ -36,6 +38,16 @@ fn v2_decode(buf: &mut BytesMut) -> Result<Vec<RespFrame>> {
Ok(frames)
}

fn v3_decode(buf: &mut BytesMut) -> Result<Vec<RespFrame>> {
use simple_redis::RespDecodeV3;
let mut frames = Vec::new();
while !buf.is_empty() {
let frame = RespFrame::decode(buf)?;
frames.push(frame);
}
Ok(frames)
}

fn criterion_benchmark(c: &mut Criterion) {
let buf = BytesMut::from(DATA);

Expand All @@ -46,6 +58,10 @@ fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("v2_decode", |b| {
b.iter(|| black_box(v2_decode(&mut buf.clone())))
});

c.bench_function("v3_decode", |b| {
b.iter(|| black_box(v3_decode(&mut buf.clone())))
});
}

criterion_group!(benches, criterion_benchmark);
Expand Down
195 changes: 153 additions & 42 deletions examples/expect_length.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use simple_redis::RespError;
use winnow::{
ascii::dec_int,
ascii::{crlf, dec_int},
combinator::terminated,
stream::AsChar,
token::{take, take_until},
Expand Down Expand Up @@ -31,81 +31,192 @@ fn main() {
// expect_length(buf).unwrap();
// let buf = b"*0\r\n";
// expect_length(buf).unwrap();
let buf = b"*2\r\n$4\r\necho\r\n$5\r\nhello\r\n";
// let buf = b"*2\r\n$4\r\necho\r\n$5\r\nhello\r\n";
// expect_length(buf).unwrap();

let buf = b"%2\r\n+hello\r\n$5\r\nworld\r\n+foo\r\n$3\r\nbar\r\n";
expect_length(buf).unwrap();
}

fn expect_length(input: &[u8]) -> Result<usize, RespError> {
match expect_length_inner(input) {
Ok(v) => {
println!("input:{}, remain: {:?}, len:{}", input.len(), v.0, v.1 + 1);
Ok(v.1 + 1)
println!("input:{}, remain: {:?}, len:{}", input.len(), v.0, v.1);
Ok(v.1)
}
Err(_) => Err(RespError::NotComplete),
}
}

fn expect_length_inner(input: &[u8]) -> PResult<(&[u8], usize)> {
Ok(match take(1usize).parse_peek(input)? {
(i, b"+") => cal_by_crlf(i)?,
let (remain, len) = match take(1usize).parse_peek(input)? {
(i, b"+") => cal_util_crlf(i)?,
(i, b"$") => cal_by_len(i)?,
(i, b"*") => array_length(i)?,
(i, b"*") => cal_array(i)?,
(i, b"%") => cal_map(i)?,
(i, p) => {
println!("{:?} {i:?}", p[0].as_char());
unreachable!()
}
})
};
Ok((remain, len + 1))
}

fn cal_by_crlf(input: &[u8]) -> PResult<(&[u8], usize)> {
// \r\n
#[inline]
fn cal_crlf(input: &[u8]) -> PResult<(&[u8], usize)> {
let (remain, found) = crlf.parse_peek(input)?;
Ok((remain, found.len()))
}

// +OK\r\n
#[inline]
fn cal_util_crlf(input: &[u8]) -> PResult<(&[u8], usize)> {
let (remain, found) = terminated(take_until(0.., CRLF), CRLF).parse_peek(input)?;
Ok((remain, found.len() + 2))
}

#[inline]
fn cal_by_len(input: &[u8]) -> PResult<(&[u8], usize)> {
let (remain, len): (&[u8], i64) = dec_int.parse_peek(input)?;

if len <= 0 {
let (remain, size) = cal_by_crlf(remain)?;
let mut total = if len == 0 { 1 } else { 2 };
if len == -1 {
let mut total = 2;
let (remain, size) = cal_crlf(remain)?;
total += size;
return Ok((remain, total));
} else if len == 0 {
let mut total = 1;
let (remain, size) = cal_crlf(remain)?;
total += size;
Ok((remain, total))
} else {
let len = len as usize;
let mut total = len / 10 + 1;
let (remain, size) = cal_by_crlf(remain)?;
let (remain, size) = cal_crlf(remain)?;
total += size;
let (remain, found) = take(len).parse_peek(remain)?;
total += found.len();
let (remain, size) = cal_by_crlf(remain)?;
return Ok((remain, total));
}

let len = len as usize;
let mut total = len / 10 + 1;
let (remain, size) = cal_crlf(remain)?;
total += size;
let (remain, found) = take(len).parse_peek(remain)?;
total += found.len();
let (remain, size) = cal_crlf(remain)?;
total += size;
Ok((remain, total))
}

#[inline]
fn cal_array(input: &[u8]) -> PResult<(&[u8], usize)> {
let (remain, len): (&[u8], i64) = dec_int.parse_peek(input.as_ref())?;
if len == 0 {
let (remain, size) = cal_crlf(remain)?;
return Ok((remain, size + 1));
} else if len == -1 {
let (remain, size) = cal_crlf(remain)?;
return Ok((remain, size + 2));
}

let len = len as usize;
let mut total = len / 10 + 1;
let (mut r1, size) = cal_crlf(remain)?;
total += size;

for _ in 0..len {
let (r2, size) = expect_length_inner(r1)?;
total += size;
Ok((remain, total))
r1 = r2;
}

Ok((r1, total))
}

fn array_length(input: &[u8]) -> PResult<(&[u8], usize)> {
#[inline]
fn cal_map(input: &[u8]) -> PResult<(&[u8], usize)> {
// 2\r\n+hello\r\n$5\r\nworld\r\n+foo\r\n$3\r\nbar\r\n

let (remain, len): (&[u8], i64) = dec_int.parse_peek(input.as_ref())?;
if len == 0 {
let (remain, size) = cal_crlf(remain)?;
return Ok((remain, size + 1));
} else if len == -1 {
let (remain, size) = cal_crlf(remain)?;
return Ok((remain, size + 2));
}

let len = len as usize;
let mut total = len / 10 + 1;
let (mut r1, size) = cal_crlf(remain)?;
total += size;

for _ in 0..len {
let (r2, size) = expect_length_inner(r1)?;
total += size;

if len <= 0 {
let (remain, size) = cal_by_crlf(remain)?;
let mut total = if len == 0 { 1 } else { 2 };
let (r3, size) = expect_length_inner(r2)?;
total += size;
Ok((remain, total))
} else {
let mut len = len as usize;
let mut total = len / 10 + 1;

let remain = loop {
let (remain, size) = cal_by_crlf(remain)?;
total += size;
let (remain, size) = expect_length_inner(remain)?;
total += size;
len -= 1;
if len == 0 {
break remain;
}
};

Ok((remain, total))
r1 = r3;
}

Ok((r1, total))
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn cal_crlf_should_work() -> PResult<()> {
let buf = b"\r\n";
let result = cal_crlf(buf)?;
assert_eq!(buf.len(), result.1);
Ok(())
}

#[test]
fn cal_util_crlf_should_work() -> PResult<()> {
let buf = b"OK\r\n";
let result = cal_util_crlf(buf)?;
assert_eq!(buf.len(), result.1);
Ok(())
}

#[test]
fn cal_by_len_should_work() -> PResult<()> {
let buf = b"0\r\n\r\n";
let result = cal_by_len(buf)?;
assert_eq!(buf.len(), result.1);

let buf = b"-1\r\n";
let result = cal_by_len(buf)?;
assert_eq!(buf.len(), result.1);

let buf = b"5\r\nhello\r\n";
let result = cal_by_len(buf)?;
assert_eq!(buf.len(), result.1);
Ok(())
}

#[test]
fn cal_array_should_work() -> PResult<()> {
let buf = b"-1\r\n";
let result = cal_array(buf)?;
assert_eq!(buf.len(), result.1);

let buf = b"0\r\n";
let result = cal_array(buf)?;
assert_eq!(buf.len(), result.1);

let buf = b"2\r\n$4\r\necho\r\n$5\r\nhello\r\n";
let result = cal_array(buf)?;
assert_eq!(buf.len(), result.1);
Ok(())
}

#[test]
fn cal_map_should_work() -> PResult<()> {
let buf = b"2\r\n+hello\r\n$5\r\nworld\r\n+foo\r\n*2\r\n$4\r\necho\r\n$5\r\nhello\r\n";
let result = cal_map(buf)?;
assert_eq!(buf.len(), result.1);
Ok(())
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod backend;
mod cmd;
mod resp;
mod respv2;
mod respv3;

pub use backend::*;
pub use cmd::*;
Expand All @@ -11,3 +12,4 @@ pub use resp::{
};
// pub use resp::*;
pub use respv2::RespDecodeV2;
pub use respv3::RespDecodeV3;
1 change: 1 addition & 0 deletions src/resp/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ impl RespDecode for RespFrame {
Some(b'*') => Option::<RespArray>::expect_length(buf),
Some(b'$') => Option::<BulkString>::expect_length(buf),
Some(b'+') => SimpleString::expect_length(buf),
Some(b'-') => SimpleError::expect_length(buf),
_ => Err(RespError::NotComplete),
}
}
Expand Down
Loading

0 comments on commit 1b636ca

Please sign in to comment.