rustical_dav/header/
depth.rs

1use actix_web::{FromRequest, HttpRequest, ResponseError, http::StatusCode};
2use futures_util::future::{Ready, err, ok};
3use rustical_xml::{ValueDeserialize, ValueSerialize, XmlError};
4use thiserror::Error;
5
6#[derive(Error, Debug)]
7#[error("Invalid Depth header")]
8pub struct InvalidDepthHeader;
9
10impl ResponseError for InvalidDepthHeader {
11    fn status_code(&self) -> actix_web::http::StatusCode {
12        StatusCode::BAD_REQUEST
13    }
14}
15
16#[derive(Debug, Clone, PartialEq)]
17pub enum Depth {
18    Zero,
19    One,
20    Infinity,
21}
22
23impl ValueSerialize for Depth {
24    fn serialize(&self) -> String {
25        match self {
26            Depth::Zero => "0",
27            Depth::One => "1",
28            Depth::Infinity => "infinity",
29        }
30        .to_owned()
31    }
32}
33
34impl ValueDeserialize for Depth {
35    fn deserialize(val: &str) -> Result<Self, XmlError> {
36        match val {
37            "0" => Ok(Self::Zero),
38            "1" => Ok(Self::One),
39            "infinity" | "Infinity" => Ok(Self::Infinity),
40            _ => Err(XmlError::InvalidVariant(
41                "Invalid value for depth".to_owned(),
42            )),
43        }
44    }
45}
46
47impl TryFrom<&[u8]> for Depth {
48    type Error = InvalidDepthHeader;
49
50    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
51        match value {
52            b"0" => Ok(Depth::Zero),
53            b"1" => Ok(Depth::One),
54            b"Infinity" | b"infinity" => Ok(Depth::Infinity),
55            _ => Err(InvalidDepthHeader),
56        }
57    }
58}
59
60impl FromRequest for Depth {
61    type Error = InvalidDepthHeader;
62    type Future = Ready<Result<Self, Self::Error>>;
63
64    fn extract(req: &HttpRequest) -> Self::Future {
65        if let Some(depth_header) = req.headers().get("Depth") {
66            match depth_header.as_bytes().try_into() {
67                Ok(depth) => ok(depth),
68                Err(e) => err(e),
69            }
70        } else {
71            // default depth
72            ok(Depth::Zero)
73        }
74    }
75
76    fn from_request(req: &HttpRequest, _payload: &mut actix_web::dev::Payload) -> Self::Future {
77        Self::extract(req)
78    }
79}