Skip to main content

trillium_http/headers/
entry.rs

1use super::{HeaderName, HeaderValues, KnownHeaderName, UnknownHeaderName};
2use hashbrown::hash_map;
3use std::fmt::{self, Debug, Formatter};
4
5/// A view into the storage for a particular header name
6#[derive(Debug)]
7pub enum Entry<'a> {
8    /// A mutable view into the slot where header values would be inserted for the
9    /// specified `HeaderName`.
10    Vacant(VacantEntry<'a>),
11    /// A mutable view into the header values stored for the specified `HeaderName`.
12    Occupied(OccupiedEntry<'a>),
13}
14
15/// A view into a vacant entry in particular `Headers` for a given `HeaderName`.
16///
17/// It is part of the [`Entry`] enum.
18pub struct VacantEntry<'a>(pub(super) VacantEntryInner<'a>);
19
20impl Debug for VacantEntry<'_> {
21    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
22        f.debug_struct("VacantEntry")
23            .field("name", &self.name())
24            .finish()
25    }
26}
27
28pub(super) enum VacantEntryInner<'a> {
29    Known(hash_map::VacantEntry<'a, KnownHeaderName, HeaderValues>),
30    Unknown(hash_map::VacantEntry<'a, UnknownHeaderName<'static>, HeaderValues>),
31}
32
33/// A view into an occupied entry in particular `Headers` for a given `HeaderName`.
34///
35/// It is part of the [`Entry`] enum.
36pub struct OccupiedEntry<'a>(pub(super) OccupiedEntryInner<'a>);
37
38impl Debug for OccupiedEntry<'_> {
39    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
40        f.debug_struct("OccupiedEntry")
41            .field("name", &self.name())
42            .field("values", &self.values())
43            .finish()
44    }
45}
46
47pub(super) enum OccupiedEntryInner<'a> {
48    Known(hash_map::OccupiedEntry<'a, KnownHeaderName, HeaderValues>),
49    Unknown(hash_map::OccupiedEntry<'a, UnknownHeaderName<'static>, HeaderValues>),
50}
51
52impl<'a> Entry<'a> {
53    /// retrieve the `HeaderName` for this entry.
54    pub fn name(&self) -> HeaderName<'_> {
55        match self {
56            Entry::Vacant(v) => v.name(),
57            Entry::Occupied(o) => o.name(),
58        }
59    }
60
61    /// Sets the value of the entry, and returns a mutable reference to the inserted value.
62    ///
63    /// Note that this drops any previous occupied value.
64    pub fn insert(self, values: impl Into<HeaderValues>) -> &'a mut HeaderValues {
65        match self {
66            Entry::Vacant(v) => v.insert(values),
67            Entry::Occupied(mut o) => {
68                o.insert(values);
69                o.into_mut()
70            }
71        }
72    }
73
74    /// Sets the value of the entry if it is vacant, and appends the new header values to the
75    /// previous ones if occupied. Returns a mutable reference to the inserted or updated value.
76    pub fn append(self, values: impl Into<HeaderValues>) -> &'a mut HeaderValues {
77        match self {
78            Entry::Vacant(v) => v.insert(values),
79            Entry::Occupied(mut o) => {
80                o.values_mut().extend(values);
81                o.into_mut()
82            }
83        }
84    }
85
86    /// Sets the value if previously vacant. The provided function is only executed if the entry is
87    /// vacant.
88    pub fn or_insert_with<V: Into<HeaderValues>>(
89        self,
90        values: impl FnOnce() -> V,
91    ) -> &'a mut HeaderValues {
92        match self {
93            Self::Occupied(entry) => entry.into_mut(),
94            Self::Vacant(entry) => entry.insert(values()),
95        }
96    }
97
98    /// Sets the value if previously vacant. See also [`Entry::or_insert_with`] if constructing the
99    /// default value is expensive.
100    pub fn or_insert(self, values: impl Into<HeaderValues>) -> &'a mut HeaderValues {
101        match self {
102            Entry::Vacant(vacant) => vacant.insert(values),
103            Entry::Occupied(occupied) => occupied.into_mut(),
104        }
105    }
106
107    /// Provides in-place mutable access to an occupied entry before any
108    /// potential inserts with [`Entry::or_insert`] or [`Entry::or_insert_with`].
109    #[must_use]
110    pub fn and_modify(self, f: impl FnOnce(&mut HeaderValues)) -> Self {
111        match self {
112            Self::Occupied(mut entry) => {
113                f(entry.values_mut());
114                Self::Occupied(entry)
115            }
116            Self::Vacant(entry) => Self::Vacant(entry),
117        }
118    }
119
120    /// Predicate to determine if this is a `VacantEntry`
121    pub fn is_vacant(&self) -> bool {
122        matches!(self, Self::Vacant(_))
123    }
124
125    /// Predicate to determine if this is an `OccupiedEntry`
126    pub fn is_occupied(&self) -> bool {
127        matches!(self, Self::Occupied(_))
128    }
129
130    /// Return the `OccupiedEntry`, if this entry is occupied
131    pub fn occupied(self) -> Option<OccupiedEntry<'a>> {
132        match self {
133            Entry::Vacant(_) => None,
134            Entry::Occupied(o) => Some(o),
135        }
136    }
137
138    /// Return the `VacantEntry`, if this entry is vacant
139    pub fn vacant(self) -> Option<VacantEntry<'a>> {
140        match self {
141            Entry::Vacant(v) => Some(v),
142            Entry::Occupied(_) => None,
143        }
144    }
145}
146
147impl<'a> VacantEntry<'a> {
148    /// Retrieves the `HeaderName` for this `Entry`.
149    pub fn name(&self) -> HeaderName<'_> {
150        match &self.0 {
151            VacantEntryInner::Known(k) => (*k.key()).into(),
152            VacantEntryInner::Unknown(u) => u.key().reborrow().into(),
153        }
154    }
155
156    /// Replace this `VacantEntry` with a value, returning a mutable reference to that value.
157    pub fn insert(self, values: impl Into<HeaderValues>) -> &'a mut HeaderValues {
158        match self.0 {
159            VacantEntryInner::Known(k) => k.insert(values.into()),
160            VacantEntryInner::Unknown(u) => u.insert(values.into()),
161        }
162    }
163}
164
165impl<'a> OccupiedEntry<'a> {
166    /// Retrieves the `HeaderName` for this `Entry`
167    pub fn name(&self) -> HeaderName<'_> {
168        match &self.0 {
169            OccupiedEntryInner::Known(known) => (*known.key()).into(),
170            OccupiedEntryInner::Unknown(unknown) => unknown.key().reborrow().into(),
171        }
172    }
173
174    /// Borrows the `HeaderValues` for this `Entry`
175    pub fn values(&self) -> &HeaderValues {
176        match &self.0 {
177            OccupiedEntryInner::Known(known) => known.get(),
178            OccupiedEntryInner::Unknown(unknown) => unknown.get(),
179        }
180    }
181
182    /// Mutate the `HeaderValues` for this `Entry`
183    pub fn values_mut(&mut self) -> &mut HeaderValues {
184        match &mut self.0 {
185            OccupiedEntryInner::Known(known) => known.get_mut(),
186            OccupiedEntryInner::Unknown(unknown) => unknown.get_mut(),
187        }
188    }
189
190    /// Take ownership of the `HeaderName` and `HeaderValues` represented by this entry, removing it
191    /// from the `Headers`
192    pub fn remove_entry(self) -> (HeaderName<'static>, HeaderValues) {
193        match self.0 {
194            OccupiedEntryInner::Known(known) => {
195                let (n, v) = known.remove_entry();
196                (n.into(), v)
197            }
198            OccupiedEntryInner::Unknown(unknown) => {
199                let (n, v) = unknown.remove_entry();
200                (n.into(), v)
201            }
202        }
203    }
204
205    /// Take ownership of the `HeaderValues` contained in this entry, removing it from the `Headers`
206    pub fn remove(self) -> HeaderValues {
207        match self.0 {
208            OccupiedEntryInner::Known(known) => known.remove(),
209            OccupiedEntryInner::Unknown(unknown) => unknown.remove(),
210        }
211    }
212
213    /// Converts this `OccupiedEntry` into a mutable reference to the value in the entry with a
214    /// lifetime bound to the Headers itself.
215    ///
216    /// If you need multiple references to the `OccupiedEntry`, see [`OccupiedEntry::values_mut`]
217    pub fn into_mut(self) -> &'a mut HeaderValues {
218        match self.0 {
219            OccupiedEntryInner::Known(k) => k.into_mut(),
220            OccupiedEntryInner::Unknown(u) => u.into_mut(),
221        }
222    }
223
224    /// Sets the value of the entry, and returns the entry's old value.
225    pub fn insert(&mut self, values: impl Into<HeaderValues>) -> HeaderValues {
226        match &mut self.0 {
227            OccupiedEntryInner::Known(k) => k.insert(values.into()),
228            OccupiedEntryInner::Unknown(u) => u.insert(values.into()),
229        }
230    }
231
232    /// Adds additional `HeaderValues` to the existing `HeaderValues` in this entry.
233    pub fn append(&mut self, values: impl Into<HeaderValues>) {
234        self.values_mut().extend(values);
235    }
236}