mirror of
https://github.com/sunface/rust-by-practice.git
synced 2025-06-27 06:29:42 +00:00
add rust lang to repo by add assets/mini-redis
This commit is contained in:
116
zh-CN/assets/mini-redis/src/cmd/mod.rs
Normal file
116
zh-CN/assets/mini-redis/src/cmd/mod.rs
Normal file
@ -0,0 +1,116 @@
|
||||
mod get;
|
||||
pub use get::Get;
|
||||
|
||||
mod publish;
|
||||
pub use publish::Publish;
|
||||
|
||||
mod set;
|
||||
pub use set::Set;
|
||||
|
||||
mod subscribe;
|
||||
pub use subscribe::{Subscribe, Unsubscribe};
|
||||
|
||||
mod unknown;
|
||||
pub use unknown::Unknown;
|
||||
|
||||
use crate::{Connection, Db, Frame, Parse, ParseError, Shutdown};
|
||||
|
||||
/// Enumeration of supported Redis commands.
|
||||
///
|
||||
/// Methods called on `Command` are delegated to the command implementation.
|
||||
#[derive(Debug)]
|
||||
pub enum Command {
|
||||
Get(Get),
|
||||
Publish(Publish),
|
||||
Set(Set),
|
||||
Subscribe(Subscribe),
|
||||
Unsubscribe(Unsubscribe),
|
||||
Unknown(Unknown),
|
||||
}
|
||||
|
||||
impl Command {
|
||||
/// Parse a command from a received frame.
|
||||
///
|
||||
/// The `Frame` must represent a Redis command supported by `mini-redis` and
|
||||
/// be the array variant.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// On success, the command value is returned, otherwise, `Err` is returned.
|
||||
pub fn from_frame(frame: Frame) -> crate::Result<Command> {
|
||||
// The frame value is decorated with `Parse`. `Parse` provides a
|
||||
// "cursor" like API which makes parsing the command easier.
|
||||
//
|
||||
// The frame value must be an array variant. Any other frame variants
|
||||
// result in an error being returned.
|
||||
let mut parse = Parse::new(frame)?;
|
||||
|
||||
// All redis commands begin with the command name as a string. The name
|
||||
// is read and converted to lower cases in order to do case sensitive
|
||||
// matching.
|
||||
let command_name = parse.next_string()?.to_lowercase();
|
||||
|
||||
// Match the command name, delegating the rest of the parsing to the
|
||||
// specific command.
|
||||
let command = match &command_name[..] {
|
||||
"get" => Command::Get(Get::parse_frames(&mut parse)?),
|
||||
"publish" => Command::Publish(Publish::parse_frames(&mut parse)?),
|
||||
"set" => Command::Set(Set::parse_frames(&mut parse)?),
|
||||
"subscribe" => Command::Subscribe(Subscribe::parse_frames(&mut parse)?),
|
||||
"unsubscribe" => Command::Unsubscribe(Unsubscribe::parse_frames(&mut parse)?),
|
||||
_ => {
|
||||
// The command is not recognized and an Unknown command is
|
||||
// returned.
|
||||
//
|
||||
// `return` is called here to skip the `finish()` call below. As
|
||||
// the command is not recognized, there is most likely
|
||||
// unconsumed fields remaining in the `Parse` instance.
|
||||
return Ok(Command::Unknown(Unknown::new(command_name)));
|
||||
}
|
||||
};
|
||||
|
||||
// Check if there is any remaining unconsumed fields in the `Parse`
|
||||
// value. If fields remain, this indicates an unexpected frame format
|
||||
// and an error is returned.
|
||||
parse.finish()?;
|
||||
|
||||
// The command has been successfully parsed
|
||||
Ok(command)
|
||||
}
|
||||
|
||||
/// Apply the 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.
|
||||
pub(crate) async fn apply(
|
||||
self,
|
||||
db: &Db,
|
||||
dst: &mut Connection,
|
||||
shutdown: &mut Shutdown,
|
||||
) -> crate::Result<()> {
|
||||
use Command::*;
|
||||
|
||||
match self {
|
||||
Get(cmd) => cmd.apply(db, dst).await,
|
||||
Publish(cmd) => cmd.apply(db, dst).await,
|
||||
Set(cmd) => cmd.apply(db, dst).await,
|
||||
Subscribe(cmd) => cmd.apply(db, dst, shutdown).await,
|
||||
Unknown(cmd) => cmd.apply(dst).await,
|
||||
// `Unsubscribe` cannot be applied. It may only be received from the
|
||||
// context of a `Subscribe` command.
|
||||
Unsubscribe(_) => Err("`Unsubscribe` is unsupported in this context".into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the command name
|
||||
pub(crate) fn get_name(&self) -> &str {
|
||||
match self {
|
||||
Command::Get(_) => "get",
|
||||
Command::Publish(_) => "pub",
|
||||
Command::Set(_) => "set",
|
||||
Command::Subscribe(_) => "subscribe",
|
||||
Command::Unsubscribe(_) => "unsubscribe",
|
||||
Command::Unknown(cmd) => cmd.get_name(),
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user