1use core::fmt;
2
3extern crate alloc;
4#[cfg(feature = "serde")]
5use alloc::string::String;
6#[cfg(feature = "std")]
7use alloc::sync::Arc;
8
9#[derive(Clone, Debug, PartialEq)]
11pub enum ReadErrorKind {
12 UnterminatedQuote,
14 TrailingContent,
16 InvalidUtf8,
18 InconsistentFieldCount { expected: usize, found: usize },
20 RecordTooLarge { limit: usize },
25 FieldTooLarge { limit: usize },
30 TooManyColumns { limit: usize },
35 NoProgress,
40 #[cfg(feature = "serde")]
42 Deserialize(String),
43 Io,
45}
46
47#[derive(Debug)]
55pub struct ReadError {
56 pub kind: ReadErrorKind,
57 pub line: usize,
63 pub column: usize,
65 #[cfg(feature = "std")]
66 source: Option<Arc<dyn core::error::Error + Send + Sync + 'static>>,
67}
68
69impl ReadError {
70 pub fn new(kind: ReadErrorKind, line: usize, column: usize) -> Self {
71 ReadError {
72 kind,
73 line,
74 column,
75 #[cfg(feature = "std")]
76 source: None,
77 }
78 }
79
80 pub fn kind(&self) -> &ReadErrorKind {
81 &self.kind
82 }
83
84 #[cfg(feature = "std")]
89 pub fn into_source(self) -> Option<Arc<dyn core::error::Error + Send + Sync + 'static>> {
90 self.source
91 }
92}
93
94impl Clone for ReadError {
95 fn clone(&self) -> Self {
96 ReadError {
97 kind: self.kind.clone(),
98 line: self.line,
99 column: self.column,
100 #[cfg(feature = "std")]
101 source: self.source.clone(),
102 }
103 }
104}
105
106impl fmt::Display for ReadError {
107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 match &self.kind {
109 ReadErrorKind::UnterminatedQuote => {
110 write!(f, "unterminated quote at line {}, column {}", self.line, self.column)
111 }
112 ReadErrorKind::TrailingContent => {
113 write!(
114 f,
115 "trailing content after quoted field at line {}, column {}",
116 self.line, self.column
117 )
118 }
119 ReadErrorKind::InvalidUtf8 => {
120 write!(f, "invalid UTF-8 at line {}, column {}", self.line, self.column)
121 }
122 ReadErrorKind::InconsistentFieldCount {
123 expected,
124 found,
125 } => {
126 write!(
127 f,
128 "expected {expected} fields, found {found} at line {}, column {}",
129 self.line, self.column
130 )
131 }
132 ReadErrorKind::RecordTooLarge {
133 limit,
134 } => {
135 write!(
136 f,
137 "record larger than {limit} bytes at line {}, column {}",
138 self.line, self.column
139 )
140 }
141 ReadErrorKind::FieldTooLarge {
142 limit,
143 } => {
144 write!(
145 f,
146 "field larger than {limit} bytes at line {}, column {}",
147 self.line, self.column
148 )
149 }
150 ReadErrorKind::TooManyColumns {
151 limit,
152 } => {
153 write!(f, "more than {limit} columns at line {}, column {}", self.line, self.column)
154 }
155 ReadErrorKind::NoProgress => {
156 write!(
157 f,
158 "read source reported more data but appended none at line {}, column {}",
159 self.line, self.column
160 )
161 }
162 #[cfg(feature = "serde")]
163 ReadErrorKind::Deserialize(msg) => {
164 write!(f, "deserialization error at line {}, column {}: {msg}", self.line, self.column)
165 }
166 ReadErrorKind::Io => {
167 write!(f, "I/O error at line {}, column {}", self.line, self.column)?;
168 #[cfg(feature = "std")]
169 if let Some(source) = &self.source {
170 write!(f, ": {source}")?;
171 }
172 Ok(())
173 }
174 }
175 }
176}
177
178impl core::error::Error for ReadError {
179 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
180 #[cfg(feature = "std")]
181 {
182 self.source
183 .as_ref()
184 .map(|b| b.as_ref() as &(dyn core::error::Error + 'static))
185 }
186 #[cfg(not(feature = "std"))]
187 {
188 None
189 }
190 }
191}
192
193#[cfg(feature = "std")]
194impl From<std::io::Error> for ReadError {
195 fn from(e: std::io::Error) -> Self {
196 ReadError {
197 kind: ReadErrorKind::Io,
198 line: 0,
199 column: 0,
200 source: Some(Arc::new(e)),
201 }
202 }
203}
204
205#[derive(Debug)]
207pub enum WriteError {
208 InconsistentFieldCount { expected: usize, found: usize, row: usize },
210 HeadersAlreadyWritten,
212 #[cfg(feature = "serde")]
214 Serialize(String),
215 #[cfg(feature = "std")]
217 Io(std::io::Error),
218 #[cfg(not(feature = "std"))]
220 Io,
221}
222
223impl fmt::Display for WriteError {
224 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
225 match self {
226 WriteError::InconsistentFieldCount {
227 expected,
228 found,
229 row,
230 } => {
231 write!(f, "expected {expected} fields, found {found} in row {row}")
232 }
233 WriteError::HeadersAlreadyWritten => write!(f, "headers have already been written"),
234 #[cfg(feature = "serde")]
235 WriteError::Serialize(msg) => write!(f, "serialization error: {msg}"),
236 #[cfg(feature = "std")]
237 WriteError::Io(e) => write!(f, "I/O error: {e}"),
238 #[cfg(not(feature = "std"))]
239 WriteError::Io => write!(f, "I/O error"),
240 }
241 }
242}
243
244impl core::error::Error for WriteError {
245 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
246 match self {
247 #[cfg(feature = "std")]
248 WriteError::Io(e) => Some(e),
249 _ => None,
250 }
251 }
252}
253
254#[cfg(feature = "std")]
255impl From<std::io::Error> for WriteError {
256 fn from(e: std::io::Error) -> Self {
257 WriteError::Io(e)
258 }
259}