Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to support `?`/`FromResidual` for custom result enum?

I would like to save entity in database in case of some specific errors and it seems nice to use custom result enum for this which should rethrow Err and SaveOnErr when ? is used.

I’ve tried to copy FromResidual trait from Result which seems responsible for ? usage, but was unsuccessful, is it possible to do?

#[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
}

Specific issue that I want to solve:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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
}

>Solution :

According to the documentation, you cannot overload the ? operator at this time. Perhaps you could write some sort of conversion that takes your values to a Result<T, E>.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading