webdav_headers/
timeout.rs

1// SPDX-FileCopyrightText: d-k-bo <d-k-bo@mailbox.org>
2//
3// SPDX-License-Identifier: MIT OR Apache-2.0
4
5use http::HeaderValue;
6
7use crate::{
8    utils::{HeaderIteratorExt, StrExt},
9    TIMEOUT,
10};
11
12/// The `Timeout` header as defined in [RFC 4918](http://webdav.org/specs/rfc4918.html#HEADER_Timeout).
13#[derive(Clone, Copy, Debug, PartialEq)]
14pub enum Timeout {
15    Seconds(u32),
16    Infinite,
17}
18
19impl headers::Header for Timeout {
20    fn name() -> &'static http::HeaderName {
21        &TIMEOUT
22    }
23
24    fn decode<'i, I>(values: &mut I) -> Result<Self, headers::Error>
25    where
26        Self: Sized,
27        I: Iterator<Item = &'i http::HeaderValue>,
28    {
29        let s = values.extract_str()?;
30
31        if s.eq_ignore_ascii_case("Infinite") {
32            Ok(Self::Infinite)
33        } else if let Some(seconds) = s
34            .strip_prefix_ignore_ascii_case("Second-")
35            .and_then(|s| s.parse().ok())
36        {
37            Ok(Self::Seconds(seconds))
38        } else {
39            Err(headers::Error::invalid())
40        }
41    }
42
43    fn encode<E: Extend<http::HeaderValue>>(&self, values: &mut E) {
44        values.extend(std::iter::once(match self {
45            Self::Seconds(seconds) => format!("Second-{seconds}").try_into().unwrap(),
46            Self::Infinite => HeaderValue::from_static("Infinite"),
47        }))
48    }
49}
50
51#[cfg(test)]
52#[test]
53fn test() {
54    use crate::test::test_all;
55
56    test_all([
57        ("Second-123", Timeout::Seconds(123)),
58        ("Infinite", Timeout::Infinite),
59    ])
60}