Skip to main content

trillium_http/headers/
entry.rs

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