1use std::{error, fmt, io, result};
2
3#[derive(Debug)]
5#[non_exhaustive]
6pub enum ErrorKind {
7 Io(io::Error),
9
10 Utf8Error,
12
13 UnequalLengths {
16 expected_len: usize,
18 len: usize,
20 pos: Option<(u64, u64)>,
22 },
23
24 OutOfBounds {
27 pos: u64,
29 start: u64,
31 end: u64,
33 },
34}
35
36#[derive(Debug)]
38pub struct Error(ErrorKind);
39
40impl Error {
41 pub(crate) fn new(kind: ErrorKind) -> Self {
42 Self(kind)
43 }
44
45 pub fn is_io_error(&self) -> bool {
47 matches!(self.0, ErrorKind::Io(_))
48 }
49
50 pub fn kind(&self) -> &ErrorKind {
52 &self.0
53 }
54
55 pub fn into_kind(self) -> ErrorKind {
57 self.0
58 }
59}
60
61impl From<io::Error> for Error {
62 fn from(err: io::Error) -> Self {
63 Self(ErrorKind::Io(err))
64 }
65}
66
67impl From<Error> for io::Error {
68 fn from(err: Error) -> Self {
69 Self::other(err)
70 }
71}
72
73impl error::Error for Error {}
74
75impl fmt::Display for Error {
76 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77 match self.0 {
78 ErrorKind::Io(ref err) => err.fmt(f),
79 ErrorKind::Utf8Error => write!(f, "utf8 decode error"),
80 ErrorKind::UnequalLengths {
81 expected_len,
82 len,
83 pos: Some((byte, index))
84 } => write!(
85 f,
86 "CSV error: record {} (byte: {}): found record with {} fields, but the previous record has {} fields",
87 index, byte, len, expected_len
88 ),
89 ErrorKind::UnequalLengths {
90 expected_len,
91 len,
92 pos: None
93 } => write!(
94 f,
95 "CSV error: found record with {} fields, but the previous record has {} fields",
96 len, expected_len
97 ),
98 ErrorKind::OutOfBounds { pos, start, end } => {
99 write!(f, "pos {} is out of bounds (should be >= {} and < {})", pos, start, end)
100 }
101 }
102 }
103}
104
105pub type Result<T> = result::Result<T, Error>;