Skip to main content

uqa_analysis/
error.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Errors produced while executing an analysis pipeline.
8
9use regex::Error as RegexError;
10
11use crate::token_filter::SynonymFileError;
12
13/// An invalid analyzer is an execution error, never an empty token stream.
14#[derive(Debug, thiserror::Error)]
15pub enum AnalysisError {
16    #[error(transparent)]
17    Memory(#[from] uqa_core::memory::MemoryError),
18    #[cfg(feature = "nori")]
19    #[error("this pipeline has no Korean normalization profile")]
20    NormalizationUnavailable,
21    #[error("invalid analyzer descriptor: {0}")]
22    Descriptor(&'static str),
23    #[error("analyzer {component} revision {actual} is unavailable; expected {expected}")]
24    DescriptorRevision {
25        component: &'static str,
26        expected: u32,
27        actual: u32,
28    },
29    #[error("analyzer fingerprint mismatch: expected {expected}, received {actual}")]
30    DescriptorFingerprint {
31        expected: crate::AnalyzerFingerprint,
32        actual: crate::AnalyzerFingerprint,
33    },
34    #[error("analysis needs {required} {resource}, exceeding limit {limit}")]
35    ResourceLimit {
36        resource: &'static str,
37        required: usize,
38        limit: usize,
39    },
40    #[error("invalid analyzer JSON: {0}")]
41    Json(#[from] serde_json::Error),
42    #[error("analysis cancelled")]
43    Cancelled,
44    #[error("token contains unpaired UTF-16 surrogate {unit:#06x}; use its lossless term units")]
45    UnpairedTokenSurrogate { unit: u16 },
46    #[error("analysis expected {expected_utf16} UTF-16 input units, but received {actual_utf16}")]
47    MismatchedAnalysisInput {
48        expected_utf16: usize,
49        actual_utf16: usize,
50    },
51    #[cfg(feature = "nori")]
52    #[error(transparent)]
53    Dictionary(#[from] crate::nori::DictionaryError),
54    #[error("{coordinate} offset {offset} is not a Unicode scalar boundary within text of length {length}")]
55    InvalidTextOffset {
56        coordinate: &'static str,
57        offset: usize,
58        length: usize,
59    },
60    #[error("text span start {start} exceeds its end {end}")]
61    InvalidTextSpan { start: usize, end: usize },
62    #[error("character-filter edits overlap or are out of order")]
63    OverlappingTextEdits,
64    #[error("highlighting requires original source offsets for every matching token")]
65    MissingTokenOffsets,
66    #[error("token graphs require a positive first increment and positive position lengths")]
67    InvalidTokenPosition,
68    #[error("token position exceeds the u32 position format")]
69    TokenPositionOverflow,
70    #[error("invalid {component} regular expression `{pattern}`: {source}")]
71    InvalidRegex {
72        component: &'static str,
73        pattern: String,
74        #[source]
75        source: RegexError,
76    },
77    #[error("failed to initialize built-in {component} regular expression: {message}")]
78    BuiltInRegex {
79        component: &'static str,
80        message: String,
81    },
82    #[error(
83        "invalid {component} gram bounds: min_gram must be at least 1 and max_gram must be greater than or equal to min_gram (got {min_gram}..={max_gram})"
84    )]
85    InvalidGramBounds {
86        component: &'static str,
87        min_gram: usize,
88        max_gram: usize,
89    },
90    #[error(transparent)]
91    SynonymFile(#[from] SynonymFileError),
92}
93
94pub type AnalysisResult<T> = std::result::Result<T, AnalysisError>;