tokio-tutorial-mini-redis: Initial protocol
authorMartin Pitt <martin@piware.de>
Fri, 16 Sep 2022 11:49:23 +0000 (13:49 +0200)
committerMartin Pitt <martin@piware.de>
Fri, 16 Sep 2022 11:49:23 +0000 (13:49 +0200)
Implement GET/SET, without shared state yet.

Move the original API demo as an example. Run it with

    cargo run --example hello-redis

tokio-tutorial-mini-redis/examples/hello-redis.rs [new file with mode: 0644]
tokio-tutorial-mini-redis/src/main.rs

diff --git a/tokio-tutorial-mini-redis/examples/hello-redis.rs b/tokio-tutorial-mini-redis/examples/hello-redis.rs
new file mode 100644 (file)
index 0000000..a498655
--- /dev/null
@@ -0,0 +1,17 @@
+use mini_redis::{client, Result};
+
+#[tokio::main]
+async fn main() -> Result<()> {
+    // Open a connection to the mini-redis address.
+    let mut client = client::connect("127.0.0.1:6379").await?;
+
+    // Set the key "hello" with value "world"
+    client.set("hello", "world".into()).await?;
+
+    // Get key "hello"
+    let result = client.get("hello").await?;
+
+    println!("got value from the server; result={:?}", result);
+
+    Ok(())
+}
index a49865584dc70a67904e2e95634c4e5cbfe01a62..d255ab36c270eb741ebc9f22c18d0a02aff6448a 100644 (file)
@@ -1,17 +1,45 @@
-use mini_redis::{client, Result};
+use std::collections::HashMap;
+
+use mini_redis::{Connection, Frame};
+use mini_redis::Command::{self, Get, Set};
+use tokio::net::{TcpListener, TcpStream};
 
 #[tokio::main]
-async fn main() -> Result<()> {
-    // Open a connection to the mini-redis address.
-    let mut client = client::connect("127.0.0.1:6379").await?;
+async fn main() {
+    let listener = TcpListener::bind("127.0.0.1:6379").await.unwrap();
 
-    // Set the key "hello" with value "world"
-    client.set("hello", "world".into()).await?;
+    loop {
+        // The second item contains the IP and port of the new connection
+        let (socket, _) = listener.accept().await.unwrap();
+        tokio::spawn(async move { process(socket).await });
+    }
+}
 
-    // Get key "hello"
-    let result = client.get("hello").await?;
+async fn process(socket: TcpStream) {
+    let mut db = HashMap::new();
+    let mut connection = Connection::new(socket);
 
-    println!("got value from the server; result={:?}", result);
+    while let Some(frame) = connection.read_frame().await.unwrap() {
+        let response = match Command::from_frame(frame).unwrap() {
+            Set(cmd) => {
+                // The value is stored as `Vec<u8>`
+                db.insert(cmd.key().to_string(), cmd.value().to_vec());
+                Frame::Simple("OK".to_string())
+            }
+            Get(cmd) => {
+                if let Some(value) = db.get(cmd.key()) {
+                    // `Frame::Bulk` expects data to be of type `Bytes`. This
+                    // type will be covered later in the tutorial. For now,
+                    // `&Vec<u8>` is converted to `Bytes` using `into()`.
+                    Frame::Bulk(value.clone().into())
+                } else {
+                    Frame::Null
+                }
+            }
+            cmd => panic!("unimplemented {:?}", cmd),
+        };
 
-    Ok(())
+        // Write the response to the client
+        connection.write_frame(&response).await.unwrap();
+    }
 }