1use core::fmt;
2
3extern crate alloc;
4#[cfg(feature = "std")]
5use alloc::boxed::Box;
6
7#[derive(Clone, Debug, PartialEq)]
9pub enum ReadErrorKind {
10 UnterminatedQuote,
12 TrailingContent,
14 InvalidUtf8,
16 #[cfg(feature = "serde")]
18 Deserialize(String),
19 Io,
21}
22
23#[derive(Debug)]
28pub struct ReadError {
29 pub kind: ReadErrorKind,
30 pub line: usize,
31 pub column: usize,
32 #[cfg(feature = "std")]
33 source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
34}
35
36impl ReadError {
37 pub fn new(kind: ReadErrorKind, line: usize, column: usize) -> Self {
38 ReadError {
39 kind,
40 line,
41 column,
42 #[cfg(feature = "std")]
43 source: None,
44 }
45 }
46
47 pub fn kind(&self) -> &ReadErrorKind {
48 &self.kind
49 }
50
51 #[cfg(feature = "std")]
53 pub fn into_source(self) -> Option<Box<dyn std::error::Error + Send + Sync + 'static>> {
54 self.source
55 }
56}
57
58impl Clone for ReadError {
59 fn clone(&self) -> Self {
60 ReadError {
61 kind: self.kind.clone(),
62 line: self.line,
63 column: self.column,
64 #[cfg(feature = "std")]
65 source: None,
66 }
67 }
68}
69
70impl fmt::Display for ReadError {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 match &self.kind {
73 ReadErrorKind::UnterminatedQuote => {
74 write!(f, "unterminated quote at line {}, column {}", self.line, self.column)
75 }
76 ReadErrorKind::TrailingContent => {
77 write!(
78 f,
79 "trailing content after quoted field at line {}, column {}",
80 self.line, self.column
81 )
82 }
83 ReadErrorKind::InvalidUtf8 => {
84 write!(f, "invalid UTF-8 at line {}, column {}", self.line, self.column)
85 }
86 #[cfg(feature = "serde")]
87 ReadErrorKind::Deserialize(msg) => {
88 write!(f, "deserialization error at line {}, column {}: {msg}", self.line, self.column)
89 }
90 ReadErrorKind::Io => {
91 write!(f, "I/O error at line {}, column {}", self.line, self.column)
92 }
93 }
94 }
95}
96
97#[cfg(feature = "std")]
98impl std::error::Error for ReadError {
99 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
100 self.source
101 .as_ref()
102 .map(|b| b.as_ref() as &(dyn std::error::Error + 'static))
103 }
104}
105
106#[cfg(all(not(feature = "std"), feature = "serde"))]
107impl core::error::Error for ReadError {}
108
109#[cfg(feature = "std")]
110impl From<std::io::Error> for ReadError {
111 fn from(e: std::io::Error) -> Self {
112 ReadError {
113 kind: ReadErrorKind::Io,
114 line: 0,
115 column: 0,
116 source: Some(Box::new(e)),
117 }
118 }
119}
120
121#[derive(Debug)]
123pub enum WriteError {
124 InconsistentFieldCount { expected: usize, found: usize, row: usize },
126 #[cfg(feature = "std")]
128 Io(std::io::Error),
129}
130
131impl fmt::Display for WriteError {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 match self {
134 WriteError::InconsistentFieldCount {
135 expected,
136 found,
137 row,
138 } => {
139 write!(f, "expected {expected} fields, found {found} in row {row}")
140 }
141 #[cfg(feature = "std")]
142 WriteError::Io(e) => write!(f, "I/O error: {e}"),
143 }
144 }
145}
146
147#[cfg(feature = "std")]
148impl std::error::Error for WriteError {
149 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
150 match self {
151 WriteError::Io(e) => Some(e),
152 _ => None,
153 }
154 }
155}
156
157#[cfg(feature = "std")]
158impl From<std::io::Error> for WriteError {
159 fn from(e: std::io::Error) -> Self {
160 WriteError::Io(e)
161 }
162}