1use thiserror::Error;
6
7#[derive(Eq, Error, Clone, Debug, PartialEq)]
8pub enum FxfsError {
9 #[error("Already exists")]
10 AlreadyExists,
11 #[error("Filesystem inconsistency")]
12 Inconsistent,
13 #[error("Internal error")]
14 Internal,
15 #[error("Expected directory")]
16 NotDir,
17 #[error("Expected file")]
18 NotFile,
19 #[error("Not found")]
20 NotFound,
21 #[error("Not empty")]
22 NotEmpty,
23 #[error("Read only filesystem")]
24 ReadOnlyFilesystem,
25 #[error("No space")]
26 NoSpace,
27 #[error("Deleted")]
28 Deleted,
29 #[error("Invalid arguments")]
30 InvalidArgs,
31 #[error("Too big")]
32 TooBig,
33 #[error("Invalid version")]
34 InvalidVersion,
35 #[error("Journal flush error")]
36 JournalFlushError,
37 #[error("Not supported")]
38 NotSupported,
39 #[error("Access denied")]
40 AccessDenied,
41 #[error("Out of range")]
42 OutOfRange,
43 #[error("Already bound")]
44 AlreadyBound,
45 #[error("Bad path")]
46 BadPath,
47 #[error("Wrong type")]
48 WrongType,
49 #[error("Data integrity error")]
50 IntegrityError,
51 #[error("Unavailable")]
52 Unavailable,
53 #[error("No key")]
54 NoKey,
55 #[error("Inconsistent encryption policy")]
56 InconsistentEncryptionPolicy,
57}
58
59impl FxfsError {
60 pub fn matches(&self, error: &anyhow::Error) -> bool {
72 if let Some(root_cause) = error.root_cause().downcast_ref::<FxfsError>() {
73 self == root_cause
74 } else {
75 false
76 }
77 }
78}
79
80#[cfg(target_os = "fuchsia")]
81mod fuchsia {
82 use super::*;
83 use zx::Status;
84
85 impl From<FxfsError> for Status {
86 fn from(err: FxfsError) -> Status {
87 match err {
88 FxfsError::AlreadyExists => Status::ALREADY_EXISTS,
89 FxfsError::Inconsistent => Status::IO_DATA_INTEGRITY,
90 FxfsError::Internal => Status::INTERNAL,
91 FxfsError::NotDir => Status::NOT_DIR,
92 FxfsError::NotFile => Status::NOT_FILE,
93 FxfsError::NotFound => Status::NOT_FOUND,
94 FxfsError::NotEmpty => Status::NOT_EMPTY,
95 FxfsError::ReadOnlyFilesystem => Status::ACCESS_DENIED,
96 FxfsError::NoSpace => Status::NO_SPACE,
97 FxfsError::Deleted => Status::ACCESS_DENIED,
98 FxfsError::InvalidArgs => Status::INVALID_ARGS,
99 FxfsError::TooBig => Status::FILE_BIG,
100 FxfsError::InvalidVersion => Status::NOT_SUPPORTED,
101 FxfsError::JournalFlushError => Status::IO,
102 FxfsError::NotSupported => Status::NOT_SUPPORTED,
103 FxfsError::AccessDenied => Status::ACCESS_DENIED,
104 FxfsError::OutOfRange => Status::OUT_OF_RANGE,
105 FxfsError::AlreadyBound => Status::ALREADY_BOUND,
106 FxfsError::BadPath => Status::BAD_PATH,
107 FxfsError::WrongType => Status::WRONG_TYPE,
108 FxfsError::IntegrityError => Status::IO_DATA_INTEGRITY,
109 FxfsError::Unavailable => Status::UNAVAILABLE,
110 FxfsError::NoKey => Status::ACCESS_DENIED,
111 FxfsError::InconsistentEncryptionPolicy => Status::BAD_STATE,
112 }
113 }
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::FxfsError;
120 use anyhow::{Context, anyhow};
121
122 #[test]
123 fn test_matches() {
124 let err: anyhow::Error = FxfsError::AlreadyBound.into();
126 let result: Result<(), anyhow::Error> = Err(err);
127 let result = result.context("Foo");
128 let err = result.err().unwrap();
129 assert!(FxfsError::AlreadyBound.matches(&err));
130
131 let err = anyhow!(FxfsError::AlreadyBound).context("Foo");
133 assert!(FxfsError::AlreadyBound.matches(&err));
134
135 let err = anyhow!(anyhow!(FxfsError::AlreadyBound).context("Foo"));
138 assert!(FxfsError::AlreadyBound.matches(&err));
139 }
140}