1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
use crate::{Connection, Db, Frame, Parse}; use bytes::Bytes; use tracing::{debug, instrument}; /// Get the value of key. /// /// If the key does not exist the special value nil is returned. An error is /// returned if the value stored at key is not a string, because GET only /// handles string values. #[derive(Debug)] pub struct Get { /// Name of the key to get key: String, } impl Get { /// Create a new `Get` command which fetches `key`. pub fn new(key: impl ToString) -> Get { Get { key: key.to_string(), } } /// Get the key pub fn key(&self) -> &str { &self.key } /// Parse a `Get` instance from a received frame. /// /// The `Parse` argument provides a cursor-like API to read fields from the /// `Frame`. At this point, the entire frame has already been received from /// the socket. /// /// The `GET` string has already been consumed. /// /// # Returns /// /// Returns the `Get` value on success. If the frame is malformed, `Err` is /// returned. /// /// # Format /// /// Expects an array frame containing two entries. /// /// ```text /// GET key /// ``` pub(crate) fn parse_frames(parse: &mut Parse) -> crate::Result<Get> { // The `GET` string has already been consumed. The next value is the // name of the key to get. If the next value is not a string or the // input is fully consumed, then an error is returned. let key = parse.next_string()?; Ok(Get { key }) } /// Apply the `Get` command to the specified `Db` instance. /// /// The response is written to `dst`. This is called by the server in order /// to execute a received command. #[instrument(skip(self, db, dst))] pub(crate) async fn apply(self, db: &Db, dst: &mut Connection) -> crate::Result<()> { // Get the value from the shared database state let response = if let Some(value) = db.get(&self.key) { // If a value is present, it is written to the client in "bulk" // format. Frame::Bulk(value) } else { // If there is no value, `Null` is written. Frame::Null }; debug!(?response); // Write the response back to the client dst.write_frame(&response).await?; Ok(()) } /// Converts the command into an equivalent `Frame`. /// /// This is called by the client when encoding a `Get` command to send to /// the server. pub(crate) fn into_frame(self) -> Frame { let mut frame = Frame::array(); frame.push_bulk(Bytes::from("get".as_bytes())); frame.push_bulk(Bytes::from(self.key.into_bytes())); frame } }