1use crate::{CodePageMark, FieldConversionError, FieldInfo};
2use std::string::FromUtf8Error;
3
4#[derive(Debug)]
5#[non_exhaustive]
6pub enum ErrorKind {
7 IoError(std::io::Error),
9 ParseFloatError(std::num::ParseFloatError),
11 ParseIntError(std::num::ParseIntError),
13 InvalidFieldType(char),
15 MissingMemoFile,
18 ErrorOpeningMemoFile(std::io::Error),
20 BadConversion(FieldConversionError),
22 EndOfRecord,
24 NotEnoughFields,
26 TooManyFields,
28 IncompatibleType,
31 UnsupportedCodePage(CodePageMark),
33 StringDecodeError(DecodeError),
35 StringEncodeError(EncodeError),
37 Message(String),
38}
39
40#[derive(Debug)]
42pub struct Error {
43 pub(crate) record_num: usize,
44 pub(crate) field: Option<FieldInfo>,
45 pub(crate) kind: ErrorKind,
46}
47
48impl Error {
49 pub(crate) fn new(field_error: FieldIOError, current_record: usize) -> Self {
50 Self {
51 record_num: current_record,
52 field: field_error.field,
53 kind: field_error.kind,
54 }
55 }
56
57 pub(crate) fn io_error(error: std::io::Error, current_record: usize) -> Self {
58 Self {
59 record_num: current_record,
60 field: None,
61 kind: ErrorKind::IoError(error),
62 }
63 }
64
65 pub fn kind(&self) -> &ErrorKind {
67 &self.kind
68 }
69
70 pub fn record_num(&self) -> usize {
75 self.record_num
76 }
77
78 pub fn field(&self) -> &Option<FieldInfo> {
80 &self.field
81 }
82}
83
84#[derive(Debug)]
85pub struct FieldIOError {
86 pub(crate) field: Option<FieldInfo>,
87 pub(crate) kind: ErrorKind,
88}
89
90impl FieldIOError {
91 pub fn new(kind: ErrorKind, field: Option<FieldInfo>) -> Self {
92 Self { field, kind }
93 }
94
95 pub(crate) fn end_of_record() -> Self {
96 Self {
97 field: None,
98 kind: ErrorKind::EndOfRecord,
99 }
100 }
101
102 pub fn kind(&self) -> &ErrorKind {
103 &self.kind
104 }
105}
106
107impl From<std::io::Error> for ErrorKind {
108 fn from(e: std::io::Error) -> Self {
109 ErrorKind::IoError(e)
110 }
111}
112
113impl From<std::num::ParseFloatError> for ErrorKind {
114 fn from(p: std::num::ParseFloatError) -> Self {
115 ErrorKind::ParseFloatError(p)
116 }
117}
118
119impl From<std::num::ParseIntError> for ErrorKind {
120 fn from(p: std::num::ParseIntError) -> Self {
121 ErrorKind::ParseIntError(p)
122 }
123}
124
125impl From<FieldConversionError> for ErrorKind {
126 fn from(e: FieldConversionError) -> Self {
127 ErrorKind::BadConversion(e)
128 }
129}
130
131impl From<DecodeError> for ErrorKind {
132 fn from(e: DecodeError) -> Self {
133 ErrorKind::StringDecodeError(e)
134 }
135}
136
137impl From<EncodeError> for ErrorKind {
138 fn from(e: EncodeError) -> Self {
139 ErrorKind::StringEncodeError(e)
140 }
141}
142
143impl From<FieldConversionError> for FieldIOError {
144 fn from(e: FieldConversionError) -> Self {
145 FieldIOError::new(ErrorKind::BadConversion(e), None)
146 }
147}
148
149impl std::fmt::Display for Error {
150 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
151 if let Some(field_info) = &self.field {
152 write!(
153 f,
154 "Error {{ record_num: {}, kind: {}, {} }}",
155 self.record_num, self.kind, field_info
156 )
157 } else {
158 write!(
159 f,
160 "Error {{ record_num: {}, kind: {} }}",
161 self.record_num, self.kind
162 )
163 }
164 }
165}
166
167impl std::error::Error for Error {}
174
175impl std::fmt::Display for ErrorKind {
176 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
177 match self {
178 ErrorKind::IoError(err) => write!(f, "An I/O error happened: {err}"),
179 ErrorKind::ParseFloatError(err) => {
180 write!(f, "Float value could not be obtained: {err}")
181 }
182 ErrorKind::ParseIntError(err) => {
183 write!(f, "Integer value could not be obtained: {err}")
184 }
185 ErrorKind::InvalidFieldType(c) => {
186 write!(f, "The FieldType code '{c}' is note a valid one")
187 }
188 ErrorKind::MissingMemoFile => write!(f, "The memo file could not be found"),
189 ErrorKind::ErrorOpeningMemoFile(err) => {
190 write!(
191 f,
192 "An error occurred when trying to open the memo file: {err}"
193 )
194 }
195 ErrorKind::BadConversion(err) => write!(f, "The convertion cannot be made: {err}"),
196 ErrorKind::EndOfRecord => write!(f, "End of record reached, no more fields left"),
197 ErrorKind::NotEnoughFields => {
198 write!(
199 f,
200 "The writer did not expected that many fields for the record"
201 )
202 }
203 ErrorKind::TooManyFields => {
204 write!(f, "The writer expected to write more fields for the record")
205 }
206 ErrorKind::IncompatibleType => write!(f, "The types are not compatible"),
207 ErrorKind::StringDecodeError(err) => {
208 write!(f, "A string from the database could not be decoded: {err}")
209 }
210 ErrorKind::StringEncodeError(err) => {
211 write!(f, "A string from the database could not be encoded: {err}")
212 }
213 ErrorKind::UnsupportedCodePage(code) => {
214 write!(f, "The code page '{code:?}' is not supported")
215 }
216 ErrorKind::Message(ref msg) => write!(f, "{msg}"),
217 }
218 }
219}
220
221impl std::fmt::Display for FieldIOError {
222 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
223 if let Some(field_info) = &self.field {
224 write!(f, "FieldIOError {{ kind: {}, {} }}", self.kind, field_info)
225 } else {
226 write!(f, "FieldIOError {{ kind: {:?} }}", self.kind)
227 }
228 }
229}
230
231impl std::error::Error for FieldIOError {}
232
233#[derive(Debug)]
234#[non_exhaustive]
235pub enum DecodeError {
236 Message(String),
237 FromUtf8(FromUtf8Error),
238 NotAscii,
239 #[cfg(feature = "yore")]
240 Yore(yore::DecodeError),
241}
242
243impl From<String> for DecodeError {
244 fn from(msg: String) -> Self {
245 Self::Message(msg)
246 }
247}
248
249#[cfg(feature = "yore")]
250impl From<yore::DecodeError> for DecodeError {
251 fn from(e: yore::DecodeError) -> Self {
252 DecodeError::Yore(e)
253 }
254}
255
256impl std::fmt::Display for DecodeError {
257 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
258 write!(f, "{self:?}")
259 }
260}
261
262impl std::error::Error for DecodeError {}
263
264#[derive(Debug)]
265#[non_exhaustive]
266pub enum EncodeError {
267 Message(String),
268 #[cfg(feature = "yore")]
269 Yore(yore::EncodeError),
270}
271
272impl From<String> for EncodeError {
273 fn from(msg: String) -> Self {
274 Self::Message(msg)
275 }
276}
277
278#[cfg(feature = "yore")]
279impl From<yore::EncodeError> for EncodeError {
280 fn from(e: yore::EncodeError) -> Self {
281 EncodeError::Yore(e)
282 }
283}
284
285impl std::fmt::Display for EncodeError {
286 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
287 write!(f, "{self:?}")
288 }
289}
290
291impl std::error::Error for EncodeError {}