lxdb-engine 0.1.0

Lazy semantic token and relation queries over LXDB datasets.
Documentation
use std::{error::Error, fmt, str::Utf8Error};

use lxdb_format::FormatError;

#[derive(Debug)]
pub enum EngineError {
    Format(FormatError),

    TokenStringOutOfBounds { token_id: u32, offset: u64, length: u32, table_length: usize },

    InvalidTokenUtf8 { token_id: u32, source: Utf8Error },

    MissingAdjacency { token_id: u32, adjacency_count: usize },

    RelationRangeOutOfBounds { token_id: u32, offset: u64, count: u32, relation_count: usize },

    MissingRelationSource { relation_id: u32, token_id: u32 },

    MissingRelationTarget { relation_id: u32, token_id: u32 },
}

impl fmt::Display for EngineError {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Format(error) => {
                write!(formatter, "failed to decode binary record: {error}",)
            }

            Self::TokenStringOutOfBounds { token_id, offset, length, table_length } => {
                write!(
                    formatter,
                    "token {token_id} references string range \
                     {offset}..{} outside a table of \
                     {table_length} bytes",
                    offset.saturating_add(u64::from(*length)),
                )
            }

            Self::InvalidTokenUtf8 { token_id, source } => {
                write!(
                    formatter,
                    "token {token_id} contains invalid UTF-8: \
                     {source}",
                )
            }

            Self::MissingAdjacency { token_id, adjacency_count } => {
                write!(
                    formatter,
                    "token {token_id} has no adjacency record; \
                     dataset contains {adjacency_count} adjacency \
                     records",
                )
            }

            Self::RelationRangeOutOfBounds { token_id, offset, count, relation_count } => {
                write!(
                    formatter,
                    "token {token_id} references relation range \
                     {offset}..{} outside a relation table \
                     containing {relation_count} records",
                    offset.saturating_add(u64::from(*count)),
                )
            }

            Self::MissingRelationSource { relation_id, token_id } => {
                write!(
                    formatter,
                    "relation {relation_id} references missing source token \
                    {token_id}",
                )
            }

            Self::MissingRelationTarget { relation_id, token_id } => {
                write!(
                    formatter,
                    "relation {relation_id} references missing target token \
                    {token_id}",
                )
            }
        }
    }
}

impl Error for EngineError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            Self::Format(error) => Some(error),

            Self::InvalidTokenUtf8 { source, .. } => Some(source),

            Self::TokenStringOutOfBounds { .. }
            | Self::MissingAdjacency { .. }
            | Self::RelationRangeOutOfBounds { .. }
            | Self::MissingRelationSource { .. }
            | Self::MissingRelationTarget { .. } => None,
        }
    }
}

impl From<FormatError> for EngineError {
    fn from(error: FormatError) -> Self {
        Self::Format(error)
    }
}