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 { offset: u64, want: usize, got: usize },
13    /// `write_at` invoked on a device opened read-only.
14    ReadOnly,
15    /// Read or write past the end of the device.
16    OutOfBounds { offset: u64, len: u64, size: u64 },
17    /// Driver-specific error lifted to the trait boundary. Each driver's
18    /// internal error type implements `Into<Error>` via this variant.
19    Custom(String),
20}
21
22impl fmt::Display for Error {
23    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24        match self {
25            Error::Io(e) => write!(f, "io: {e}"),
26            Error::ShortRead { offset, want, got } => {
27                write!(f, "short read at {offset}: wanted {want} got {got}")
28            }
29            Error::ReadOnly => write!(f, "device is read-only"),
30            Error::OutOfBounds { offset, len, size } => {
31                write!(f, "{offset}+{len} past device size {size}")
32            }
33            Error::Custom(s) => f.write_str(s),
34        }
35    }
36}
37
38impl std::error::Error for Error {
39    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
40        match self {
41            Error::Io(e) => Some(e),
42            _ => None,
43        }
44    }
45}
46
47impl From<io::Error> for Error {
48    fn from(e: io::Error) -> Self {
49        Error::Io(e)
50    }
51}
52
53pub type Result<T> = std::result::Result<T, Error>;