1use std::fmt;
4
5#[derive(Debug)]
7pub enum YamlError {
8 Io(std::io::Error),
10
11 Parse {
13 message: String,
15 line: Option<usize>,
17 column: Option<usize>,
19 },
20
21 KeyNotFound {
23 key: String,
25 available_keys: Vec<String>,
27 path: String,
29 },
30
31 TypeMismatch {
33 expected: String,
35 actual: String,
37 path: String,
39 },
40
41 InvalidIndex {
43 index: usize,
45 length: usize,
47 path: String,
49 },
50
51 InvalidOperation {
53 operation: String,
55 reason: String,
57 },
58
59 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
159pub type YamlResult<T> = Result<T, YamlError>;