]> piware.de Git - learn-rust.git/blob - tokio-tutorial-mini-redis/src/main.rs
tokio-tutorial-mini-redis: Initial protocol
[learn-rust.git] / tokio-tutorial-mini-redis / src / main.rs
1 use std::collections::HashMap;
2
3 use mini_redis::{Connection, Frame};
4 use mini_redis::Command::{self, Get, Set};
5 use tokio::net::{TcpListener, TcpStream};
6
7 #[tokio::main]
8 async fn main() {
9     let listener = TcpListener::bind("127.0.0.1:6379").await.unwrap();
10
11     loop {
12         // The second item contains the IP and port of the new connection
13         let (socket, _) = listener.accept().await.unwrap();
14         tokio::spawn(async move { process(socket).await });
15     }
16 }
17
18 async fn process(socket: TcpStream) {
19     let mut db = HashMap::new();
20     let mut connection = Connection::new(socket);
21
22     while let Some(frame) = connection.read_frame().await.unwrap() {
23         let response = match Command::from_frame(frame).unwrap() {
24             Set(cmd) => {
25                 // The value is stored as `Vec<u8>`
26                 db.insert(cmd.key().to_string(), cmd.value().to_vec());
27                 Frame::Simple("OK".to_string())
28             }
29             Get(cmd) => {
30                 if let Some(value) = db.get(cmd.key()) {
31                     // `Frame::Bulk` expects data to be of type `Bytes`. This
32                     // type will be covered later in the tutorial. For now,
33                     // `&Vec<u8>` is converted to `Bytes` using `into()`.
34                     Frame::Bulk(value.clone().into())
35                 } else {
36                     Frame::Null
37                 }
38             }
39             cmd => panic!("unimplemented {:?}", cmd),
40         };
41
42         // Write the response to the client
43         connection.write_frame(&response).await.unwrap();
44     }
45 }