[英]How do I return an error within match statement while implementing from_str in rust?
我是 rust 的新手。 我正在尝试按照示例在此处实现 from_str 特征
https://doc.rust-lang.org/std/str/trait.FromStr.html
但我不断收到指向“return Err(Self::Err)”的错误
variant or associated item not found in `black_jack_tools::PlayerDifficulty`
我知道为什么 Self::Err 没有在我的枚举中定义但我不明白为什么 rust 在这种情况下关心,因为我返回了我的 Err object 的 Err,它与 Result<Self, Self::Err> 类型。
这是我的 FromStr 下面是带有 MRE 的 rust 操场的链接
impl FromStr for PlayerDifficulty {
type Err = ParseError;
fn from_str(s:&str) -> Result<Self,Self::Err>{
let result = match s {
"Player" => Ok(PlayerDifficulty::Player),
"Dealer" => Ok(PlayerDifficulty::Dealer),
"Normal" => Ok(PlayerDifficulty::Normal),
"Perfect"=> Ok(PlayerDifficulty::Perfect),
"Micky" => Ok(PlayerDifficulty::Micky),
"Elliot" => Ok(PlayerDifficulty::Elliot),
"Cultist"=> Ok(PlayerDifficulty::Cultist),
_ => return Err(Self::Err)
};
}
}
我究竟做错了什么? 有一个更好的方法吗?
您的代码存在三个问题。 第一个是如果你想在FromStr
实现中引用Err
类型,你需要使用<Self as FromStr>::Err
:
impl FromStr for PlayerDifficulty {
type Err = ParseError;
fn from_str(s:&str) -> Result<Self,Self::Err>{
let result = match s {
"Player" => Ok(PlayerDifficulty::Player),
/* ... */
_ => return Err(<Self as FromStr>::Err)
};
}
}
Self::Err
尝试在PlayerDifficulty
枚举中查找Err
变体,但没有这样的变体。
第二个问题是std::string::ParseError
实际上是std::convert::Infallible
的别名,这是一个永远不会发生且无法实例化的错误。 由于您的转换可能会失败,因此您需要使用可以实例化或定义自己的错误:
struct UnknownDifficultyError;
impl FromStr for PlayerDifficulty {
type Err = UnknownDifficultyError;
fn from_str(s:&str) -> Result<Self,Self::Err>{
let result = match s {
"Player" => Ok(PlayerDifficulty::Player),
/* ... */
_ => return Err(UnknownDifficultyError),
};
}
}
最后,即使转换成功,您也需要通过删除let result =
和分号来返回结果:
struct UnknownDifficultyError;
impl FromStr for PlayerDifficulty {
type Err = UnknownDifficultyError;
fn from_str(s:&str) -> Result<Self,Self::Err>{
match s {
"Player" => Ok(PlayerDifficulty::Player),
/* ... */
_ => return Err(UnknownDifficultyError),
}
}
}
function 将返回最后一条语句。 去掉最后一个分号,也可以去掉内部的return语句,返回match
语句的结果。
有没有更好的办法? 看起来您正在将字符串解析为enum
, create enum-utils就是这样做的。 而不是用样板代码实现解析器,您只需派生它。
#[derive(Debug, PartialEq, enum_utils::FromStr)]
enum PlayerDifficulty {
Player,
Dealer,
Cultist,
Normal,
}
fn main() {
let _x:PlayerDifficulty= "Player".parse().unwrap();
}
在你的 cargo.toml 中
[dependencies]
enum-utils = "0.1.2"
您应该定义一个自定义错误
#[derive(Debug)]
struct PlayerError;
impl std::fmt::Display for PlayerError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Could not parse player")
}
}
impl std::error::Error for PlayerError{}
然后更改匹配总是在相同的路径中返回Result
use std::str::FromStr;
impl FromStr for PlayerDifficulty {
type Err = PlayerError;
fn from_str(s:&str) -> Result<Self,Self::Err>{
match s {
"Player" => Ok(PlayerDifficulty::Player),
"Dealer" => Ok(PlayerDifficulty::Dealer),
"Normal" => Ok(PlayerDifficulty::Normal),
"Perfect"=> Ok(PlayerDifficulty::Perfect),
"Micky" => Ok(PlayerDifficulty::Micky),
"Elliot" => Ok(PlayerDifficulty::Elliot),
"Cultist"=> Ok(PlayerDifficulty::Cultist),
_ => Err(PlayerError)
}
}
}
并与?
传播错误。
fn main() -> (Result<(),Box<dyn std::error::Error>>) {
let _x = PlayerDifficulty::from_str("Player")?;
let _x = PlayerDifficulty::from_str("PlayerPlayer")?;
Ok(())
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.