Skip to main content

yaml_edit/
error.rs

1//! Error types for yaml-edit
2
3use std::fmt;
4
5/// Errors that can occur when working with YAML documents
6#[derive(Debug)]
7pub enum YamlError {
8    /// I/O error when reading or writing files
9    Io(std::io::Error),
10
11    /// Parse error when parsing YAML
12    Parse {
13        /// Error message describing what went wrong
14        message: String,
15        /// Line number where the error occurred (if available)
16        line: Option<usize>,
17        /// Column number where the error occurred (if available)
18        column: Option<usize>,
19    },
20
21    /// Key not found in mapping
22    KeyNotFound {
23        /// The key that was not found
24        key: String,
25        /// Available keys in the mapping (for helpful error messages)
26        available_keys: Vec<String>,
27        /// Path to the mapping where the key was searched
28        path: String,
29    },
30
31    /// Type mismatch - expected one type but got another
32    TypeMismatch {
33        /// Expected type (e.g., "mapping", "sequence", "scalar")
34        expected: String,
35        /// Actual type found
36        actual: String,
37        /// Path to the value with the type mismatch
38        path: String,
39    },
40
41    /// Invalid index for sequence access
42    InvalidIndex {
43        /// The index that was out of bounds
44        index: usize,
45        /// The actual length of the sequence
46        length: usize,
47        /// Path to the sequence
48        path: String,
49    },
50
51    /// Invalid operation for the given context
52    InvalidOperation {
53        /// Description of what operation was attempted
54        operation: String,
55        /// Why it's invalid
56        reason: String,
57    },
58
59    /// Content that could not be resolved or converted to a
60    /// [`YamlValue`](crate::YamlValue)
61    Resolve(crate::anchor_resolution::ResolveError),
62}
63
64impl fmt::Display for YamlError {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        match self {
67            YamlError::Io(err) => write!(f, "I/O error: {err}"),
68
69            YamlError::Parse {
70                message,
71                line,
72                column,
73            } => {
74                write!(f, "Parse error")?;
75                if let (Some(line), Some(column)) = (line, column) {
76                    write!(f, " at line {line}, column {column}")?;
77                } else if let Some(line) = line {
78                    write!(f, " at line {line}")?;
79                }
80                write!(f, ": {message}")
81            }
82
83            YamlError::KeyNotFound {
84                key,
85                available_keys,
86                path,
87            } => {
88                write!(f, "Key '{key}' not found")?;
89                if !path.is_empty() {
90                    write!(f, " at path '{path}'")?;
91                }
92                if !available_keys.is_empty() {
93                    write!(f, ". Available keys: [{}]", available_keys.join(", "))?;
94                }
95                Ok(())
96            }
97
98            YamlError::TypeMismatch {
99                expected,
100                actual,
101                path,
102            } => {
103                write!(
104                    f,
105                    "Type mismatch: expected '{expected}', but found '{actual}'"
106                )?;
107                if !path.is_empty() {
108                    write!(f, " at path '{path}'")?;
109                }
110                Ok(())
111            }
112
113            YamlError::InvalidIndex {
114                index,
115                length,
116                path,
117            } => {
118                write!(
119                    f,
120                    "Index {index} is out of bounds (sequence has {length} elements)"
121                )?;
122                if !path.is_empty() {
123                    write!(f, " at path '{path}'")?;
124                }
125                Ok(())
126            }
127
128            YamlError::InvalidOperation { operation, reason } => {
129                write!(f, "Invalid operation '{operation}': {reason}")
130            }
131
132            YamlError::Resolve(err) => write!(f, "Resolve error: {err}"),
133        }
134    }
135}
136
137impl std::error::Error for YamlError {
138    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
139        match self {
140            YamlError::Io(err) => Some(err),
141            YamlError::Resolve(err) => Some(err),
142            _ => None,
143        }
144    }
145}
146
147impl From<std::io::Error> for YamlError {
148    fn from(err: std::io::Error) -> Self {
149        YamlError::Io(err)
150    }
151}
152
153impl From<crate::anchor_resolution::ResolveError> for YamlError {
154    fn from(err: crate::anchor_resolution::ResolveError) -> Self {
155        YamlError::Resolve(err)
156    }
157}
158
159/// Result type for yaml-edit operations
160pub type YamlResult<T> = Result<T, YamlError>;