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
60impl fmt::Display for YamlError {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 match self {
63 YamlError::Io(err) => write!(f, "I/O error: {}", err),
64
65 YamlError::Parse {
66 message,
67 line,
68 column,
69 } => {
70 write!(f, "Parse error")?;
71 if let (Some(line), Some(column)) = (line, column) {
72 write!(f, " at line {}, column {}", line, column)?;
73 } else if let Some(line) = line {
74 write!(f, " at line {}", line)?;
75 }
76 write!(f, ": {}", message)
77 }
78
79 YamlError::KeyNotFound {
80 key,
81 available_keys,
82 path,
83 } => {
84 write!(f, "Key '{}' not found", key)?;
85 if !path.is_empty() {
86 write!(f, " at path '{}'", path)?;
87 }
88 if !available_keys.is_empty() {
89 write!(f, ". Available keys: [{}]", available_keys.join(", "))?;
90 }
91 Ok(())
92 }
93
94 YamlError::TypeMismatch {
95 expected,
96 actual,
97 path,
98 } => {
99 write!(
100 f,
101 "Type mismatch: expected '{}', but found '{}'",
102 expected, actual
103 )?;
104 if !path.is_empty() {
105 write!(f, " at path '{}'", path)?;
106 }
107 Ok(())
108 }
109
110 YamlError::InvalidIndex {
111 index,
112 length,
113 path,
114 } => {
115 write!(
116 f,
117 "Index {} is out of bounds (sequence has {} elements)",
118 index, length
119 )?;
120 if !path.is_empty() {
121 write!(f, " at path '{}'", path)?;
122 }
123 Ok(())
124 }
125
126 YamlError::InvalidOperation { operation, reason } => {
127 write!(f, "Invalid operation '{}': {}", operation, reason)
128 }
129 }
130 }
131}
132
133impl std::error::Error for YamlError {
134 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
135 match self {
136 YamlError::Io(err) => Some(err),
137 _ => None,
138 }
139 }
140}
141
142impl From<std::io::Error> for YamlError {
143 fn from(err: std::io::Error) -> Self {
144 YamlError::Io(err)
145 }
146}
147
148pub type YamlResult<T> = Result<T, YamlError>;