我想保存实体在数据库中的一些特定错误的情况下,这似乎很好使用自定义结果枚举这应该重新抛出ErrSaveOnErr当使用?.

我试着从Result中复制FromResidual个性状,这似乎是?个使用的原因,但失败了,可以这样做吗?

#[derive(Copy, PartialEq, Eq, Debug, Clone)]
pub enum SavableResult<T, E> {
    Ok(T),
    Err(E),
    SaveOnErr(E),
}

fn test1() {
    let result = test2();

    match result {
        SavableResult::Ok(_) | SavableResult::SaveOnErr(_) => save(),
        SavableResult::Err(_) => {}
    };
}
fn test2() -> SavableResult<(), ApiErr> {
    test3()?; // not working

    SavableResult::Ok(())
}
fn test3() -> SavableResult<(), ApiErr> {
    SavableResult::Ok(())
}
fn save() {
    // save in db
}

我想解决的具体问题:

pub async fn execute(&self) -> Result<JwtTokensPair, ApiErr> {
    let mut auth = AuthRepository::get_by_user_id(user_id, &trx).await?;

    // in case of incorrect password `auth` entity `failed_auth_count`
    // is incremented and I need to save it in database anyway
    // to block any auth after 10 fails for hour
    // but only for one specific error
    let result = auth.login(&self.password, self.hash_service);

    // problem here is that it's easy to forget which
    // entities have this special requirement
    // or use this ugly match everywhere
    match result {
        Ok(_)
        | Err(ApiErr {
            save_on_err: true, ..
        }) => AuthRepository::save(&auth, &trx).await?,
        Err(_) => {}
    };
    trx.commit().await?;

    result
}

推荐答案

根据the documentation,此时您不能超载?操作员.也许您可以编写某种类型的转换,将您的值转换为Result<T, E>.

Rust相关问答推荐

如何在 struct 中填充缓冲区并同时显示它?

在Rust中宏的表达式中提取对象

无法从流中读取Redis请求

将PathBuf转换为字符串

为什么';t std::cell::ref使用引用而不是非空?

在macro_rule中拆分模块和函数名

对于rustc编译的RISC-V32IM二进制文件,llvm objdump没有输出

为什么切片时需要参考?

将引用移动到线程中

如何为整数切片定义一个带有额外函数的特性别名?

如何将 &[T] 或 Vec<T> 转换为 Arc<Mutex<[T]>>?

有没有办法隐式绑定 let/match 操作的成员?

类型判断模式匹配panic

rust 中不同类型的工厂函数

在 Rust 中,将可变引用传递给函数的机制是什么?

如何创建递归borrow 其父/创建者的 struct ?

为什么我可以同时传递可变和不可变引用?

为什么 &i32 可以与 Rust 中的 &&i32 进行比较?

Abortable:悬而未决的期货?

为什么 std::iter::Peekable::peek 可变地borrow self 参数?