ouisync/
error.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use crate::{db, store};
use std::{array::TryFromSliceError, fmt, io};
use thiserror::Error;

/// A specialized `Result` type for convenience.
pub type Result<T, E = Error> = std::result::Result<T, E>;

#[derive(Debug, Error)]
pub enum Error {
    // TODO: remove / merge with `Store`
    #[error("database error")]
    Db(#[from] db::Error),
    #[error("store error")]
    Store(#[from] store::Error),
    #[error("permission denied")]
    PermissionDenied,
    // TODO: remove
    #[error("data is malformed")]
    MalformedData,
    #[error("invalid argument")]
    InvalidArgument,
    #[error("not a directory or directory malformed")]
    MalformedDirectory,
    #[error("entry already exists")]
    EntryExists,
    #[error("entry not found")]
    EntryNotFound,
    #[error("ambiguous entry")]
    AmbiguousEntry,
    #[error("entry is a file")]
    EntryIsFile,
    #[error("entry is a directory")]
    EntryIsDirectory,
    #[error("File name is not a valid UTF-8 string")]
    NonUtf8FileName,
    #[error("offset is out of range")]
    OffsetOutOfRange,
    #[error("directory is not empty")]
    DirectoryNotEmpty,
    #[error("operation is not supported")]
    OperationNotSupported,
    #[error("failed to write into writer")]
    Writer(#[source] io::Error),
    #[error("storage version mismatch")]
    StorageVersionMismatch,
    #[error("file or directory is locked")]
    Locked,
}

impl Error {
    /// Returns an object that implements `Display` which prints this error together with its whole
    /// causal chain.
    pub fn verbose(&self) -> Verbose {
        Verbose(self)
    }
}

impl From<TryFromSliceError> for Error {
    fn from(_: TryFromSliceError) -> Self {
        Self::MalformedData
    }
}

impl From<sqlx::Error> for Error {
    fn from(src: sqlx::Error) -> Self {
        Self::Db(src.into())
    }
}

pub struct Verbose<'a>(&'a Error);

impl fmt::Display for Verbose<'_> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use std::error::Error;

        writeln!(f, "{}", self.0)?;

        let mut current = self.0 as &dyn Error;

        while let Some(source) = current.source() {
            writeln!(f, "    caused by: {}", source)?;
            current = source;
        }

        Ok(())
    }
}