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 }