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 non-flexible reader or writer attempted to read/write a
14    /// unaligned record having an incorrect number of fields.
15    UnequalLengths {
16        /// Expected number of fields
17        expected_len: usize,
18        /// Actual and incorrect number of fields observed
19        len: usize,
20        /// Optional position `(byte_offset, record_index)`
21        pos: Option<(u64, u64)>,
22    },
23
24    /// Indicate that a [`Seeker`](crate::Seeker) attempted to find a record in
25    /// a position that is out of bounds
26    OutOfBounds {
27        /// Desired position
28        pos: u64,
29        /// Byte offset of the first record
30        start: u64,
31        /// Byte length of the considered stream
32        end: u64,
33    },
34}
35
36/// An error occurring when reading/writing CSV data.
37#[derive(Debug)]
38pub struct Error(ErrorKind);
39
40impl Error {
41    pub(crate) fn new(kind: ErrorKind) -> Self {
42        Self(kind)
43    }
44
45    /// Return whether the wrapped error is a [`std::io::Error`].
46    pub fn is_io_error(&self) -> bool {
47        matches!(self.0, ErrorKind::Io(_))
48    }
49
50    /// Return a reference to the underlying [`ErrorKind`].
51    pub fn kind(&self) -> &ErrorKind {
52        &self.0
53    }
54
55    /// Unwraps the error into its underlying [`ErrorKind`].
56    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
105/// A type alias for `Result<T, simd_csv::Error>`.
106pub type Result<T> = result::Result<T, Error>;