Skip to main content

eure_mark/
error.rs

1//! Error types for eure-mark
2
3use eure_document::document::NodeId;
4use thiserror::Error;
5
6/// Errors that can occur during eumd document processing
7#[derive(Debug, Error)]
8pub enum EumdError {
9    /// Parse error from eure-parol
10    #[error("Parse error: {0}")]
11    Parse(String),
12
13    /// Document parsing error
14    #[error("Document error: {0}")]
15    Document(#[from] eure_document::parse::ParseError),
16
17    /// Reference check errors
18    #[error("Reference errors:\n{}", format_reference_errors(.0))]
19    ReferenceErrors(Vec<ReferenceError>),
20}
21
22/// A single reference error with optional span information
23#[derive(Debug, Clone)]
24pub struct ReferenceError {
25    /// Type of reference
26    pub ref_type: ReferenceType,
27    /// The key that was referenced
28    pub key: String,
29    /// Location description (e.g., "in section 'intro'")
30    pub location: String,
31    /// NodeId of the field containing the reference (for span resolution)
32    pub node_id: Option<NodeId>,
33    /// Byte offset of the reference within the field content
34    pub offset: Option<u32>,
35    /// Byte length of the reference string (e.g., "!cite[key]")
36    pub len: Option<u32>,
37}
38
39impl ReferenceError {
40    /// Create a new reference error without span information
41    pub fn new(ref_type: ReferenceType, key: String, location: String) -> Self {
42        Self {
43            ref_type,
44            key,
45            location,
46            node_id: None,
47            offset: None,
48            len: None,
49        }
50    }
51
52    /// Create a new reference error with span information
53    pub fn with_span(
54        ref_type: ReferenceType,
55        key: String,
56        location: String,
57        node_id: NodeId,
58        offset: u32,
59        len: u32,
60    ) -> Self {
61        Self {
62            ref_type,
63            key,
64            location,
65            node_id: Some(node_id),
66            offset: Some(offset),
67            len: Some(len),
68        }
69    }
70}
71
72/// Type of reference
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub enum ReferenceType {
75    /// Citation reference: !cite[key]
76    Cite,
77    /// Footnote reference: !footnote[key]
78    Footnote,
79    /// Section reference: !ref[key]
80    Section,
81}
82
83impl std::fmt::Display for ReferenceType {
84    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85        match self {
86            ReferenceType::Cite => write!(f, "cite"),
87            ReferenceType::Footnote => write!(f, "footnote"),
88            ReferenceType::Section => write!(f, "ref"),
89        }
90    }
91}
92
93impl std::fmt::Display for ReferenceError {
94    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95        write!(
96            f,
97            "Undefined !{}[{}] {}",
98            self.ref_type, self.key, self.location
99        )
100    }
101}
102
103fn format_reference_errors(errors: &[ReferenceError]) -> String {
104    errors
105        .iter()
106        .map(|e| format!("  - {e}"))
107        .collect::<Vec<_>>()
108        .join("\n")
109}