1pub mod list_cmd;
2
3use std::fmt;
4use std::fmt::{Debug, Display, Formatter};
5
6use reqwest::Response;
7use serde_derive::{Deserialize, Serialize};
8
9pub enum Error {
10 Reqwest(reqwest::Error),
11 ReqwestDecode(ReqwestDecodeError),
12 Decode(DecodeError),
13 MissingAuthContext,
14}
15
16pub enum DecodeError {
17 DigestAuth(digest_auth::Error),
18 NoAuthHeaderInResponse,
19 SerdeXml(serde_xml_rs::Error),
20 FieldNotSupported(FieldError),
21 FieldNotFound(FieldError),
22 StatusMismatched(StatusMismatchedError),
23 Server(ServerError),
24}
25
26#[derive(Debug)]
27pub struct FieldError {
28 pub field: String,
29}
30
31#[derive(Debug)]
32pub struct StatusMismatchedError {
33 pub response_code: u16,
34 pub expected_code: u16,
35}
36
37#[derive(Debug)]
38pub struct ServerError {
39 pub response_code: u16,
40 pub exception: String,
41 pub message: String,
42}
43
44#[derive(Debug)]
45pub enum ReqwestDecodeError {
46 Url(url::ParseError),
47 HeaderToString(reqwest::header::ToStrError),
48 InvalidHeaderValue(reqwest::header::InvalidHeaderValue),
49 InvalidMethod(http::method::InvalidMethod),
50}
51
52impl Debug for Error {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 let mut builder = f.debug_struct("reqwest_dav::Error");
55 match self {
56 Error::Reqwest(err) => {
57 builder.field("kind", &"Reqwest");
58 builder.field("source", err);
59 }
60 Error::ReqwestDecode(err) => {
61 builder.field("kind", &"ReqwestDecode");
62 builder.field("source", err);
63 }
64 Error::Decode(err) => {
65 builder.field("kind", &"Decode");
66 builder.field("source", err);
67 }
68 Error::MissingAuthContext => {
69 builder.field("kind", &"MissingAuthContext");
70 }
71 }
72 builder.finish()
73 }
74}
75
76impl Display for Error {
77 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78 let mut builder = f.debug_struct("reqwest_dav::Error");
79 match self {
80 Error::Reqwest(err) => {
81 builder.field("kind", &"Reqwest");
82 builder.field("source", err);
83 }
84 Error::ReqwestDecode(err) => {
85 builder.field("kind", &"ReqwestDecode");
86 builder.field("source", err);
87 }
88 Error::Decode(err) => {
89 builder.field("kind", &"Decode");
90 builder.field("source", err);
91 }
92 Error::MissingAuthContext => {
93 builder.field(
94 "kind",
95 &"Tried to make a digest request without a valid context.",
96 );
97 }
98 }
99 builder.finish()
100 }
101}
102
103impl Debug for DecodeError {
104 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
105 match self {
106 Self::DigestAuth(arg0) => f.debug_tuple("DigestAuth").field(arg0).finish(),
107 Self::SerdeXml(arg0) => f.debug_tuple("SerdeXml").field(arg0).finish(),
108 Self::FieldNotSupported(arg0) => f.debug_tuple("NotSupported").field(arg0).finish(),
109 Self::FieldNotFound(arg0) => f.debug_tuple("NotFound").field(arg0).finish(),
110 Self::StatusMismatched(arg0) => f.debug_tuple("StatusMismatched").field(arg0).finish(),
111 Self::Server(arg0) => f.debug_tuple("Server").field(arg0).finish(),
112 Self::NoAuthHeaderInResponse => f.debug_tuple("NoAuthHeaderInResponse").finish(),
113 }
114 }
115}
116
117impl Display for DecodeError {
118 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
119 match self {
120 Self::DigestAuth(arg0) => f.debug_tuple("DigestAuth").field(arg0).finish(),
121 Self::SerdeXml(arg0) => f.debug_tuple("SerdeXml").field(arg0).finish(),
122 Self::FieldNotSupported(arg0) => f.debug_tuple("NotSupported").field(arg0).finish(),
123 Self::FieldNotFound(arg0) => f.debug_tuple("NotFound").field(arg0).finish(),
124 Self::StatusMismatched(arg0) => f.debug_tuple("StatusMismatched").field(arg0).finish(),
125 Self::Server(arg0) => f.debug_tuple("Server").field(arg0).finish(),
126 Self::NoAuthHeaderInResponse => f.debug_tuple("NoAuthHeaderInResponse").finish(),
127 }
128 }
129}
130
131impl std::error::Error for Error {}
132
133impl From<url::ParseError> for Error {
134 fn from(error: url::ParseError) -> Self {
135 Error::ReqwestDecode(ReqwestDecodeError::Url(error))
136 }
137}
138
139impl From<reqwest::Error> for Error {
140 fn from(error: reqwest::Error) -> Self {
141 Error::Reqwest(error)
142 }
143}
144
145impl From<reqwest::header::ToStrError> for Error {
146 fn from(error: reqwest::header::ToStrError) -> Self {
147 Error::ReqwestDecode(ReqwestDecodeError::HeaderToString(error))
148 }
149}
150
151impl From<reqwest::header::InvalidHeaderValue> for Error {
152 fn from(error: reqwest::header::InvalidHeaderValue) -> Self {
153 Error::ReqwestDecode(ReqwestDecodeError::InvalidHeaderValue(error))
154 }
155}
156
157impl From<http::method::InvalidMethod> for Error {
158 fn from(error: http::method::InvalidMethod) -> Self {
159 Error::ReqwestDecode(ReqwestDecodeError::InvalidMethod(error))
160 }
161}
162
163impl From<digest_auth::Error> for Error {
164 fn from(error: digest_auth::Error) -> Self {
165 Error::Decode(DecodeError::DigestAuth(error))
166 }
167}
168
169impl From<serde_xml_rs::Error> for Error {
170 fn from(error: serde_xml_rs::Error) -> Self {
171 Error::Decode(DecodeError::SerdeXml(error))
172 }
173}
174
175#[derive(Debug, Clone, Serialize, Deserialize)]
176struct DavErrorTmp {
177 pub exception: String,
178 pub message: String,
179}
180
181#[async_trait::async_trait]
182pub trait Dav2xx {
183 async fn dav2xx(self) -> Result<Response, Error>;
184}
185
186#[async_trait::async_trait]
187impl Dav2xx for Response {
188 async fn dav2xx(self) -> Result<Response, Error> {
189 let code = self.status().as_u16();
190 if code / 100 == 2 {
191 Ok(self)
192 } else {
193 let text = self.text().await?;
194 let tmp: DavErrorTmp = match serde_xml_rs::from_str(&text) {
195 Ok(tmp) => tmp,
196 Err(_) => {
197 return Err(Error::Decode(DecodeError::Server(ServerError {
198 response_code: code,
199 exception: "server exception and parse error".to_owned(),
200 message: text,
201 })))
202 }
203 };
204 Err(Error::Decode(DecodeError::Server(ServerError {
205 response_code: code,
206 exception: tmp.exception,
207 message: tmp.message,
208 })))
209 }
210 }
211}
212
213#[derive(Debug, Clone)]
214pub enum Auth {
215 Anonymous,
216 Basic(String, String),
217 Digest(String, String),
218}
219
220#[derive(Debug, Clone)]
221pub enum Depth {
222 Number(i64),
223 Infinity,
224}