xgraph 3.0.0

Graph algorithms for Rust: shortest paths, centrality, connectivity, spanning trees and community detection, over directed, undirected and heterogeneous multigraphs
Documentation
//! The crate's unifying error type.
//!
//! Each area of the library reports a precise error of its own, which is what a caller
//! handling one specific failure wants. A caller that merely wants to propagate — with `?`,
//! through a function that touches traversal, weighting and I/O alike — wants a single
//! type instead. [`Error`] is that type: every error the library produces converts into it.
//!
//! Both examples shipped with this crate used to declare a wrapper enum of their own,
//! by hand, for exactly this reason.

use std::fmt::Debug;

/// Any failure the library can report.
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
    /// A graph operation failed.
    #[cfg(feature = "graph")]
    #[error(transparent)]
    Graph(#[from] crate::graph::graph::GraphError),

    /// A heterogeneous graph operation failed.
    #[cfg(feature = "hgraph")]
    #[error(transparent)]
    HGraph(#[from] crate::hgraph::h_graph::HGraphError),

    /// A traversal failed.
    #[error(transparent)]
    Traversal(#[from] crate::core::TraversalError),

    /// A shortest-path computation failed.
    #[error(transparent)]
    ShortestPath(#[from] crate::core::ShortestPathError),

    /// A centrality computation failed.
    #[error(transparent)]
    Centrality(#[from] crate::core::CentralityError),

    /// Community detection failed.
    #[cfg(feature = "community")]
    #[error(transparent)]
    CommunityDetection(#[from] crate::core::CommunityDetectionError),

    /// Converting a graph to different node or edge types failed.
    #[cfg(feature = "graph")]
    #[error(transparent)]
    GraphConversion(#[from] crate::graph::conversion::graph_conversion::GraphConversionError),

    /// Converting a heterogeneous graph to different node or edge types failed.
    #[cfg(feature = "hgraph")]
    #[error(transparent)]
    HGraphConversion(#[from] crate::hgraph::conversion::h_graph_conversion::GraphConversionError),

    /// Reading or writing CSV failed.
    #[cfg(feature = "hgraph")]
    #[error(transparent)]
    Csv(#[from] crate::hgraph::io::hcsv_io::CsvIoError),

    /// An I/O operation failed.
    #[error(transparent)]
    Io(#[from] std::io::Error),
}

/// A `Result` whose error is the crate's unifying [`Error`].
pub type Result<T> = std::result::Result<T, Error>;

#[cfg(test)]
#[cfg(feature = "graph")]
mod tests {
    use super::*;
    use crate::core::{NodeId, ShortestPath, Traversal};
    use crate::graph::Graph;

    /// One function, three different failure modes, one `?` each.
    fn analyse() -> Result<usize> {
        let mut graph = Graph::<u32, u32, ()>::new(false);
        let a = graph.add_node(0);
        let b = graph.add_node(1);
        graph.add_edge(a, b, 1, ())?;

        let reachable = graph.reachable_from(a)?;
        let distances = graph.dijkstra(a)?;
        Ok(reachable.len() + distances.len())
    }

    #[test]
    fn test_unrelated_errors_share_one_type() {
        assert_eq!(analyse().unwrap(), 4);
    }

    #[test]
    fn test_each_error_keeps_its_own_message() {
        let graph = Graph::<u32, u32, ()>::new(false);
        let error: Error = graph
            .reachable_from(NodeId::from_index(7))
            .unwrap_err()
            .into();
        // `#[error(transparent)]` forwards to the precise error rather than adding a layer.
        assert_eq!(
            error.to_string(),
            "Invalid node reference: node ID 7 not found"
        );
    }
}