Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,23 @@ shlex = "1.3.0"
assert_cmd = "2.0.16"
predicates = "3.1.3"
testcontainers = "0.23.3"

[lints.clippy]
single_match = "warn"
single_match_else = "warn"
needless_match = "warn"
needless_late_init = "warn"
redundant_pattern_matching = "warn"
redundant_pattern = "warn"
redundant_guards = "warn"
collapsible_match = "warn"
match_single_binding = "warn"
match_same_arms = "warn"
match_ref_pats = "warn"
match_bool = "warn"
needless_bool = "deny"
unwrap_used = "warn"
expect_used = "warn"

[lints.rust]
unsafe_code = "forbid"
13 changes: 10 additions & 3 deletions examples/hello_redis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ async fn main() -> Result<()> {

for id in 0..num_clients {
let handle = tokio::spawn(async move {
let mut client = Client::connect("127.0.0.1:6379").await.unwrap();
let response = client.ping(Some("Redis".as_bytes())).await.unwrap();
let mut client = Client::connect("127.0.0.1:6379")
.await
.unwrap_or_else(|err| panic!("Failed to connect to Redis server: {:?}", err));
let response = client
.ping(Some("Redis".as_bytes()))
.await
.unwrap_or_else(|err| panic!("Failed to send PING command: {:?}", err));

if let Ok(string) = str::from_utf8(&response) {
println!("From client {id}, got: \"{}\"", string);
Expand All @@ -27,7 +32,9 @@ async fn main() -> Result<()> {
}

for handle in handles {
handle.await.unwrap();
handle.await.unwrap_or_else(|err| {
panic!("Failed to join thread: {:?}", err);
});
}

Ok(())
Expand Down
14 changes: 10 additions & 4 deletions src/bin/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ async fn main() -> Result<()> {

loop {
print!("{addr}> "); // Print the prompt
io::stdout().flush().unwrap(); // Flush the buffer
io::stdout().flush()?; // Flush the buffer

let mut input = String::new();
std::io::stdin().read_line(&mut input)?;
Expand All @@ -383,8 +383,12 @@ async fn main() -> Result<()> {
break;
}

let args = split(input).unwrap();
if args.is_empty() {
if let Some(args) = split(input) {
if args.is_empty() {
continue;
}
} else {
eprintln!("Error parsing input: {input}");
continue;
}

Expand Down Expand Up @@ -428,5 +432,7 @@ async fn main() -> Result<()> {
// TODO: catch signals like Ctrl+C and Ctrl+D
fn clear_screen() {
print!("\x1B[2J\x1B[1;1H"); // Clears the screen and moves the cursor to the top-left
std::io::stdout().flush().unwrap();
std::io::stdout().flush().unwrap_or_else(|_| {
eprintln!("Failed to clear screen");
});
}
37 changes: 18 additions & 19 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl Client {
/// * `Ok(HashMap<String, Vec<u8>>)` if the HELLO command is successful
/// * `Err(RedisError)` if an error occurs
pub async fn hello(&mut self, proto: Option<u8>) -> Result<HashMap<String, Vec<u8>>> {
let frame: Frame = Hello::new(proto).into_stream();
let frame: Frame = Hello::new(proto).try_into()?;

self.conn
.write_frame(&frame)
Expand Down Expand Up @@ -122,7 +122,7 @@ impl Client {
/// }
/// ```
pub async fn ping(&mut self, msg: Option<&[u8]>) -> Result<Vec<u8>> {
let frame: Frame = Ping::new(msg).into_stream();
let frame: Frame = Ping::new(msg).try_into()?;

self.conn
.write_frame(&frame)
Expand Down Expand Up @@ -168,7 +168,7 @@ impl Client {
/// }
/// ```
pub async fn get(&mut self, key: &str) -> Result<Option<Vec<u8>>> {
let frame: Frame = Get::new(key).into_stream();
let frame: Frame = Get::new(key).try_into()?;

self.conn
.write_frame(&frame)
Expand Down Expand Up @@ -215,7 +215,7 @@ impl Client {
/// }
/// ```
pub async fn get_ex(&mut self, key: &str, expiry: Option<Expiry>) -> Result<Option<Vec<u8>>> {
let frame: Frame = GetEx::new(key, expiry).into_stream();
let frame: Frame = GetEx::new(key, expiry).try_into()?;

self.conn.write_frame(&frame).await?;

Expand Down Expand Up @@ -272,7 +272,7 @@ impl Client {
/// let resp = client.set("mykey", "myvalue").await?;
/// }
pub async fn set(&mut self, key: &str, val: &[u8]) -> Result<Option<Vec<u8>>> {
let frame: Frame = Set::new(key, val).into_stream();
let frame: Frame = Set::new(key, val).try_into()?;

self.conn
.write_frame(&frame)
Expand Down Expand Up @@ -349,7 +349,7 @@ impl Client {
/// let resp = client.del(vec!["foo", "bar", "baz"]).await?;
/// }
pub async fn del(&mut self, keys: Vec<&str>) -> Result<u64> {
let frame: Frame = Del::new(keys).into_stream();
let frame: Frame = Del::new(keys).try_into()?;

self.conn
.write_frame(&frame)
Expand Down Expand Up @@ -390,7 +390,7 @@ impl Client {
/// let resp = client.exists(vec!["foo", "bar", "baz"]).await?;
/// }
pub async fn exists(&mut self, keys: Vec<&str>) -> Result<u64> {
let frame: Frame = Exists::new(keys).into_stream();
let frame: Frame = Exists::new(keys).try_into()?;

self.conn
.write_frame(&frame)
Expand Down Expand Up @@ -434,7 +434,7 @@ impl Client {
/// let resp = client.expire("mykey", 1).await?;
/// }
pub async fn expire(&mut self, key: &str, seconds: i64) -> Result<u64> {
let frame: Frame = Expire::new(key, seconds).into_stream();
let frame: Frame = Expire::new(key, seconds).try_into()?;

self.conn
.write_frame(&frame)
Expand Down Expand Up @@ -477,7 +477,7 @@ impl Client {
/// let resp = client.ttl("mykey").await?;
/// }
pub async fn ttl(&mut self, key: &str) -> Result<i64> {
let frame: Frame = Ttl::new(key).into_stream();
let frame: Frame = Ttl::new(key).try_into()?;

self.conn
.write_frame(&frame)
Expand Down Expand Up @@ -519,7 +519,7 @@ impl Client {
/// let resp = client.incr("mykey").await?;
/// }
pub async fn incr(&mut self, key: &str) -> Result<i64> {
let frame: Frame = Incr::new(key).into_stream();
let frame: Frame = Incr::new(key).try_into()?;

self.conn
.write_frame(&frame)
Expand Down Expand Up @@ -591,7 +591,7 @@ impl Client {
/// let resp = client.decr("mykey").await?;
/// }
pub async fn decr(&mut self, key: &str) -> Result<i64> {
let frame: Frame = Decr::new(key).into_stream();
let frame: Frame = Decr::new(key).try_into()?;

self.conn
.write_frame(&frame)
Expand Down Expand Up @@ -664,7 +664,7 @@ impl Client {
/// let resp = client.lpush("mykey", vec!["foo", "bar", "baz"]).await?;
/// }
pub async fn lpush(&mut self, key: &str, values: Vec<&[u8]>) -> Result<u64> {
let frame: Frame = LPush::new(key, values).into_stream();
let frame: Frame = LPush::new(key, values).try_into()?;

self.conn
.write_frame(&frame)
Expand Down Expand Up @@ -706,7 +706,7 @@ impl Client {
/// let resp = client.rpush("mykey", vec!["foo", "bar", "baz"]).await?;
/// }
pub async fn rpush(&mut self, key: &str, values: Vec<&[u8]>) -> Result<u64> {
let frame: Frame = RPush::new(key, values).into_stream();
let frame: Frame = RPush::new(key, values).try_into()?;

self.conn
.write_frame(&frame)
Expand Down Expand Up @@ -750,7 +750,7 @@ impl Client {
/// let resp = client.lpop("mykey", 1).await?;
/// }
pub async fn lpop(&mut self, key: &str) -> Result<Option<Vec<u8>>> {
let frame: Frame = LPop::new(key, None).into_stream();
let frame: Frame = LPop::new(key, None).try_into()?;

self.conn
.write_frame(&frame)
Expand All @@ -770,7 +770,7 @@ impl Client {
}

pub async fn lpop_n(&mut self, key: &str, count: u64) -> Result<Option<Vec<Vec<u8>>>> {
let frame: Frame = LPop::new(key, Some(count)).into_stream();
let frame: Frame = LPop::new(key, Some(count)).try_into()?;

self.conn
.write_frame(&frame)
Expand Down Expand Up @@ -815,7 +815,7 @@ impl Client {
/// let resp = client.rpop("mykey", 1).await?;
/// }
pub async fn rpop(&mut self, key: &str) -> Result<Option<Vec<u8>>> {
let frame: Frame = RPop::new(key, None).into_stream();
let frame: Frame = RPop::new(key, None).try_into()?;

self.conn
.write_frame(&frame)
Expand All @@ -835,7 +835,7 @@ impl Client {
}

pub async fn rpop_n(&mut self, key: &str, count: u64) -> Result<Option<Vec<Vec<u8>>>> {
let frame: Frame = RPop::new(key, Some(count)).into_stream();
let frame: Frame = RPop::new(key, Some(count)).try_into()?;

self.conn
.write_frame(&frame)
Expand Down Expand Up @@ -881,7 +881,7 @@ impl Client {
/// let resp = client.lrange("mykey", 0, -1).await?;
/// }
pub async fn lrange(&mut self, key: &str, start: i64, end: i64) -> Result<Vec<Vec<u8>>> {
let frame: Frame = LRange::new(key, start, end).into_stream();
let frame: Frame = LRange::new(key, start, end).try_into()?;

self.conn
.write_frame(&frame)
Expand Down Expand Up @@ -1363,7 +1363,6 @@ impl Client {
.collect::<Vec<_>>();
result.concat()
}
Frame::Null => vec![],
_ => vec![],
})
.collect();
Expand Down
25 changes: 13 additions & 12 deletions src/cmd/decr.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/// A Redis DECR command.
use crate::cmd::Command;
use crate::frame::Frame;
use crate::{Result, cmd::Command, frame::Frame};
use bytes::Bytes;

pub struct Decr {
Expand Down Expand Up @@ -30,17 +29,17 @@ impl Decr {
}
}

impl Command for Decr {
fn into_stream(self) -> Frame {
impl Command for Decr {}

impl TryInto<Frame> for Decr {
type Error = crate::RedisError;

fn try_into(self) -> Result<Frame> {
let mut frame: Frame = Frame::array();
frame
.push_frame_to_array(Frame::BulkString("DECR".into()))
.unwrap();
frame
.push_frame_to_array(Frame::BulkString(Bytes::from(self.key)))
.unwrap();
frame.push_frame_to_array(Frame::BulkString("DECR".into()))?;
frame.push_frame_to_array(Frame::BulkString(Bytes::from(self.key)))?;

frame
Ok(frame)
}
}

Expand All @@ -51,7 +50,9 @@ mod tests {
#[test]
fn test_decr() {
let decr = Decr::new("mykey");
let frame = decr.into_stream();
let frame: Frame = decr
.try_into()
.unwrap_or_else(|err| panic!("Failed to create DECR command: {:?}", err));

assert_eq!(
frame,
Expand Down
Loading