Created
May 6, 2022 17:44
-
-
Save arjunsk/d40bf4f63936562e2883d5cfdd13bcd7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment