请考虑从类型级别处理此问题。A.
Command
可以从一些字符串输入中解析,并且知道如何执行一些操作并返回其结果。
use std::str::FromStr;
pub enum CommandError {
BadlyFormattedCommand,
CouldNotFindCommand,
NotEnoughArguments,
}
pub enum Commands {
SetClipboard(String),
MouseMoveRel(i32, i32),
MouseMoveAbs(i32, i32),
}
impl FromStr for Commands {
type Err = CommandError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.split("|").collect::<Vec<&str>>().as_slice() {
["1", value] => Ok(Commands::SetClipboard(value.to_string())),
["1", ..] => Err(CommandError::NotEnoughArguments),
["2", x, y] => {
let x: i32 = x.parse().map_err(|_| CommandError::BadlyFormattedCommand)?;
let y: i32 = y.parse().map_err(|_| CommandError::BadlyFormattedCommand)?;
Ok(Commands::MouseMoveRel(x, y))
}
["2", ..] => Err(CommandError::NotEnoughArguments),
["3", x, y] => {
let x: i32 = x.parse().map_err(|_| CommandError::BadlyFormattedCommand)?;
let y: i32 = y.parse().map_err(|_| CommandError::BadlyFormattedCommand)?;
Ok(Commands::MouseMoveAbs(x, y))
}
["3", ..] => Err(CommandError::NotEnoughArguments),
_ => Err(CommandError::CouldNotFindCommand),
}
}
}
pub struct CommandResponse; // I won't define this, but maybe this is actually an enum?
impl Commands {
pub fn execute(&self) -> Result<Option<CommandResponse>, CommandError> {
match self {
Self::SetClipboard(s) => {
// do that thing
Ok(None)
}
Self::MouseMoveRel(x, y) => {
// do that thing
Ok(Some(CommandResponse)) // Maybe this is the new location?
}
Self::MouseMoveAbs(x, y) => {
// do THAT thing
Ok(Some(CommandResponse))
}
}
}
}
然后使用代码是:
def run_command(s: &str) -> Result<Option<CommandResult>, ApplicationError> {
// Parse the command
command: Command = s.parse().map_err(|_| ApplicationError)?;
// and return the result of its execution
command.execute().map_err(|_| ApplicationError)
}