#![allow(non_snake_case)] use bytes::Bytes; use mini_redis::{Connection, Frame}; use std::collections::HashMap; use std::sync::{Arc, Mutex}; use tokio::net::{TcpListener, TcpStream}; type DataBase = Arc>>; #[tokio::main] async fn main() { // Bind the listener to the address let listener = TcpListener::bind("127.0.0.1:6379").await.unwrap(); println!("Listen {}", 6379); let db = Arc::new(Mutex::new(HashMap::new())); loop { // The second item contains the IP and port of the new connection. let (socket, _) = listener.accept().await.unwrap(); // Clone the handle to the hash map. let db = db.clone(); println!("Fetched"); // A new task is spawned for each inbound socket. The socket is // moved to the new task and processed there. tokio::spawn(async move { process(socket, db).await; }); } } async fn process(socket: TcpStream, db: DataBase) { use mini_redis::Command::{self, Get, Set}; // Connection, provided by `mini-redis`, handles parsing frames from // the socket let mut connection = Connection::new(socket); // Use `read_frame` to receive a command from the connection. while let Some(frame) = connection.read_frame().await.unwrap() { let response = match Command::from_frame(frame).unwrap() { Set(cmd) => { let mut db = db.lock().unwrap(); db.insert(cmd.key().to_string(), cmd.value().clone()); Frame::Simple("OK".to_string()) } Get(cmd) => { let db = db.lock().unwrap(); if let Some(value) = db.get(cmd.key()) { Frame::Bulk(value.clone()) } else { Frame::Null } } cmd => panic!("unimplemented {:?}", cmd), }; // Write the response to the client connection.write_frame(&response).await.unwrap(); } }