Skip to main content

QueryResultExt

Trait QueryResultExt 

Source
pub trait QueryResultExt<T> {
    // Required method
    fn downcast_err<E: Error + Send + Sync + 'static>(
        self,
    ) -> Result<Result<Arc<T>, TypedErr<E>>, QueryError>;
}
Expand description

Extension trait for query results that provides ergonomic error downcasting.

This trait is implemented for Result<Arc<T>, QueryError> and allows you to downcast user errors to a specific type while propagating system errors.

§Example

use std::fmt;

use query_flow::{query, Db, QueryError, QueryResultExt, QueryRuntime};

#[derive(Debug)]
struct MyError {
    code: u32,
}

impl fmt::Display for MyError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "my error {}", self.code)
    }
}

impl std::error::Error for MyError {}

#[query]
fn my_query(db: &impl Db, succeed: bool) -> Result<i32, QueryError> {
    let _ = db;
    if succeed {
        Ok(1)
    } else {
        Err(MyError { code: 7 }.into())
    }
}

#[query]
fn caller(db: &impl Db, succeed: bool) -> Result<String, QueryError> {
    // Downcast to MyError, propagating system errors and non-matching user errors
    let result = db.query(MyQuery::new(succeed)).downcast_err::<MyError>()?;

    Ok(match result {
        Ok(value) => format!("Success: {:?}", value),
        Err(my_err) => format!("MyError: {}", my_err.code),
    })
}

let runtime = QueryRuntime::new();
assert_eq!(*runtime.query(Caller::new(true)).unwrap(), "Success: 1");
assert_eq!(*runtime.query(Caller::new(false)).unwrap(), "MyError: 7");

Required Methods§

Source

fn downcast_err<E: Error + Send + Sync + 'static>( self, ) -> Result<Result<Arc<T>, TypedErr<E>>, QueryError>

Attempts to downcast a UserError to a specific error type.

§Returns
  • Ok(Ok(value)) - The query succeeded with value
  • Ok(Err(typed_err)) - The query failed with a UserError of type E
  • Err(query_error) - The query failed with a system error, or a UserError that is not of type E
§Example
use std::fmt;

use query_flow::{query, Db, QueryError, QueryResultExt, QueryRuntime};

#[derive(Debug)]
struct MyError {
    message: String,
}

impl fmt::Display for MyError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.message)
    }
}

impl std::error::Error for MyError {}

#[query]
fn my_query(db: &impl Db) -> Result<i32, QueryError> {
    let _ = db;
    Err(MyError { message: "boom".into() }.into())
}

#[query]
fn caller(db: &impl Db) -> Result<i32, QueryError> {
    // Handle specific error type, propagate others
    let result = db.query(MyQuery::new()).downcast_err::<MyError>()?;
    let value = result.map_err(|e| {
        eprintln!("MyError occurred: {}", e.message);
        e
    })?;
    Ok(*value)
}

let runtime = QueryRuntime::new();
let err = runtime.query(Caller::new()).unwrap_err();
assert!(err.is::<MyError>());

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl<T> QueryResultExt<T> for Result<Arc<T>, QueryError>

Source§

fn downcast_err<E: Error + Send + Sync + 'static>( self, ) -> Result<Result<Arc<T>, TypedErr<E>>, QueryError>

Implementors§