1use std::error::Error;
2use std::io::{self, ErrorKind};
3
4use http::StatusCode;
5
6use crate::fs::FsError;
7
8pub(crate) type DavResult<T> = Result<T, DavError>;
9
10#[derive(Debug)]
11pub(crate) enum DavError {
12 XmlReadError, XmlParseError, InvalidPath, IllegalPath, ForbiddenPath, UnknownDavMethod,
18 ChanError,
19 Utf8Error,
20 Status(StatusCode),
21 StatusClose(StatusCode),
22 FsError(FsError),
23 IoError(io::Error),
24 XmlReaderError(xml::reader::Error),
25 XmlWriterError(xml::writer::Error),
26}
27
28impl Error for DavError {
29 fn description(&self) -> &str {
30 "DAV error"
31 }
32
33 fn cause(&self) -> Option<&dyn Error> {
34 match *self {
35 DavError::FsError(ref e) => Some(e),
36 DavError::IoError(ref e) => Some(e),
37 DavError::XmlReaderError(ref e) => Some(e),
38 DavError::XmlWriterError(ref e) => Some(e),
39 _ => None,
40 }
41 }
42}
43
44impl std::fmt::Display for DavError {
45 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
46 match *self {
47 DavError::XmlReaderError(_) => write!(f, "XML parse error"),
48 DavError::XmlWriterError(_) => write!(f, "XML generate error"),
49 DavError::IoError(_) => write!(f, "I/O error"),
50 _ => write!(f, "{:?}", self),
51 }
52 }
53}
54
55impl From<FsError> for DavError {
56 fn from(e: FsError) -> Self {
57 DavError::FsError(e)
58 }
59}
60
61impl From<DavError> for io::Error {
62 fn from(e: DavError) -> Self {
63 match e {
64 DavError::IoError(e) => e,
65 DavError::FsError(e) => e.into(),
66 _ => io::Error::new(io::ErrorKind::Other, e),
67 }
68 }
69}
70
71impl From<FsError> for io::Error {
72 fn from(e: FsError) -> Self {
73 fserror_to_ioerror(e)
74 }
75}
76
77impl From<io::Error> for DavError {
78 fn from(e: io::Error) -> Self {
79 DavError::IoError(e)
80 }
81}
82
83impl From<StatusCode> for DavError {
84 fn from(e: StatusCode) -> Self {
85 DavError::Status(e)
86 }
87}
88
89impl From<xml::reader::Error> for DavError {
90 fn from(e: xml::reader::Error) -> Self {
91 DavError::XmlReaderError(e)
92 }
93}
94
95impl From<xml::writer::Error> for DavError {
96 fn from(e: xml::writer::Error) -> Self {
97 DavError::XmlWriterError(e)
98 }
99}
100
101impl From<std::str::Utf8Error> for DavError {
102 fn from(_: std::str::Utf8Error) -> Self {
103 DavError::Utf8Error
104 }
105}
106
107impl From<std::string::FromUtf8Error> for DavError {
108 fn from(_: std::string::FromUtf8Error) -> Self {
109 DavError::Utf8Error
110 }
111}
112
113impl From<futures_channel::mpsc::SendError> for DavError {
114 fn from(_e: futures_channel::mpsc::SendError) -> Self {
115 DavError::ChanError
116 }
117}
118
119fn fserror_to_ioerror(e: FsError) -> io::Error {
120 match e {
121 FsError::NotImplemented => io::Error::new(io::ErrorKind::Other, "NotImplemented"),
122 FsError::GeneralFailure => io::Error::new(io::ErrorKind::Other, "GeneralFailure"),
123 FsError::Exists => io::Error::new(io::ErrorKind::AlreadyExists, "Exists"),
124 FsError::NotFound => io::Error::new(io::ErrorKind::NotFound, "Notfound"),
125 FsError::Forbidden => io::Error::new(io::ErrorKind::PermissionDenied, "Forbidden"),
126 FsError::InsufficientStorage => io::Error::new(io::ErrorKind::Other, "InsufficientStorage"),
127 FsError::LoopDetected => io::Error::new(io::ErrorKind::Other, "LoopDetected"),
128 FsError::PathTooLong => io::Error::new(io::ErrorKind::Other, "PathTooLong"),
129 FsError::TooLarge => io::Error::new(io::ErrorKind::Other, "TooLarge"),
130 FsError::IsRemote => io::Error::new(io::ErrorKind::Other, "IsRemote"),
131 }
132}
133
134fn ioerror_to_status(ioerror: &io::Error) -> StatusCode {
135 match ioerror.kind() {
136 ErrorKind::NotFound => StatusCode::NOT_FOUND,
137 ErrorKind::PermissionDenied => StatusCode::FORBIDDEN,
138 ErrorKind::AlreadyExists => StatusCode::CONFLICT,
139 ErrorKind::TimedOut => StatusCode::GATEWAY_TIMEOUT,
140 _ => StatusCode::BAD_GATEWAY,
141 }
142}
143
144fn fserror_to_status(e: &FsError) -> StatusCode {
145 match e {
146 FsError::NotImplemented => StatusCode::NOT_IMPLEMENTED,
147 FsError::GeneralFailure => StatusCode::INTERNAL_SERVER_ERROR,
148 FsError::Exists => StatusCode::METHOD_NOT_ALLOWED,
149 FsError::NotFound => StatusCode::NOT_FOUND,
150 FsError::Forbidden => StatusCode::FORBIDDEN,
151 FsError::InsufficientStorage => StatusCode::INSUFFICIENT_STORAGE,
152 FsError::LoopDetected => StatusCode::LOOP_DETECTED,
153 FsError::PathTooLong => StatusCode::URI_TOO_LONG,
154 FsError::TooLarge => StatusCode::PAYLOAD_TOO_LARGE,
155 FsError::IsRemote => StatusCode::BAD_GATEWAY,
156 }
157}
158
159impl DavError {
160 pub(crate) fn statuscode(&self) -> StatusCode {
161 match *self {
162 DavError::XmlReadError => StatusCode::BAD_REQUEST,
163 DavError::XmlParseError => StatusCode::BAD_REQUEST,
164 DavError::InvalidPath => StatusCode::BAD_REQUEST,
165 DavError::IllegalPath => StatusCode::BAD_GATEWAY,
166 DavError::ForbiddenPath => StatusCode::FORBIDDEN,
167 DavError::UnknownDavMethod => StatusCode::NOT_IMPLEMENTED,
168 DavError::ChanError => StatusCode::INTERNAL_SERVER_ERROR,
169 DavError::Utf8Error => StatusCode::UNSUPPORTED_MEDIA_TYPE,
170 DavError::IoError(ref e) => ioerror_to_status(e),
171 DavError::FsError(ref e) => fserror_to_status(e),
172 DavError::Status(e) => e,
173 DavError::StatusClose(e) => e,
174 DavError::XmlReaderError(ref _e) => StatusCode::BAD_REQUEST,
175 DavError::XmlWriterError(ref _e) => StatusCode::INTERNAL_SERVER_ERROR,
176 }
177 }
178
179 pub(crate) fn must_close(&self) -> bool {
180 !matches!(
181 self,
182 &DavError::Status(_)
183 | &DavError::FsError(FsError::NotFound)
184 | &DavError::FsError(FsError::Forbidden)
185 | &DavError::FsError(FsError::Exists)
186 )
187 }
188}