Skip to main content

zenith_core/
error.rs

1//! Parse error types for zenith-core.
2
3use crate::ast::Span;
4
5/// Codes that identify the category of a parse error.
6#[derive(Debug, Clone, PartialEq)]
7pub enum ParseErrorCode {
8    /// The input bytes are not valid UTF-8.
9    NotUtf8,
10    /// The UTF-8 source is not valid KDL.
11    InvalidKdl,
12    /// No top-level `zenith` node was found in the document.
13    MissingZenithRoot,
14    /// A node appeared in a context where it is not expected.
15    UnexpectedNode,
16    /// A property value could not be parsed into the expected type.
17    InvalidPropertyValue,
18}
19
20/// A single error emitted by the parse layer.
21#[derive(Debug, Clone, PartialEq)]
22pub struct ParseError {
23    /// Source span of the offending token or node, if available.
24    pub span: Option<Span>,
25    /// Stable error category code.
26    pub code: ParseErrorCode,
27    /// Human-readable description of the error.
28    pub message: String,
29}
30
31impl ParseError {
32    /// Construct a `ParseError` without a source span.
33    pub fn spanless(code: ParseErrorCode, message: impl Into<String>) -> Self {
34        Self {
35            span: None,
36            code,
37            message: message.into(),
38        }
39    }
40
41    /// Construct a `ParseError` with an explicit source span.
42    pub fn with_span(code: ParseErrorCode, span: Span, message: impl Into<String>) -> Self {
43        Self {
44            span: Some(span),
45            code,
46            message: message.into(),
47        }
48    }
49}
50
51impl std::fmt::Display for ParseError {
52    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53        write!(f, "{}", self.message)
54    }
55}
56
57impl std::error::Error for ParseError {}
58
59/// An error emitted by the format layer.
60///
61/// In practice, formatting the minimal v0 node set never fails — return `Err`
62/// only for genuinely un-serializable states (unreachable in valid input, but
63/// the fallible signature is the contract from the format spec).
64#[derive(Debug, Clone, PartialEq)]
65pub struct FormatError {
66    /// Human-readable description of why formatting failed.
67    pub message: String,
68}
69
70impl FormatError {
71    /// Construct a `FormatError` with the given message.
72    pub fn new(message: impl Into<String>) -> Self {
73        Self {
74            message: message.into(),
75        }
76    }
77}
78
79impl std::fmt::Display for FormatError {
80    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81        write!(f, "{}", self.message)
82    }
83}
84
85impl std::error::Error for FormatError {}