Store values
We will now implement the process function to handle incoming commands. We will use a HashMap to store values. SET commands will insert into the HashMap and GET values will load them. Additionally, we will use a loop to accept more than one command per connection.
1. use tokio::net::TcpStream;
2. use mini_redis::{Connection, Frame};
4. async fn process(socket: TcpStream) {
5. use mini_redis::Command::{self, Get, Set};
6. use std::collections::HashMap;
8. // A hashmap is used to store data
9. let mut db = HashMap::new();
11. // Connection, provided by `mini-redis`, handles parsing frames from
12. // the socket
13. let mut connection = Connection::new(socket);
15. // Use `read_frame` to receive a command from the connection.
16. while let Some(frame) = connection.read_frame().await.unwrap() {
17. let response = match Command::from_frame(frame).unwrap() {
18. Set(cmd) => {
19. // The value is stored as `Vec<u8>`
20. db.insert(cmd.key().to_string(), cmd.value().to_vec());
21. Frame::Simple("OK".to_string())
22. }
23. Get(cmd) => {
24. if let Some(value) = db.get(cmd.key()) {
25. // `Frame::Bulk` expects data to be of type `Bytes`. This
26. // type will be covered later in the tutorial. For now,
27. // `&Vec<u8>` is converted to `Bytes` using `into()`.
28. Frame::Bulk(value.clone().into())
29. } else {
30. Frame::Null
31. }
32. }
33. cmd => panic!("unimplemented {:?}", cmd),
34. };
36. // Write the response to the client
37. connection.write_frame(&response).await.unwrap();
38. }
39. }
Now, start the server:
1. $ cargo run
and in a separate terminal window, run the hello-redis example:
1. $ cargo run --example hello-redis
Now, the output will be:
1. got value from the server; success=Some(b"world")
We can now get and set values, but there is a problem: The values are not shared between connections. If another socket connects and tries to GET the hello key, it will not find anything.
You can find the full code here.
In the next section, we will implement persisting data for all sockets.
