Skip to main content

uqa_operators/phrase/
error.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Typed failures at the graph matching boundary.
8
9use std::{collections::TryReserveError, error::Error, fmt};
10use uqa_core::QueryCancelled;
11use uqa_scoring::TextSearchError;
12use uqa_storage::StorageBackendError;
13
14#[derive(Debug)]
15pub enum PhraseError {
16    Cancelled(QueryCancelled),
17    MemoryLimit { required: usize, limit: usize },
18    Allocation(TryReserveError),
19    Memory(uqa_core::memory::MemoryError),
20    Storage(StorageBackendError),
21    Scoring(TextSearchError),
22    InvalidGraph(String),
23}
24
25pub type PhraseResult<T> = Result<T, PhraseError>;
26
27impl fmt::Display for PhraseError {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        match self {
30            Self::Cancelled(error) => error.fmt(f),
31            Self::MemoryLimit { required, limit } => write!(
32                f,
33                "phrase execution requires {required} bytes, exceeding work_mem of {limit} bytes"
34            ),
35            Self::Allocation(error) => error.fmt(f),
36            Self::Memory(error) => error.fmt(f),
37            Self::Storage(error) => error.fmt(f),
38            Self::Scoring(error) => error.fmt(f),
39            Self::InvalidGraph(message) => f.write_str(message),
40        }
41    }
42}
43
44impl Error for PhraseError {
45    fn source(&self) -> Option<&(dyn Error + 'static)> {
46        match self {
47            Self::Cancelled(error) => Some(error),
48            Self::Allocation(error) => Some(error),
49            Self::Memory(error) => Some(error),
50            Self::Storage(error) => Some(error),
51            Self::Scoring(error) => Some(error),
52            Self::MemoryLimit { .. } | Self::InvalidGraph(_) => None,
53        }
54    }
55}
56
57impl From<StorageBackendError> for PhraseError {
58    fn from(error: StorageBackendError) -> Self {
59        match error {
60            StorageBackendError::Memory(error) => error.into(),
61            StorageBackendError::Cancelled(error) => Self::Cancelled(error),
62            error => Self::Storage(error),
63        }
64    }
65}
66
67impl From<TextSearchError> for PhraseError {
68    fn from(error: TextSearchError) -> Self {
69        match error {
70            TextSearchError::Memory(error) => error.into(),
71            TextSearchError::Cancelled(error) => Self::Cancelled(error),
72            error => Self::Scoring(error),
73        }
74    }
75}
76
77impl From<uqa_core::memory::MemoryError> for PhraseError {
78    fn from(error: uqa_core::memory::MemoryError) -> Self {
79        match error {
80            uqa_core::memory::MemoryError::Limit { required, limit } => {
81                Self::MemoryLimit { required, limit }
82            }
83            uqa_core::memory::MemoryError::Allocation(error) => Self::Allocation(error),
84            error @ uqa_core::memory::MemoryError::SizeOverflow => Self::Memory(error),
85        }
86    }
87}