Skip to main content

tea_context/
error.rs

1use serde::{Deserialize, Serialize};
2use thiserror::Error;
3
4/// Stable machine-readable context failure classification.
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
6#[serde(rename_all = "snake_case")]
7pub enum ContextErrorCode {
8    /// An identifier, provenance value, or enum relationship is invalid.
9    InvalidValue,
10    /// A module or segment exceeds deterministic bounds.
11    BoundsExceeded,
12    /// The same canonical identity was defined inconsistently.
13    DuplicateIdentity,
14    /// Equal-precedence conflict claims are ambiguous.
15    AmbiguousConflict,
16    /// Required prompt content does not fit the configured budget.
17    BudgetExceeded,
18    /// A context provider failed without producing usable modules.
19    ProviderFailure,
20}
21
22/// Bounded safe context/compiler failure.
23#[derive(Debug, Clone, PartialEq, Eq, Error)]
24#[error("{code:?}: {message}")]
25pub struct ContextError {
26    code: ContextErrorCode,
27    message: String,
28}
29
30impl ContextError {
31    /// Creates a bounded English technical context error.
32    #[must_use]
33    pub fn new(code: ContextErrorCode, message: impl Into<String>) -> Self {
34        let mut message = message.into();
35        if message.is_empty() {
36            "context operation failed".clone_into(&mut message);
37        }
38        message.retain(|character| character != '\0');
39        if message.len() > 4096 {
40            let boundary = message
41                .char_indices()
42                .map(|(index, _)| index)
43                .take_while(|index| *index <= 4096)
44                .last()
45                .unwrap_or(0);
46            message.truncate(boundary);
47        }
48        Self { code, message }
49    }
50
51    /// Returns the stable classification.
52    #[must_use]
53    pub const fn code(&self) -> ContextErrorCode {
54        self.code
55    }
56
57    /// Returns the bounded safe diagnostic.
58    #[must_use]
59    pub fn message(&self) -> &str {
60        &self.message
61    }
62}