webauthn_rp

WebAuthn RP library.
git clone https://git.philomathiclife.com/repos/webauthn_rp
Log | Files | Refs | README

hash_map.rs (27745B)


      1 #[cfg(test)]
      2 mod tests;
      3 use super::{super::request::TimedCeremony, BuildIdentityHasher};
      4 #[cfg(doc)]
      5 use core::hash::Hasher;
      6 use core::hash::{BuildHasher, Hash};
      7 use hashbrown::{
      8     Equivalent, TryReserveError,
      9     hash_map::{Drain, Entry, EntryRef, ExtractIf, HashMap, IterMut, OccupiedError, ValuesMut},
     10 };
     11 #[cfg(any(doc, not(feature = "serializable_server_state")))]
     12 use std::time::Instant;
     13 #[cfg(feature = "serializable_server_state")]
     14 use std::time::SystemTime;
     15 /// [`HashMap`] that has maximum [`HashMap::capacity`] and length and allocates exactly once.
     16 ///
     17 /// Note due to how `HashMap` removes entries, it's possible to insert an entry after removing an entry and cause
     18 /// a new allocation. To avoid this, we ensure that the allocated capacity is at least twice the size of
     19 /// the requested maximum length.
     20 ///
     21 /// This is useful in situations when the underlying entries are expected to be removed, and one wants to ensure the
     22 /// map does not grow unbounded. When `K` is a [`TimedCeremony`], helper methods (e.g.,
     23 /// [`Self::insert_remove_all_expired`]) are provided that will automatically remove expired entries. Note the
     24 /// intended use case is for `K` to be based on a server-side randomly generated value; thus the default [`Hasher`]
     25 /// is [`BuildIdentityHasher`]. In the event this is not true, one MUST use a more appropriate `Hasher`.
     26 ///
     27 /// Only the mutable methods of `HashMap` are re-defined in order to ensure [`Self::max_len`] is never exceeded.
     28 /// For all other methods, first call [`Self::as_ref`] or [`Self::into`].
     29 ///
     30 /// [`Self::into`]: struct.MaxLenHashMap.html#impl-Into<U>-for-T
     31 #[derive(Debug)]
     32 pub struct MaxLenHashMap<K, V, S = BuildIdentityHasher>(HashMap<K, V, S>, usize);
     33 impl<K, V> MaxLenHashMap<K, V, BuildIdentityHasher> {
     34     /// [`HashMap::with_capacity_and_hasher`] using `2 * max_len` and `BuildIdentityHasher`.
     35     ///
     36     /// Note since the actual capacity allocated may exceed the requested capacity, [`Self::max_len`] may exceed
     37     /// `max_len`.
     38     ///
     39     /// # Panics
     40     ///
     41     /// `panic`s if `max_len > usize::MAX / 2`. Note since [`HashMap::with_capacity_and_hasher`] `panic`s
     42     /// for much smaller values than `usize::MAX / 2`—even when `K` and `V` are zero-sized types (ZSTs)—this is not
     43     /// an additional `panic` than what would already occur. The only difference is the message reported.
     44     #[inline]
     45     #[must_use]
     46     pub fn new(max_len: usize) -> Self {
     47         Self::with_hasher(max_len, BuildIdentityHasher)
     48     }
     49 }
     50 impl<K, V, S> MaxLenHashMap<K, V, S> {
     51     /// Capacity we allocate.
     52     ///
     53     /// # Errors
     54     ///
     55     /// Errors iff `max_len > usize::MAX / 2`.
     56     const fn requested_capacity(max_len: usize) -> Result<usize, TryReserveError> {
     57         if max_len <= usize::MAX >> 1u8 {
     58             Ok(max_len << 1u8)
     59         } else {
     60             Err(TryReserveError::CapacityOverflow)
     61         }
     62     }
     63     /// Returns the immutable maximum length allowed by `self`.
     64     #[inline]
     65     pub const fn max_len(&self) -> usize {
     66         self.1
     67     }
     68     /// [`HashMap::values_mut`].
     69     #[inline]
     70     pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
     71         self.0.values_mut()
     72     }
     73     /// [`HashMap::iter_mut`].
     74     #[expect(
     75         clippy::iter_without_into_iter,
     76         reason = "re-export all mutable methods of HashMap"
     77     )]
     78     #[inline]
     79     pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
     80         self.0.iter_mut()
     81     }
     82     /// [`HashMap::clear`].
     83     #[inline]
     84     pub fn clear(&mut self) {
     85         self.0.clear();
     86     }
     87     /// [`HashMap::drain`].
     88     #[inline]
     89     pub fn drain(&mut self) -> Drain<'_, K, V> {
     90         self.0.drain()
     91     }
     92     /// [`HashMap::extract_if`].
     93     #[inline]
     94     pub fn extract_if<F: FnMut(&K, &mut V) -> bool>(&mut self, f: F) -> ExtractIf<'_, K, V, F> {
     95         self.0.extract_if(f)
     96     }
     97     /// [`HashMap::with_capacity_and_hasher`] using `2 * max_len` and `hasher`.
     98     ///
     99     /// Note since the actual capacity allocated may exceed the requested capacity, [`Self::max_len`] may exceed
    100     /// `max_len`.
    101     ///
    102     /// # Panics
    103     ///
    104     /// `panic`s if `max_len > usize::MAX / 2`. Note since [`HashMap::with_capacity_and_hasher`] `panic`s
    105     /// for much smaller values than `usize::MAX / 2`—even when `K` and `V` are zero-sized types (ZSTs)—this is not
    106     /// an additional `panic` than what would already occur. The only difference is the message reported.
    107     #[expect(
    108         clippy::expect_used,
    109         reason = "purpose of this function is to panic if the hash map cannot be allocated"
    110     )]
    111     #[inline]
    112     #[must_use]
    113     pub fn with_hasher(max_len: usize, hasher: S) -> Self {
    114         let map = HashMap::with_capacity_and_hasher(Self::requested_capacity(max_len).expect("HashMap::with_hasher must be passed a maximum length that does not exceed usize::MAX / 2"), hasher);
    115         let len = map.capacity() >> 1u8;
    116         Self(map, len)
    117     }
    118     /// [`HashMap::retain`].
    119     #[inline]
    120     pub fn retain<F: FnMut(&K, &mut V) -> bool>(&mut self, f: F) {
    121         self.0.retain(f);
    122     }
    123 }
    124 impl<K: TimedCeremony, V, S> MaxLenHashMap<K, V, S> {
    125     /// Removes all expired ceremonies.
    126     ///
    127     /// `None` is returned iff at least one expired ceremony was removed; otherwise returns the earliest
    128     /// expiration.
    129     ///
    130     /// Note when `serializable_server_state` is enabled, [`SystemTime`] is returned instead.
    131     #[cfg_attr(docsrs, doc(auto_cfg = false))]
    132     #[cfg(any(doc, not(feature = "serializable_server_state")))]
    133     #[inline]
    134     pub fn remove_expired_ceremonies(&mut self) -> Option<Instant> {
    135         // Even though it's more accurate to check the current `Instant` for each ceremony, we elect to capture
    136         // the `Instant` we begin iteration for performance reasons. It's unlikely an appreciable amount of
    137         // additional ceremonies would be removed.
    138         let now = Instant::now();
    139         let mut some = true;
    140         let mut expiry_min = None;
    141         self.retain(|k, _| {
    142             let expiry = k.expiration();
    143             if expiry >= now {
    144                 match expiry_min {
    145                     None => expiry_min = Some(expiry),
    146                     Some(ref mut e) if expiry < *e => *e = expiry,
    147                     _ => {}
    148                 }
    149                 true
    150             } else {
    151                 some = false;
    152                 false
    153             }
    154         });
    155         if some { expiry_min } else { None }
    156     }
    157     /// Removes all expired ceremonies.
    158     ///
    159     /// `None` is returned iff at least one expired ceremony was removed; otherwise returns the earliest
    160     /// expiration.
    161     ///
    162     /// Note when `serializable_server_state` is enabled, [`SystemTime`] is returned instead.
    163     #[cfg(all(not(doc), feature = "serializable_server_state"))]
    164     #[inline]
    165     pub fn remove_expired_ceremonies(&mut self) -> Option<SystemTime> {
    166         // Even though it's more accurate to check the current `SystemTime` for each ceremony, we elect to capture
    167         // the `SystemTime` we begin iteration for performance reasons. It's unlikely an appreciable amount of
    168         // additional ceremonies would be removed.
    169         let now = SystemTime::now();
    170         let mut some = true;
    171         let mut expiry_min = None;
    172         self.retain(|k, _| {
    173             let expiry = k.expiration();
    174             if expiry >= now {
    175                 match expiry_min {
    176                     None => expiry_min = Some(expiry),
    177                     Some(ref mut e) if expiry < *e => *e = expiry,
    178                     _ => {}
    179                 }
    180                 true
    181             } else {
    182                 some = false;
    183                 false
    184             }
    185         });
    186         if some { expiry_min } else { None }
    187     }
    188     /// Removes the first encountered expired ceremony.
    189     ///
    190     /// `None` is returned iff an expired ceremony was removed; otherwise returns the earliest
    191     /// expiration.
    192     ///
    193     /// Note when `serializable_server_state` is enabled, [`SystemTime`] is returned instead.
    194     #[cfg_attr(docsrs, doc(auto_cfg = false))]
    195     #[cfg(any(doc, not(feature = "serializable_server_state")))]
    196     #[inline]
    197     pub fn remove_first_expired_ceremony(&mut self) -> Option<Instant> {
    198         // Even though it's more accurate to check the current `Instant` for each ceremony, we elect to capture
    199         // the `Instant` we begin iteration for performance reasons. It's unlikely an appreciable amount of
    200         // additional ceremonies would be removed.
    201         let now = Instant::now();
    202         let mut expiry_min = None;
    203         self.0
    204             .extract_if(|k, _| {
    205                 let expiry = k.expiration();
    206                 if expiry < now {
    207                     true
    208                 } else {
    209                     match expiry_min {
    210                         None => expiry_min = Some(expiry),
    211                         Some(ref mut e) if expiry < *e => *e = expiry,
    212                         _ => {}
    213                     }
    214                     false
    215                 }
    216             })
    217             .next()
    218             .map_or(expiry_min, |_| None)
    219     }
    220     /// Removes the first encountered expired ceremony.
    221     ///
    222     /// `None` is returned iff an expired ceremony was removed; otherwise returns the earliest
    223     /// expiration.
    224     ///
    225     /// Note when `serializable_server_state` is enabled, [`SystemTime`] is returned instead.
    226     #[cfg(all(not(doc), feature = "serializable_server_state"))]
    227     #[inline]
    228     pub fn remove_first_expired_ceremony(&mut self) -> Option<SystemTime> {
    229         // Even though it's more accurate to check the current `SystemTime` for each ceremony, we elect to capture
    230         // the `SystemTime` we begin iteration for performance reasons. It's unlikely an appreciable amount of
    231         // additional ceremonies would be removed.
    232         let now = SystemTime::now();
    233         let mut expiry_min = None;
    234         self.0
    235             .extract_if(|k, _| {
    236                 let expiry = k.expiration();
    237                 if expiry < now {
    238                     true
    239                 } else {
    240                     match expiry_min {
    241                         None => expiry_min = Some(expiry),
    242                         Some(ref mut e) if expiry < *e => *e = expiry,
    243                         _ => {}
    244                     }
    245                     false
    246                 }
    247             })
    248             .next()
    249             .map_or(expiry_min, |_| None)
    250     }
    251 }
    252 /// Signifies the consequences of [`MaxLenHashMap::insert`].
    253 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    254 pub enum Insert<V> {
    255     /// The entry was successfully inserted.
    256     Success,
    257     /// The value replaced the contained value.
    258     Previous(V),
    259     /// The key does not exist, but there was no available capacity to insert the entry.
    260     CapacityFull,
    261 }
    262 /// Error returned from [`MaxLenHashMap::try_insert`].
    263 #[derive(Debug)]
    264 pub enum FullCapOccupiedErr<'a, K, V, S> {
    265     /// Error when the key already exists.
    266     Occupied(OccupiedError<'a, K, V, S>),
    267     /// Error when there is no available capacity and the key does not exist.
    268     CapacityFull,
    269 }
    270 /// Error returned from [`MaxLenHashMap::try_insert_remove_expired`] and
    271 /// [`MaxLenHashMap::try_insert_remove_all_expired`].
    272 #[derive(Debug)]
    273 pub enum FullCapRemoveExpiredOccupiedErr<'a, K, V, S> {
    274     /// Error when the key already exists.
    275     Occupied(OccupiedError<'a, K, V, S>),
    276     /// Error when there was is no available capacity to insert the entry and no expired
    277     /// [`TimedCeremony`]s could be removed.
    278     ///
    279     /// The contained `Instant` is the earliest expiration.
    280     ///
    281     /// Note when `serializable_server_state` is enabled, [`SystemTime`] is contained instead.
    282     #[cfg_attr(docsrs, doc(auto_cfg = false))]
    283     #[cfg(any(doc, not(feature = "serializable_server_state")))]
    284     CapacityFull(Instant),
    285     /// Error when there was is no available capacity to insert the entry and no expired
    286     /// [`TimedCeremony`]s could be removed.
    287     ///
    288     /// The contained `Instant` is the earliest expiration.
    289     ///
    290     /// Note when `serializable_server_state` is enabled, [`SystemTime`] is contained instead.
    291     #[cfg(all(not(doc), feature = "serializable_server_state"))]
    292     CapacityFull(SystemTime),
    293 }
    294 /// Signifies the consequences of [`MaxLenHashMap::insert_remove_expired`] and
    295 /// [`MaxLenHashMap::insert_remove_all_expired`].
    296 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    297 pub enum InsertRemoveExpired<V> {
    298     /// The entry was successfully inserted.
    299     Success,
    300     /// The value replaced the contained value.
    301     Previous(V),
    302     /// The key does not exist, but there was no available capacity to insert the entry and no expired
    303     /// [`TimedCeremony`]s could be removed.
    304     ///
    305     /// The contained `Instant` is the earliest expiration.
    306     ///
    307     /// Note when `serializable_server_state` is enabled, [`SystemTime`] is contained instead.
    308     #[cfg_attr(docsrs, doc(auto_cfg = false))]
    309     #[cfg(any(doc, not(feature = "serializable_server_state")))]
    310     CapacityFull(Instant),
    311     /// The value does not exist, but there was no available capacity to insert it and no expired
    312     /// [`TimedCeremony`]s that could be removed.
    313     ///
    314     /// The contained `Instant` is the earliest expiration.
    315     ///
    316     /// Note when `serializable_server_state` is enabled, [`SystemTime`] is contained instead.
    317     #[cfg(all(not(doc), feature = "serializable_server_state"))]
    318     CapacityFull(SystemTime),
    319 }
    320 /// Signifies the consequences of [`MaxLenHashMap::entry`] and [`MaxLenHashMap::entry_ref`].
    321 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    322 pub enum EntryStatus<E> {
    323     /// The entry was successfully grabbed.
    324     Success(E),
    325     /// The capacity was full, and there was no value where the entry would be.
    326     CapacityFull,
    327 }
    328 /// Signifies the consequences of [`MaxLenHashMap::entry_remove_expired`] and
    329 /// [`MaxLenHashMap::entry_remove_all_expired`].
    330 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    331 pub enum EntryStatusRemoveExpired<E> {
    332     /// The entry was successfully grabbed.
    333     Success(E),
    334     /// The capacity was full, and there was no value where the entry would be.
    335     ///
    336     /// The contained `Instant` is the earliest expiration.
    337     ///
    338     /// Note when `serializable_server_state` is enabled, [`SystemTime`] is contained instead.
    339     #[cfg_attr(docsrs, doc(auto_cfg = false))]
    340     #[cfg(any(doc, not(feature = "serializable_server_state")))]
    341     CapacityFull(Instant),
    342     /// The capacity was full, and there was no value where the entry would be.
    343     ///
    344     /// The contained `Instant` is the earliest expiration.
    345     ///
    346     /// Note when `serializable_server_state` is enabled, [`SystemTime`] is contained instead.
    347     #[cfg(all(not(doc), feature = "serializable_server_state"))]
    348     CapacityFull(SystemTime),
    349 }
    350 impl<K: Eq + Hash, V, S: BuildHasher> MaxLenHashMap<K, V, S> {
    351     /// [`HashMap::with_hasher`] using `hasher` followed by [`HashMap::try_reserve`] using `2 * max_len`.
    352     ///
    353     /// Note since the actual capacity allocated may exceed the requested capacity, [`Self::max_len`] may exceed
    354     /// `max_len`.
    355     ///
    356     /// # Errors
    357     ///
    358     /// Errors iff `max_len > usize::MAX / 2` or [`HashMap::try_reserve`] does.
    359     #[inline]
    360     pub fn try_with_hasher(max_len: usize, hasher: S) -> Result<Self, TryReserveError> {
    361         Self::requested_capacity(max_len).and_then(|additional| {
    362             let mut set = HashMap::with_hasher(hasher);
    363             set.try_reserve(additional).map(|()| {
    364                 let len = set.capacity() >> 1u8;
    365                 Self(set, len)
    366             })
    367         })
    368     }
    369     /// [`HashMap::get_mut`].
    370     #[inline]
    371     pub fn get_mut<Q: Equivalent<K> + Hash + ?Sized>(&mut self, k: &Q) -> Option<&mut V> {
    372         self.0.get_mut(k)
    373     }
    374     /// [`HashMap::get_key_value_mut`].
    375     #[inline]
    376     pub fn get_key_value_mut<Q: Equivalent<K> + Hash + ?Sized>(
    377         &mut self,
    378         k: &Q,
    379     ) -> Option<(&K, &mut V)> {
    380         self.0.get_key_value_mut(k)
    381     }
    382     /// [`HashMap::get_disjoint_mut`].
    383     #[inline]
    384     pub fn get_disjoint_mut<Q: Equivalent<K> + Hash + ?Sized, const N: usize>(
    385         &mut self,
    386         ks: [&Q; N],
    387     ) -> [Option<&mut V>; N] {
    388         self.0.get_disjoint_mut(ks)
    389     }
    390     /// [`HashMap::get_disjoint_key_value_mut`].
    391     #[inline]
    392     pub fn get_disjoint_key_value_mut<Q: Equivalent<K> + Hash + ?Sized, const N: usize>(
    393         &mut self,
    394         ks: [&Q; N],
    395     ) -> [Option<(&K, &mut V)>; N] {
    396         self.0.get_disjoint_key_value_mut(ks)
    397     }
    398     /// [`HashMap::remove`].
    399     #[inline]
    400     pub fn remove<Q: Equivalent<K> + Hash + ?Sized>(&mut self, k: &Q) -> Option<V> {
    401         self.0.remove(k)
    402     }
    403     /// [`HashMap::remove_entry`].
    404     #[inline]
    405     pub fn remove_entry<Q: Equivalent<K> + Hash + ?Sized>(&mut self, k: &Q) -> Option<(K, V)> {
    406         self.0.remove_entry(k)
    407     }
    408     /// [`HashMap::try_insert`].
    409     ///
    410     /// # Errors
    411     ///
    412     /// Errors iff [`HashMap::try_insert`] does or there is no available capacity to insert the entry.
    413     #[inline]
    414     pub fn try_insert(
    415         &mut self,
    416         key: K,
    417         value: V,
    418     ) -> Result<&mut V, FullCapOccupiedErr<'_, K, V, S>> {
    419         let full = self.0.len() == self.1;
    420         match self.0.entry(key) {
    421             Entry::Occupied(entry) => {
    422                 Err(FullCapOccupiedErr::Occupied(OccupiedError { entry, value }))
    423             }
    424             Entry::Vacant(ent) => {
    425                 if full {
    426                     Err(FullCapOccupiedErr::CapacityFull)
    427                 } else {
    428                     Ok(ent.insert(value))
    429                 }
    430             }
    431         }
    432     }
    433     /// [`HashMap::insert`].
    434     #[inline]
    435     pub fn insert(&mut self, k: K, v: V) -> Insert<V> {
    436         let full = self.0.len() == self.1;
    437         match self.0.entry(k) {
    438             Entry::Occupied(mut ent) => Insert::Previous(ent.insert(v)),
    439             Entry::Vacant(ent) => {
    440                 if full {
    441                     Insert::CapacityFull
    442                 } else {
    443                     _ = ent.insert(v);
    444                     Insert::Success
    445                 }
    446             }
    447         }
    448     }
    449     /// [`HashMap::entry`].
    450     #[inline]
    451     pub fn entry(&mut self, key: K) -> EntryStatus<Entry<'_, K, V, S>> {
    452         let full = self.0.len() == self.1;
    453         match self.0.entry(key) {
    454             ent @ Entry::Occupied(_) => EntryStatus::Success(ent),
    455             ent @ Entry::Vacant(_) => {
    456                 if full {
    457                     EntryStatus::CapacityFull
    458                 } else {
    459                     EntryStatus::Success(ent)
    460                 }
    461             }
    462         }
    463     }
    464     /// [`HashMap::entry_ref`].
    465     #[inline]
    466     pub fn entry_ref<'a, 'b, Q: Equivalent<K> + Hash + ?Sized>(
    467         &'a mut self,
    468         key: &'b Q,
    469     ) -> EntryStatus<EntryRef<'a, 'b, K, Q, V, S>> {
    470         let full = self.0.len() == self.1;
    471         match self.0.entry_ref(key) {
    472             ent @ EntryRef::Occupied(_) => EntryStatus::Success(ent),
    473             ent @ EntryRef::Vacant(_) => {
    474                 if full {
    475                     EntryStatus::CapacityFull
    476                 } else {
    477                     EntryStatus::Success(ent)
    478                 }
    479             }
    480         }
    481     }
    482 }
    483 impl<K: Eq + Hash + TimedCeremony, V, S: BuildHasher> MaxLenHashMap<K, V, S> {
    484     /// [`Self::try_insert`] except the first encountered expired ceremony is removed in the event [`Self::max_len`]
    485     /// entries have been added.
    486     ///
    487     /// # Errors
    488     ///
    489     /// Errors iff [`HashMap::try_insert`] does after removing the first expired ceremony.
    490     #[inline]
    491     pub fn try_insert_remove_expired(
    492         &mut self,
    493         key: K,
    494         value: V,
    495     ) -> Result<&mut V, FullCapRemoveExpiredOccupiedErr<'_, K, V, S>> {
    496         if self.0.len() == self.1 {
    497             match self.remove_first_expired_ceremony() {
    498                 None => self
    499                     .0
    500                     .try_insert(key, value)
    501                     .map_err(FullCapRemoveExpiredOccupiedErr::Occupied),
    502                 Some(exp) => {
    503                     if let Entry::Occupied(entry) = self.0.entry(key) {
    504                         Err(FullCapRemoveExpiredOccupiedErr::Occupied(OccupiedError {
    505                             entry,
    506                             value,
    507                         }))
    508                     } else {
    509                         Err(FullCapRemoveExpiredOccupiedErr::CapacityFull(exp))
    510                     }
    511                 }
    512             }
    513         } else {
    514             self.0
    515                 .try_insert(key, value)
    516                 .map_err(FullCapRemoveExpiredOccupiedErr::Occupied)
    517         }
    518     }
    519     /// [`Self::try_insert`] except all expired ceremonies are removed in the event [`Self::max_len`] entries have
    520     /// been added.
    521     ///
    522     /// # Errors
    523     ///
    524     /// Errors iff [`HashMap::try_insert`] does after removing all expired ceremonies.
    525     #[inline]
    526     pub fn try_insert_remove_all_expired(
    527         &mut self,
    528         key: K,
    529         value: V,
    530     ) -> Result<&mut V, FullCapRemoveExpiredOccupiedErr<'_, K, V, S>> {
    531         if self.0.len() == self.1 {
    532             match self.remove_expired_ceremonies() {
    533                 None => self
    534                     .0
    535                     .try_insert(key, value)
    536                     .map_err(FullCapRemoveExpiredOccupiedErr::Occupied),
    537                 Some(exp) => {
    538                     if let Entry::Occupied(entry) = self.0.entry(key) {
    539                         Err(FullCapRemoveExpiredOccupiedErr::Occupied(OccupiedError {
    540                             entry,
    541                             value,
    542                         }))
    543                     } else {
    544                         Err(FullCapRemoveExpiredOccupiedErr::CapacityFull(exp))
    545                     }
    546                 }
    547             }
    548         } else {
    549             self.0
    550                 .try_insert(key, value)
    551                 .map_err(FullCapRemoveExpiredOccupiedErr::Occupied)
    552         }
    553     }
    554     /// [`Self::insert`] except the first encountered expired ceremony is removed in the event [`Self::max_len`]
    555     /// entries have been added.
    556     #[inline]
    557     pub fn insert_remove_expired(&mut self, k: K, v: V) -> InsertRemoveExpired<V> {
    558         if self.0.len() == self.1 {
    559             match self.remove_first_expired_ceremony() {
    560                 None => self.0.insert(k, v).map_or_else(
    561                     || InsertRemoveExpired::Success,
    562                     InsertRemoveExpired::Previous,
    563                 ),
    564                 Some(exp) => {
    565                     if let Entry::Occupied(mut ent) = self.0.entry(k) {
    566                         InsertRemoveExpired::Previous(ent.insert(v))
    567                     } else {
    568                         InsertRemoveExpired::CapacityFull(exp)
    569                     }
    570                 }
    571             }
    572         } else {
    573             self.0.insert(k, v).map_or_else(
    574                 || InsertRemoveExpired::Success,
    575                 InsertRemoveExpired::Previous,
    576             )
    577         }
    578     }
    579     /// [`Self::insert`] except all expired ceremonies are removed in the event [`Self::max_len`] entries have
    580     /// been added.
    581     #[inline]
    582     pub fn insert_remove_all_expired(&mut self, k: K, v: V) -> InsertRemoveExpired<V> {
    583         if self.0.len() == self.1 {
    584             match self.remove_expired_ceremonies() {
    585                 None => self.0.insert(k, v).map_or_else(
    586                     || InsertRemoveExpired::Success,
    587                     InsertRemoveExpired::Previous,
    588                 ),
    589                 Some(exp) => {
    590                     if let Entry::Occupied(mut ent) = self.0.entry(k) {
    591                         InsertRemoveExpired::Previous(ent.insert(v))
    592                     } else {
    593                         InsertRemoveExpired::CapacityFull(exp)
    594                     }
    595                 }
    596             }
    597         } else {
    598             self.0.insert(k, v).map_or_else(
    599                 || InsertRemoveExpired::Success,
    600                 InsertRemoveExpired::Previous,
    601             )
    602         }
    603     }
    604     /// [`Self::entry`] except the first encountered expired ceremony is removed in the event [`Self::max_len`]
    605     /// entries have been added.
    606     #[inline]
    607     pub fn entry_remove_expired(&mut self, key: K) -> EntryStatusRemoveExpired<Entry<'_, K, V, S>> {
    608         if self.0.len() == self.1 {
    609             match self.remove_first_expired_ceremony() {
    610                 None => EntryStatusRemoveExpired::Success(self.0.entry(key)),
    611                 Some(exp) => {
    612                     if let ent @ Entry::Occupied(_) = self.0.entry(key) {
    613                         EntryStatusRemoveExpired::Success(ent)
    614                     } else {
    615                         EntryStatusRemoveExpired::CapacityFull(exp)
    616                     }
    617                 }
    618             }
    619         } else {
    620             EntryStatusRemoveExpired::Success(self.0.entry(key))
    621         }
    622     }
    623     /// [`Self::entry`] except all expired ceremonies are removed in the event [`Self::max_len`] entries have
    624     /// been added.
    625     #[inline]
    626     pub fn entry_remove_all_expired(
    627         &mut self,
    628         key: K,
    629     ) -> EntryStatusRemoveExpired<Entry<'_, K, V, S>> {
    630         if self.0.len() == self.1 {
    631             match self.remove_expired_ceremonies() {
    632                 None => EntryStatusRemoveExpired::Success(self.0.entry(key)),
    633                 Some(exp) => {
    634                     if let ent @ Entry::Occupied(_) = self.0.entry(key) {
    635                         EntryStatusRemoveExpired::Success(ent)
    636                     } else {
    637                         EntryStatusRemoveExpired::CapacityFull(exp)
    638                     }
    639                 }
    640             }
    641         } else {
    642             EntryStatusRemoveExpired::Success(self.0.entry(key))
    643         }
    644     }
    645     /// [`Self::entry_ref`] except the first encoutered expired ceremony is removed in the event [`Self::max_len`]
    646     /// entries have been added.
    647     #[inline]
    648     pub fn entry_ref_remove_expired<'a, 'b, Q: Equivalent<K> + Hash + ?Sized>(
    649         &'a mut self,
    650         key: &'b Q,
    651     ) -> EntryStatusRemoveExpired<EntryRef<'a, 'b, K, Q, V, S>> {
    652         if self.0.len() == self.1 {
    653             match self.remove_first_expired_ceremony() {
    654                 None => EntryStatusRemoveExpired::Success(self.0.entry_ref(key)),
    655                 Some(exp) => {
    656                     if let ent @ EntryRef::Occupied(_) = self.0.entry_ref(key) {
    657                         EntryStatusRemoveExpired::Success(ent)
    658                     } else {
    659                         EntryStatusRemoveExpired::CapacityFull(exp)
    660                     }
    661                 }
    662             }
    663         } else {
    664             EntryStatusRemoveExpired::Success(self.0.entry_ref(key))
    665         }
    666     }
    667     /// [`Self::entry_ref`] except all expired ceremonies are removed in the event [`Self::max_len`] entries have
    668     /// been added.
    669     #[inline]
    670     pub fn entry_ref_remove_all_expired<'a, 'b, Q: Equivalent<K> + Hash + ?Sized>(
    671         &'a mut self,
    672         key: &'b Q,
    673     ) -> EntryStatusRemoveExpired<EntryRef<'a, 'b, K, Q, V, S>> {
    674         if self.0.len() == self.1 {
    675             match self.remove_expired_ceremonies() {
    676                 None => EntryStatusRemoveExpired::Success(self.0.entry_ref(key)),
    677                 Some(exp) => {
    678                     if let ent @ EntryRef::Occupied(_) = self.0.entry_ref(key) {
    679                         EntryStatusRemoveExpired::Success(ent)
    680                     } else {
    681                         EntryStatusRemoveExpired::CapacityFull(exp)
    682                     }
    683                 }
    684             }
    685         } else {
    686             EntryStatusRemoveExpired::Success(self.0.entry_ref(key))
    687         }
    688     }
    689 }
    690 impl<K, V, S> AsRef<HashMap<K, V, S>> for MaxLenHashMap<K, V, S> {
    691     #[inline]
    692     fn as_ref(&self) -> &HashMap<K, V, S> {
    693         &self.0
    694     }
    695 }
    696 impl<K, V, S> From<MaxLenHashMap<K, V, S>> for HashMap<K, V, S> {
    697     #[inline]
    698     fn from(value: MaxLenHashMap<K, V, S>) -> Self {
    699         value.0
    700     }
    701 }