fast-cache 0.1.0

Embedded-first thread-per-core in-memory cache with optional Redis-compatible server
Documentation
use crate::Result;
use crate::commands::{BorrowedCommandBox, CommandCatalog, OwnedCommandBox};
use crate::protocol::{BorrowedCommandFrame, Frame, RespCodec};

#[derive(Debug)]
pub struct Command {
    inner: OwnedCommandBox,
}

impl Command {
    pub(crate) fn new(inner: OwnedCommandBox) -> Self {
        Self { inner }
    }

    pub fn from_frame(frame: Frame) -> Result<Self> {
        let parts = RespCodec::as_command(frame)?.parts;
        CommandCatalog::parse_owned(&parts)
    }

    pub fn name(&self) -> &'static str {
        self.inner.name()
    }

    pub fn mutates_value(&self) -> bool {
        self.inner.mutates_value()
    }

    pub fn route_key(&self) -> Option<&[u8]> {
        self.inner.route_key()
    }

    pub(crate) fn to_borrowed_command(&self) -> BorrowedCommand<'_> {
        BorrowedCommand::new(self.inner.to_borrowed_command())
    }
}

#[derive(Debug)]
pub struct BorrowedCommand<'a> {
    inner: BorrowedCommandBox<'a>,
}

impl<'a> BorrowedCommand<'a> {
    pub(crate) fn new(inner: BorrowedCommandBox<'a>) -> Self {
        Self { inner }
    }

    pub fn from_frame(frame: BorrowedCommandFrame<'a>) -> Result<Self> {
        Self::from_parts(&frame.parts)
    }

    pub fn from_parts(parts: &[&'a [u8]]) -> Result<Self> {
        CommandCatalog::parse_borrowed(parts).map(Self::new)
    }

    pub fn name(&self) -> &'static str {
        self.inner.name()
    }

    pub fn mutates_value(&self) -> bool {
        self.inner.mutates_value()
    }

    pub fn route_key(&self) -> Option<&'a [u8]> {
        self.inner.route_key()
    }

    pub(crate) fn supports_spanned_resp(&self) -> bool {
        self.inner.supports_spanned_resp()
    }

    pub fn to_owned_command(&self) -> Command {
        self.inner.to_owned_command()
    }

    pub(crate) fn execute_engine<'b>(
        &'b self,
        ctx: crate::storage::EngineCommandContext<'b>,
    ) -> crate::storage::EngineFrameFuture<'b>
    where
        'a: 'b,
    {
        self.inner.execute_engine(ctx)
    }

    #[cfg(feature = "server")]
    pub(crate) fn execute_borrowed_frame(
        &self,
        store: &crate::storage::EmbeddedStore,
        now_ms: u64,
    ) -> Frame {
        self.inner.execute_borrowed_frame(store, now_ms)
    }

    #[cfg(feature = "server")]
    pub(crate) fn execute_borrowed(
        &self,
        ctx: crate::server::commands::BorrowedCommandContext<'_, '_, '_>,
    ) {
        self.inner.execute_borrowed(ctx);
    }

    #[cfg(feature = "server")]
    pub(crate) fn execute_direct_borrowed(
        &self,
        ctx: crate::server::commands::DirectCommandContext,
    ) -> Frame {
        self.inner.execute_direct_borrowed(ctx)
    }
}

#[cfg(test)]
mod tests {
    use crate::commands::CommandCatalog;
    use crate::protocol::Frame;

    use super::{BorrowedCommand, Command};

    #[test]
    fn parses_set_with_ttl() {
        let command = Command::from_frame(Frame::Array(vec![
            Frame::BlobString(b"SET".to_vec()),
            Frame::BlobString(b"alpha".to_vec()),
            Frame::BlobString(b"beta".to_vec()),
            Frame::BlobString(b"EX".to_vec()),
            Frame::BlobString(b"5".to_vec()),
        ]))
        .unwrap();

        assert_eq!(command.name(), "SET");
        assert!(command.mutates_value());
        assert_eq!(command.route_key(), Some(b"alpha".as_slice()));
    }

    #[test]
    fn parses_get_command() {
        let command =
            BorrowedCommand::from_parts(&[b"GET".as_slice(), b"alpha".as_slice()]).unwrap();

        assert_eq!(command.name(), "GET");
        assert!(!command.mutates_value());
        assert_eq!(command.route_key(), Some(b"alpha".as_slice()));
    }

    #[test]
    fn parses_del_command() {
        let command = BorrowedCommand::from_parts(&[
            b"DEL".as_slice(),
            b"alpha".as_slice(),
            b"beta".as_slice(),
        ])
        .unwrap();

        assert_eq!(command.name(), "DEL");
        assert!(command.mutates_value());
        assert_eq!(command.route_key(), Some(b"alpha".as_slice()));
        assert_eq!(
            command.to_owned_command().route_key(),
            Some(b"alpha".as_slice())
        );
    }

    #[test]
    fn parses_borrowed_command_object() {
        let command = CommandCatalog::parse_borrowed(&[
            b"SET".as_slice(),
            b"alpha".as_slice(),
            b"beta".as_slice(),
        ])
        .unwrap();

        assert_eq!(command.name(), "SET");
        assert!(command.mutates_value());
        assert_eq!(command.route_key(), Some(b"alpha".as_slice()));
        assert_eq!(
            command.to_owned_command().route_key(),
            Some(b"alpha".as_slice())
        );
    }
}