oxilite-core 0.9.0

The I/O-free core of oxilite: SPARQL to SQL compiler, term encoding and SQLite schema (sans-IO jobs for any SQLite backend)
Documentation
use std::fmt;

/// Result alias used across oxilite.
pub type Result<T, E = Error> = std::result::Result<T, E>;

/// Errors raised by oxilite.
#[derive(Debug, thiserror::Error)]
pub enum Error {
    /// The SPARQL query or update could not be parsed.
    #[error(transparent)]
    Syntax(#[from] spargebra::SparqlSyntaxError),
    /// An RDF document could not be parsed.
    #[error(transparent)]
    Parse(#[from] oxrdfio::RdfParseError),
    /// The SQL backend failed.
    #[error("SQL backend error: {0}")]
    Backend(String),
    /// The operation needs something the compiler or backend cannot do.
    #[error("unsupported: {0}")]
    Unsupported(String),
    /// Two different terms hashed to the same id.
    #[error("term hash collision: {0}")]
    Collision(String),
    /// The database content is not what oxilite expects.
    #[error("corrupted store: {0}")]
    Corrupted(String),
    /// Evaluation by the fallback evaluator failed.
    #[error(transparent)]
    Evaluation(#[from] spareval::QueryEvaluationError),
    /// I/O error while reading or writing RDF.
    #[error(transparent)]
    Io(#[from] std::io::Error),
    /// Other errors.
    #[error("{0}")]
    Other(String),
}

impl Error {
    pub fn backend(e: impl fmt::Display) -> Self {
        let msg = e.to_string();
        if msg.contains("oxilite: term hash collision") {
            Self::Collision(msg)
        } else if msg.contains("graph_does_not_exist") {
            Self::Other("the graph does not exist".into())
        } else if msg.contains("graph_already_exists") {
            Self::Other("the graph already exists".into())
        } else if msg.contains("vector_dimensions_mismatch") {
            Self::Other(
                "a value of the indexed property is not a JSON array with the index's dimensions"
                    .into(),
            )
        } else if msg.contains("computed_value_not_storable") {
            Self::Unsupported(
                "an update template stores a computed non-integer value, which SQL cannot hash"
                    .into(),
            )
        } else {
            Self::Backend(msg)
        }
    }

    pub fn unsupported(msg: impl Into<String>) -> Self {
        Self::Unsupported(msg.into())
    }

    pub fn corrupted(msg: impl Into<String>) -> Self {
        Self::Corrupted(msg.into())
    }

    /// Is this error a request for the fallback evaluator?
    pub fn is_unsupported(&self) -> bool {
        matches!(self, Self::Unsupported(_))
    }
}