Skip to main content

fs_core/
error.rs

1//! Unified error type. Each driver still keeps its own rich error type for
2//! internal use; conversions to/from this one happen at the trait boundary.
3
4use std::fmt;
5use std::io;
6
7#[derive(Debug)]
8pub enum Error {
9    /// Underlying I/O failure (open, seek, read, write).
10    Io(io::Error),
11    /// Device returned fewer bytes than requested before EOF.
12    ShortRead {
13        offset: u64,
14        want: usize,
15        got: usize,
16    },
17    /// `write_at` invoked on a device opened read-only.
18    ReadOnly,
19    /// Read or write past the end of the device.
20    OutOfBounds { offset: u64, len: u64, size: u64 },
21    /// Driver-specific error lifted to the trait boundary. Each driver's
22    /// internal error type implements `Into<Error>` via this variant.
23    Custom(String),
24}
25
26impl fmt::Display for Error {
27    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        match self {
29            Error::Io(e) => write!(f, "io: {e}"),
30            Error::ShortRead { offset, want, got } => {
31                write!(f, "short read at {offset}: wanted {want} got {got}")
32            }
33            Error::ReadOnly => write!(f, "device is read-only"),
34            Error::OutOfBounds { offset, len, size } => {
35                write!(f, "{offset}+{len} past device size {size}")
36            }
37            Error::Custom(s) => f.write_str(s),
38        }
39    }
40}
41
42impl std::error::Error for Error {
43    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
44        match self {
45            Error::Io(e) => Some(e),
46            _ => None,
47        }
48    }
49}
50
51impl From<io::Error> for Error {
52    fn from(e: io::Error) -> Self {
53        Error::Io(e)
54    }
55}
56
57pub type Result<T> = std::result::Result<T, Error>;