Skip to main content

simd_csv/
error.rs

1use std::{error, fmt, io, result};
2
3/// The specific type of an error.
4#[derive(Debug)]
5#[non_exhaustive]
6pub enum ErrorKind {
7    /// Wrap a [std::io::Error].
8    Io(io::Error),
9
10    /// Indicate that utf-8 decoding failed when reading a record.
11    Utf8Error,
12
13    /// Indicate that a selector could not be parsed
14    SelectorParseError(String),
15
16    /// Indictae that a selector could not be succefully applied on given headers
17    SelectionError(String),
18
19    /// Indicate that a non-flexible reader or writer attempted to read/write a
20    /// unaligned record having an incorrect number of fields.
21    UnequalLengths {
22        /// Expected number of fields
23        expected_len: usize,
24        /// Actual and incorrect number of fields observed
25        len: usize,
26        /// Optional position `(byte_offset, record_index)`
27        pos: Option<(u64, u64)>,
28    },
29
30    /// Indicate that a [`Seeker`](crate::Seeker) attempted to find a record in
31    /// a position that is out of bounds
32    OutOfBounds {
33        /// Desired position
34        pos: u64,
35        /// Byte offset of the first record
36        start: u64,
37        /// Byte length of the considered stream
38        end: u64,
39    },
40}
41
42/// An error occurring when reading/writing CSV data.
43#[derive(Debug)]
44pub struct Error(ErrorKind);
45
46impl Error {
47    pub(crate) fn new(kind: ErrorKind) -> Self {
48        Self(kind)
49    }
50
51    /// Return whether the wrapped error is a [`std::io::Error`].
52    pub fn is_io_error(&self) -> bool {
53        matches!(self.0, ErrorKind::Io(_))
54    }
55
56    /// Return a reference to the underlying [`ErrorKind`].
57    pub fn kind(&self) -> &ErrorKind {
58        &self.0
59    }
60
61    /// Unwraps the error into its underlying [`ErrorKind`].
62    pub fn into_kind(self) -> ErrorKind {
63        self.0
64    }
65}
66
67impl From<io::Error> for Error {
68    fn from(err: io::Error) -> Self {
69        Self(ErrorKind::Io(err))
70    }
71}
72
73impl From<Error> for io::Error {
74    fn from(err: Error) -> Self {
75        Self::other(err)
76    }
77}
78
79impl error::Error for Error {}
80
81impl fmt::Display for Error {
82    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83        match self.0 {
84            ErrorKind::Io(ref err) => err.fmt(f),
85            ErrorKind::Utf8Error => write!(f, "utf8 decode error"),
86            ErrorKind::SelectorParseError(ref msg) => write!(f, "{}", msg),
87            ErrorKind::SelectionError(ref msg) => write!(f, "{}", msg),
88            ErrorKind::UnequalLengths {
89                expected_len,
90                len,
91                pos: Some((byte, index))
92            } => write!(
93                f,
94                "CSV error: record {} (byte: {}): found record with {} fields, but the previous record has {} fields",
95                index, byte, len, expected_len
96            ),
97             ErrorKind::UnequalLengths {
98                expected_len,
99                len,
100                pos: None
101            } => write!(
102                f,
103                "CSV error: found record with {} fields, but the previous record has {} fields",
104                len, expected_len
105            ),
106            ErrorKind::OutOfBounds { pos, start, end } => {
107                write!(f, "pos {} is out of bounds (should be >= {} and < {})", pos, start, end)
108            }
109        }
110    }
111}
112
113/// A type alias for `Result<T, simd_csv::Error>`.
114pub type Result<T> = result::Result<T, Error>;