使用 From/Into 特征进行错误的转换是否符合习惯?

use*_*467 1 idioms rust

我正在使用 jwt 为我的 API 开发身份验证系统,并且有以下两种类型:

#[derive(Serialize, Deserialize)]
pub struct UserClaims {
    email: String,
    exp: usize,
    sub: String,
}

#[derive(Serialize)]
struct AccessToken(String);
Run Code Online (Sandbox Code Playgroud)

现在我想表达这样一个事实:访问令牌可以“转换”为声明对象。所以我决定实施以下措施:

impl From<AccessToken> for UserClaims {
    fn from(token: AccessToken) -> Self {
        // ... NOTE: this is fallible i.e actually returns a `Result`
    }
}
Run Code Online (Sandbox Code Playgroud)

但我意识到解码令牌的代码是错误的并返回 a Result,现在我可以将impl块更改为类似以下内容:impl Into<Result<UserClaims, SomeError>> for AccessToken但这是这些特征的惯用用法吗?或者如果我只使用常规方法会更好吗?

Sil*_*olo 6

不,事实上,文档专门指出了这个用例。

注意:此特性一定不能失败。From特征旨在实现完美转换。如果转换可能失败或不完美,请使用TryFrom

TryFrom特征(及其总体伴侣TryInto)旨在捕获容易出错的转换。看起来像这样。

pub trait TryFrom<T> {
  type Error;

  fn try_from(value: T) -> Result<Self, Self::Error>;
}
Run Code Online (Sandbox Code Playgroud)

因此“错误”类型被内置到特征中。您可以指定此转换对于特定的错误类型是错误的,然后try_from(并且再次通过扩展try_into)返回一个Result,其中转换成功或返回您选择的错误类型的值。

所以你的建议From看起来像

impl TryFrom<AccessToken> for UserClaims {
  type Error = SomeError;

  fn try_from(token: AccessToken) -> Result<Self, Self::Error> {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)