Skip to main content

rama_http_headers/
header.rs

1use rama_http_types::{HeaderName, HeaderValue};
2
3use std::error;
4use std::fmt::{self, Display, Formatter};
5use std::sync::Arc;
6
7/// Base trait for a typed header.
8///
9/// To be implemented as part of being able to
10/// implement [`HeaderEncode`] and/or [`HeaderDecode`].
11pub trait TypedHeader {
12    /// The name of this header.
13    fn name() -> &'static HeaderName;
14}
15
16impl<H: TypedHeader> TypedHeader for &H {
17    #[inline(always)]
18    fn name() -> &'static HeaderName {
19        H::name()
20    }
21}
22
23impl<H: TypedHeader> TypedHeader for Arc<H> {
24    #[inline]
25    fn name() -> &'static HeaderName {
26        H::name()
27    }
28}
29
30/// A typed header which can be decoded from one or multiple headers.
31pub trait HeaderDecode: TypedHeader {
32    /// Decode this type from an iterator of [`HeaderValue`]s.
33    fn decode<'i, I>(values: &mut I) -> Result<Self, Error>
34    where
35        Self: Sized,
36        I: Iterator<Item = &'i HeaderValue>;
37}
38
39/// A typed header which can be encoded into one or multiple headers.
40pub trait HeaderEncode: TypedHeader {
41    /// Encode this type to a [`HeaderValue`], and add it to a container
42    /// which has [`HeaderValue`] type as each element.
43    ///
44    /// This function should be infallible. Any errors converting to a
45    /// `HeaderValue` should have been caught when parsing or constructing
46    /// this value.
47    fn encode<E: Extend<HeaderValue>>(&self, values: &mut E);
48
49    /// Encode this header to [`HeaderValue`].
50    ///
51    /// [`None`] is returned in case no header was encoded.
52    fn encode_to_value(&self) -> Option<HeaderValue> {
53        let mut container = ExtendOnce(None);
54        self.encode(&mut container);
55        container.0
56    }
57}
58
59impl<H: HeaderEncode> HeaderEncode for &H {
60    #[inline(always)]
61    fn encode<E: Extend<HeaderValue>>(&self, values: &mut E) {
62        (*self).encode(values);
63    }
64
65    #[inline]
66    fn encode_to_value(&self) -> Option<HeaderValue> {
67        (*self).encode_to_value()
68    }
69}
70
71impl<H: HeaderEncode> HeaderEncode for Arc<H> {
72    #[inline]
73    fn encode<E: Extend<HeaderValue>>(&self, values: &mut E) {
74        self.as_ref().encode(values);
75    }
76
77    #[inline]
78    fn encode_to_value(&self) -> Option<HeaderValue> {
79        self.as_ref().encode_to_value()
80    }
81}
82
83struct ExtendOnce(Option<HeaderValue>);
84
85impl Extend<HeaderValue> for ExtendOnce {
86    fn extend<T: IntoIterator<Item = HeaderValue>>(&mut self, iter: T) {
87        self.0 = iter.into_iter().next();
88    }
89}
90
91/// Errors trying to decode a header.
92#[derive(Debug)]
93pub struct Error {
94    kind: Kind,
95}
96
97#[derive(Debug)]
98enum Kind {
99    Invalid,
100}
101
102impl Error {
103    /// Create an 'invalid' Error.
104    #[must_use]
105    pub fn invalid() -> Self {
106        Self {
107            kind: Kind::Invalid,
108        }
109    }
110}
111
112impl Display for Error {
113    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
114        match &self.kind {
115            Kind::Invalid => f.write_str("invalid HTTP header"),
116        }
117    }
118}
119
120impl error::Error for Error {}