Skip to content

Commit 4d4fa85

Browse files
committed
parse rdb file
1 parent c2761ce commit 4d4fa85

11 files changed

+256
-101
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ target/
99

1010
# MSVC Windows builds of rustc generate these, which store debugging information
1111
*.pdb
12+
dumb.rdb

Cargo.lock

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

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ bytes = "1.3.0"
1010
thiserror = "1.0.32"
1111
tokio = { version = "1.23.0", features = ["full"] }
1212
clap = { version = "4.5.20", features = ["derive"] }
13+
byteorder = "1.4.3"
14+

src/cmd.rs

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{error::Error, protocol::Protocol, server::Server};
1+
use crate::{error::DBError, protocol::Protocol, server::Server};
22

33
pub enum Cmd {
44
Ping,
@@ -12,13 +12,13 @@ pub enum Cmd {
1212
}
1313

1414
impl Cmd {
15-
pub fn from(s: &str) -> Result<Self, Error> {
15+
pub fn from(s: &str) -> Result<Self, DBError> {
1616
let protocol = Protocol::from(s)?;
1717
match protocol.0 {
1818
Protocol::Array(p) => {
1919
let cmd = p.into_iter().map(|x| x.decode()).collect::<Vec<_>>();
2020
if cmd.len() == 0 {
21-
return Err(Error::E("cmd length is 0".to_string()));
21+
return Err(DBError("cmd length is 0".to_string()));
2222
}
2323
Ok(match cmd[0].as_str() {
2424
"echo" => Cmd::Echo(cmd[1].clone()),
@@ -35,34 +35,34 @@ impl Cmd {
3535
}
3636
"config" => {
3737
if cmd.len() != 3 || cmd[1] != "get" {
38-
return Err(Error::E(format!("unsupported cmd {:?}", cmd)));
38+
return Err(DBError(format!("unsupported cmd {:?}", cmd)));
3939
} else {
4040
Cmd::ConfigGet(cmd[2].clone())
4141
}
4242
}
4343
"keys" => {
4444
if cmd.len() != 2 || cmd[1] != "*" {
45-
return Err(Error::E(format!("unsupported cmd {:?}", cmd)));
45+
return Err(DBError(format!("unsupported cmd {:?}", cmd)));
4646
} else {
4747
Cmd::Keys
4848
}
4949
}
50-
_ => return Err(Error::E(format!("unknown cmd {:?}", cmd[0]))),
50+
_ => return Err(DBError(format!("unknown cmd {:?}", cmd[0]))),
5151
})
5252
}
53-
_ => Err(Error::E(format!(
53+
_ => Err(DBError(format!(
5454
"fail to parse as cmd for {:?}",
5555
protocol.0
5656
))),
5757
}
5858
}
5959

60-
pub fn run(self: &Self, server: &mut Server) -> Result<Protocol, String> {
60+
pub fn run(self: &Self, server: &mut Server) -> Result<Protocol, DBError> {
6161
match self {
6262
Cmd::Ping => Ok(Protocol::SimpleString("PONG".to_string())),
6363
Cmd::Echo(s) => Ok(Protocol::SimpleString(s.clone())),
6464
Cmd::Get(k) => {
65-
let s = server.storage.read().unwrap();
65+
let mut s = server.storage.lock().unwrap();
6666
Ok(if let Some(v) = s.get(k) {
6767
Protocol::SimpleString(v.clone())
6868
} else {
@@ -71,21 +71,21 @@ impl Cmd {
7171
}
7272
Cmd::Set(k, v) => {
7373
{
74-
let mut s = server.storage.write().unwrap();
74+
let mut s = server.storage.lock().unwrap();
7575
s.set(k.clone(), v.clone());
7676
}
7777
Ok(Protocol::ok())
7878
}
7979
Cmd::SetPx(k, v, x) => {
8080
{
81-
let mut s = server.storage.write().unwrap();
81+
let mut s = server.storage.lock().unwrap();
8282
s.setx(k.clone(), v.clone(), *x);
8383
}
8484
Ok(Protocol::ok())
8585
}
8686
Cmd::SetEx(k, v, x) => {
8787
{
88-
let mut s = server.storage.write().unwrap();
88+
let mut s = server.storage.lock().unwrap();
8989
s.setx(k.clone(), v.clone(), *x * 1000);
9090
}
9191
Ok(Protocol::ok())
@@ -99,10 +99,10 @@ impl Cmd {
9999
Protocol::BulkString(name.clone()),
100100
Protocol::BulkString(server.option.db_file_name.clone()),
101101
])),
102-
_ => Err(format!("unsupported config {:?}", name)),
102+
_ => Err(DBError(format!("unsupported config {:?}", name))),
103103
},
104104
Cmd::Keys => {
105-
let keys = { server.storage.read().unwrap().keys() };
105+
let keys = { server.storage.lock().unwrap().keys() };
106106
Ok(Protocol::Array(
107107
keys.into_iter().map(|x| Protocol::BulkString(x)).collect(),
108108
))

src/error.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,16 @@
1+
use std::num::ParseIntError;
12
// todo: more error types
2-
pub enum Error {
3-
E(String),
3+
#[derive(Debug)]
4+
pub struct DBError(pub String);
5+
6+
impl From<std::io::Error> for DBError {
7+
fn from(item: std::io::Error) -> Self {
8+
DBError(item.to_string().clone())
9+
}
10+
}
11+
12+
impl From<ParseIntError> for DBError {
13+
fn from(item: ParseIntError) -> Self {
14+
DBError(item.to_string().clone())
15+
}
416
}

src/main.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
use redis_rs::server;
44

55
use clap::Parser;
6-
use tokio::io::{AsyncReadExt, AsyncWriteExt};
76
use tokio::net::TcpListener;
87

98
/// Simple program to greet a person
@@ -25,6 +24,8 @@ async fn main() {
2524
let option = redis_rs::options::DBOption {
2625
dir: args.dir,
2726
db_file_name: args.dbfilename,
27+
redis_version: String::new(),
28+
place_holder: String::new(),
2829
};
2930

3031
let listener = TcpListener::bind("127.0.0.1:6379").await.unwrap();

src/options.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ pub struct DBOption {
33
pub dir: String,
44
pub db_file_name: String,
55
pub redis_version: String,
6+
pub place_holder: String,
67
}

src/protocol.rs

+18-16
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::error::Error;
1+
use crate::error::DBError;
22

33
#[derive(Debug)]
44
pub enum Protocol {
@@ -9,12 +9,12 @@ pub enum Protocol {
99
}
1010

1111
impl Protocol {
12-
pub fn from(protocol: &str) -> Result<(Self, usize), Error> {
12+
pub fn from(protocol: &str) -> Result<(Self, usize), DBError> {
1313
let ret = match protocol.chars().nth(0) {
1414
Some('+') => Self::parse_simple_string_sfx(&protocol[1..]),
1515
Some('$') => Self::parse_bulk_string_sfx(&protocol[1..]),
1616
Some('*') => Self::parse_array_sfx(&protocol[1..]),
17-
_ => Err(Error::E(format!(
17+
_ => Err(DBError(format!(
1818
"[from] unsupported protocol: {:?}",
1919
protocol
2020
))),
@@ -59,23 +59,23 @@ impl Protocol {
5959
}
6060
}
6161

62-
fn parse_simple_string_sfx(protocol: &str) -> Result<(Self, usize), Error> {
62+
fn parse_simple_string_sfx(protocol: &str) -> Result<(Self, usize), DBError> {
6363
match protocol.find("\r\n") {
6464
Some(x) => Ok((Self::SimpleString(protocol[..x].to_string()), x + 2)),
65-
_ => Err(Error::E(format!(
65+
_ => Err(DBError(format!(
6666
"[new simple string] unsupported protocol: {:?}",
6767
protocol
6868
))),
6969
}
7070
}
7171

72-
fn parse_bulk_string_sfx(protocol: &str) -> Result<(Self, usize), Error> {
72+
fn parse_bulk_string_sfx(protocol: &str) -> Result<(Self, usize), DBError> {
7373
if let Some(len) = protocol.find("\r\n") {
7474
let size = Self::parse_usize(&protocol[..len])?;
7575
if let Some(data_len) = protocol[len + 2..].find("\r\n") {
7676
let s = Self::parse_string(&protocol[len + 2..len + 2 + data_len])?;
7777
if size != s.len() {
78-
Err(Error::E(format!(
78+
Err(DBError(format!(
7979
"[new bulk string] unmatched string length in prototocl {:?}",
8080
protocol,
8181
)))
@@ -86,20 +86,20 @@ impl Protocol {
8686
))
8787
}
8888
} else {
89-
Err(Error::E(format!(
89+
Err(DBError(format!(
9090
"[new bulk string] unsupported protocol: {:?}",
9191
protocol
9292
)))
9393
}
9494
} else {
95-
Err(Error::E(format!(
95+
Err(DBError(format!(
9696
"[new bulk string] unsupported protocol: {:?}",
9797
protocol
9898
)))
9999
}
100100
}
101101

102-
fn parse_array_sfx(s: &str) -> Result<(Self, usize), Error> {
102+
fn parse_array_sfx(s: &str) -> Result<(Self, usize), DBError> {
103103
let mut offset = 0;
104104
match s.find("\r\n") {
105105
Some(x) => {
@@ -119,23 +119,25 @@ impl Protocol {
119119
}
120120
Ok((Protocol::Array(vec), offset))
121121
}
122-
_ => Err(Error::E(format!(
122+
_ => Err(DBError(format!(
123123
"[new array] unsupported protocol: {:?}",
124124
s
125125
))),
126126
}
127127
}
128128

129-
fn parse_usize(protocol: &str) -> Result<usize, Error> {
129+
fn parse_usize(protocol: &str) -> Result<usize, DBError> {
130130
match protocol.len() {
131-
0 => Err(Error::E(format!("parse usize error: {:?}", protocol))),
132-
_ => Ok(protocol.parse::<usize>().ok_or("")?),
131+
0 => Err(DBError(format!("parse usize error: {:?}", protocol))),
132+
_ => Ok(protocol
133+
.parse::<usize>()
134+
.map_err(|_| DBError(format!("parse usize error: {}", protocol)))?),
133135
}
134136
}
135137

136-
fn parse_string(protocol: &str) -> Result<String, Error> {
138+
fn parse_string(protocol: &str) -> Result<String, DBError> {
137139
match protocol.len() {
138-
0 => Err(Error::E(format!("parse usize error: {:?}", protocol))),
140+
0 => Err(DBError(format!("parse usize error: {:?}", protocol))),
139141
_ => Ok(protocol.to_string()),
140142
}
141143
}

0 commit comments

Comments
 (0)