Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/nornir

crates/mimir-graph/src/error.rs

use std::fmt;

/// Everything that can go wrong in this crate.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Error {
    /// A GraphBLAS call returned an error `GrB_Info` (negative code).
    GraphBlas { call: &'static str, info: i32 },
    /// The input was rejected before it reached GraphBLAS (bad CSR, index out
    /// of range, size mismatch, …).
    Invalid(String),
    /// The Arrow batch does not have the expected shape.
    Arrow(String),
    /// `malloc` failed for a buffer handed to GraphBLAS.
    Alloc { bytes: usize },
    /// The linked libgraphblas is not the major version the bindings are for.
    Version {
        found: (i32, i32, i32),
        expected_major: i32,
    },
}

pub type Result<T> = std::result::Result<T, Error>;

impl Error {
    pub(crate) fn invalid(msg: impl Into<String>) -> Self {
        Error::Invalid(msg.into())
    }
}

fn info_name(info: i32) -> &'static str {
    match info {
        -1 => "GrB_UNINITIALIZED_OBJECT",
        -2 => "GrB_NULL_POINTER",
        -3 => "GrB_INVALID_VALUE",
        -4 => "GrB_INVALID_INDEX",
        -5 => "GrB_DOMAIN_MISMATCH",
        -6 => "GrB_DIMENSION_MISMATCH",
        -7 => "GrB_OUTPUT_NOT_EMPTY",
        -8 => "GrB_NOT_IMPLEMENTED",
        -101 => "GrB_PANIC",
        -102 => "GrB_OUT_OF_MEMORY",
        -103 => "GrB_INSUFFICIENT_SPACE",
        -104 => "GrB_INVALID_OBJECT",
        -105 => "GrB_INDEX_OUT_OF_BOUNDS",
        -106 => "GrB_EMPTY_OBJECT",
        _ => "unknown GrB_Info",
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::GraphBlas { call, info } => {
                write!(f, "{call} failed: {} ({info})", info_name(*info))
            }
            Error::Invalid(m) => write!(f, "invalid input: {m}"),
            Error::Arrow(m) => write!(f, "arrow: {m}"),
            Error::Alloc { bytes } => write!(f, "malloc of {bytes} bytes failed"),
            Error::Version {
                found: (a, b, c),
                expected_major,
            } => write!(
                f,
                "libgraphblas {a}.{b}.{c} is linked, the bindings are for {expected_major}.x"
            ),
        }
    }
}

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

/// Turn a `GrB_Info` into a `Result`. `GrB_SUCCESS` (0) and `GrB_NO_VALUE` (1)
/// are both "not an error"; callers that care about NO_VALUE use [`check_value`].
pub(crate) fn check(call: &'static str, info: graphblas_sys::GrB_Info) -> Result<()> {
    if info >= 0 {
        Ok(())
    } else {
        Err(Error::GraphBlas { call, info })
    }
}

/// Like [`check`] but reports whether an entry was present (`GrB_NO_VALUE` → false).
pub(crate) fn check_value(call: &'static str, info: graphblas_sys::GrB_Info) -> Result<bool> {
    match info {
        graphblas_sys::GrB_SUCCESS => Ok(true),
        graphblas_sys::GrB_NO_VALUE => Ok(false),
        _ => check(call, info).map(|_| false),
    }
}

/// Call a GraphBLAS function and `?` its `GrB_Info`, naming the call in the error.
macro_rules! grb {
    ($f:ident ( $($arg:expr),* $(,)? )) => {
        $crate::error::check(stringify!($f), unsafe { graphblas_sys::$f($($arg),*) })
    };
}
pub(crate) use grb;