Skip to main content

sark_core/http/response/direct/
value.rs

1use o3::buffer::{Borrowed, Bytes, Owned, Retained, Shared};
2
3use super::headers::HeaderNameToken;
4
5#[derive(Clone)]
6pub enum HeaderValueInner<'req> {
7    Static(&'static [u8]),
8    Inline(InlineHeaderValue),
9    Shared(Shared),
10    Borrowed(Bytes<Borrowed<'req>>),
11    Retained(Bytes<Retained>),
12}
13
14#[derive(Clone, Copy)]
15pub struct InlineHeaderValue {
16    bytes: [u8; 31],
17    len: u8,
18}
19
20impl InlineHeaderValue {
21    pub fn new(value: &[u8]) -> Self {
22        assert!(
23            value.len() <= 31,
24            "inline header value overflow: max 31, got {}",
25            value.len()
26        );
27        let mut bytes = [0u8; 31];
28        bytes[..value.len()].copy_from_slice(value);
29        Self {
30            bytes,
31            len: value.len() as u8,
32        }
33    }
34
35    pub fn as_bytes(&self) -> &[u8] {
36        &self.bytes[..usize::from(self.len)]
37    }
38}
39
40impl std::fmt::Debug for InlineHeaderValue {
41    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42        f.debug_struct("InlineHeaderValue")
43            .field("len", &self.len)
44            .finish()
45    }
46}
47
48impl<'req> std::fmt::Debug for HeaderValueInner<'req> {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        match self {
51            Self::Static(value) => f
52                .debug_struct("HeaderValue::Static")
53                .field("len", &value.len())
54                .finish(),
55            Self::Inline(value) => f
56                .debug_struct("HeaderValue::Inline")
57                .field("len", &value.as_bytes().len())
58                .finish(),
59            Self::Shared(value) => f
60                .debug_struct("HeaderValue::Shared")
61                .field("len", &value.len())
62                .finish(),
63            Self::Borrowed(value) => f
64                .debug_struct("HeaderValue::Borrowed")
65                .field("len", &value.len())
66                .finish(),
67            Self::Retained(value) => f
68                .debug_struct("HeaderValue::Retained")
69                .field("len", &value.len())
70                .finish(),
71        }
72    }
73}
74
75impl<'req> HeaderValueInner<'req> {
76    pub fn as_bytes(&self) -> &[u8] {
77        match self {
78            Self::Static(value) => value,
79            Self::Inline(value) => value.as_bytes(),
80            Self::Shared(value) => value.as_ref(),
81            Self::Borrowed(value) => value.as_slice(),
82            Self::Retained(value) => value.as_slice(),
83        }
84    }
85
86    pub fn len(&self) -> usize {
87        self.as_bytes().len()
88    }
89
90    pub fn is_empty(&self) -> bool {
91        self.as_bytes().is_empty()
92    }
93}
94
95#[derive(Clone, Debug)]
96pub struct HeaderItem<'req> {
97    pub(super) name: HeaderNameToken,
98    pub(super) value: HeaderValueInner<'req>,
99}
100
101impl<'req> HeaderItem<'req> {
102    pub fn from_value<V>(name: HeaderNameToken, value: V) -> Self
103    where
104        V: Into<HeaderValueInner<'req>>,
105    {
106        Self {
107            name,
108            value: value.into(),
109        }
110    }
111
112    pub(crate) fn placeholder() -> Self {
113        Self {
114            name: HeaderNameToken::empty_placeholder(),
115            value: HeaderValueInner::Static(&[]),
116        }
117    }
118
119    pub fn wire_len(&self) -> usize {
120        self.name.as_bytes().len() + 2 + self.value.len() + 2
121    }
122
123    pub fn name_bytes(&self) -> &'static [u8] {
124        self.name.as_bytes()
125    }
126
127    pub fn value_bytes(&self) -> &[u8] {
128        self.value.as_bytes()
129    }
130}
131
132impl<'req> From<InlineHeaderValue> for HeaderValueInner<'req> {
133    fn from(value: InlineHeaderValue) -> Self {
134        Self::Inline(value)
135    }
136}
137
138impl<'req> From<Bytes<Borrowed<'req>>> for HeaderValueInner<'req> {
139    fn from(value: Bytes<Borrowed<'req>>) -> Self {
140        Self::Borrowed(value)
141    }
142}
143
144impl<'req> From<Bytes<Retained>> for HeaderValueInner<'req> {
145    fn from(value: Bytes<Retained>) -> Self {
146        Self::Retained(value)
147    }
148}
149
150impl<'req> From<Shared> for HeaderValueInner<'req> {
151    fn from(value: Shared) -> Self {
152        Self::Shared(value)
153    }
154}
155
156impl<'req> From<Owned> for HeaderValueInner<'req> {
157    fn from(value: Owned) -> Self {
158        Self::Shared(value.freeze())
159    }
160}
161
162impl<'req> From<String> for HeaderValueInner<'req> {
163    fn from(value: String) -> Self {
164        Self::Shared(Shared::from(value.into_bytes()))
165    }
166}
167
168impl<'req> From<&'static str> for HeaderValueInner<'req> {
169    fn from(value: &'static str) -> Self {
170        Self::Static(value.as_bytes())
171    }
172}