tokio_valkey/
lib.rs

1use tokio::{
2    io::{AsyncReadExt, AsyncWriteExt},
3    net::{TcpStream, ToSocketAddrs},
4};
5
6mod err;
7pub use err::{Error, Result};
8
9#[derive(Debug)]
10pub struct Client {
11    conn: TcpStream,
12}
13
14impl Client {
15    pub async fn connect<A: ToSocketAddrs>(addr: A) -> Result<Self> {
16        let conn = TcpStream::connect(addr).await?;
17        Ok(Self { conn })
18    }
19
20    /// Sets the string value of a key.
21    pub async fn set(&mut self, k: &str, v: &str) -> Result<()> {
22        let cmd = format!(
23            "*3\r\n${cmd_len}\r\nSET\r\n${k_len}\r\n{k}\r\n${v_len}\r\n{v}\r\n",
24            cmd_len = 3,
25            k_len = k.len(),
26            v_len = v.len(),
27        );
28
29        // send the command to the server
30        self.conn.write_all(cmd.as_bytes()).await?;
31        self.conn.flush().await?;
32
33        // read response
34        let mut buf = [0; 512];
35        let size = self.conn.read(&mut buf).await?;
36
37        let resp = String::from_utf8_lossy(&buf[..size]);
38        if resp.starts_with("+OK") {
39            Ok(())
40        } else {
41            Err(Error::Custom(resp.to_string()))
42        }
43    }
44
45    /// Gets the value of a key.
46    pub async fn get(&mut self, k: &str) -> Result<Option<String>> {
47        let cmd = format!(
48            "*2\r\n${cmd_len}\r\nGET\r\n${k_len}\r\n{k}\r\n",
49            cmd_len = 3,
50            k_len = k.len(),
51        );
52
53        // send the command to the server
54        self.conn.write_all(cmd.as_bytes()).await?;
55        self.conn.flush().await?;
56
57        // read response
58        let mut buf = [0; 512];
59        let size = self.conn.read(&mut buf).await?;
60
61        let resp = String::from_utf8_lossy(&buf[..size]);
62        if resp.starts_with("$-1") {
63            Ok(None)
64        } else {
65            let parts = resp.split("\r\n").collect::<Vec<_>>();
66            Ok(Some(parts[1].to_string()))
67        }
68    }
69}