in_memory_cache/
command.rs

1//! Command types for the cache protocol.
2//!
3//! This module defines the commands that can be sent to the cache server.
4
5use crate::error::{CacheError, CacheResult};
6
7/// Types of commands supported by the cache server.
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum Command {
10    /// Get a value by key.
11    Get,
12    /// Set a key-value pair.
13    Set,
14    /// Delete a key.
15    Delete,
16    /// Ping the server (health check).
17    Ping,
18    /// Get server statistics.
19    Stats,
20    /// Invalid or unknown command.
21    Invalid,
22}
23
24impl Command {
25    /// Parse a command from a string.
26    ///
27    /// # Arguments
28    /// * `s` - The command string (case-insensitive).
29    ///
30    /// # Returns
31    /// The parsed command, or `Command::Invalid` for unknown commands.
32    pub fn get(s: &str) -> Command {
33        match s.to_lowercase().as_str() {
34            "set" => Command::Set,
35            "get" => Command::Get,
36            "delete" | "del" => Command::Delete,
37            "ping" => Command::Ping,
38            "stats" | "info" => Command::Stats,
39            _ => Command::Invalid,
40        }
41    }
42
43    /// Parse a command from a string, returning an error for invalid commands.
44    ///
45    /// # Arguments
46    /// * `s` - The command string (case-insensitive).
47    ///
48    /// # Returns
49    /// The parsed command, or an error for unknown commands.
50    pub fn parse(s: &str) -> CacheResult<Command> {
51        let cmd = Self::get(s);
52        if cmd == Command::Invalid {
53            Err(CacheError::InvalidCommand(s.to_string()))
54        } else {
55            Ok(cmd)
56        }
57    }
58
59    /// Get the string representation of this command.
60    pub fn as_str(&self) -> &'static str {
61        match self {
62            Command::Get => "get",
63            Command::Set => "set",
64            Command::Delete => "delete",
65            Command::Ping => "ping",
66            Command::Stats => "stats",
67            Command::Invalid => "invalid",
68        }
69    }
70}
71
72impl std::fmt::Display for Command {
73    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74        write!(f, "{}", self.as_str())
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81
82    #[test]
83    fn test_parse_commands() {
84        assert_eq!(Command::get("get"), Command::Get);
85        assert_eq!(Command::get("GET"), Command::Get);
86        assert_eq!(Command::get("set"), Command::Set);
87        assert_eq!(Command::get("SET"), Command::Set);
88        assert_eq!(Command::get("delete"), Command::Delete);
89        assert_eq!(Command::get("del"), Command::Delete);
90        assert_eq!(Command::get("ping"), Command::Ping);
91        assert_eq!(Command::get("stats"), Command::Stats);
92        assert_eq!(Command::get("unknown"), Command::Invalid);
93    }
94
95    #[test]
96    fn test_parse_with_error() {
97        assert!(Command::parse("get").is_ok());
98        assert!(Command::parse("unknown").is_err());
99    }
100
101    #[test]
102    fn test_as_str() {
103        assert_eq!(Command::Get.as_str(), "get");
104        assert_eq!(Command::Set.as_str(), "set");
105    }
106}