pub(crate) mod weak_vec { #![allow(dead_code)] //! Module containing the [`WeakVec`] API. use std::{sync::Weak, vec::Vec}; /// An optimized container for `Weak` references of `T` that minimizes reallocations by /// dropping older elements that no longer have strong references to them. #[derive(Debug)] pub(crate) struct WeakVec { inner: Vec>, } impl Default for WeakVec { fn default() -> Self { Self { inner: Default::default(), } } } impl WeakVec { pub(crate) fn new() -> Self { Self { inner: Vec::new() } } /// Pushes a new element to this collection. /// /// If the inner Vec needs to be reallocated, we will first drop older elements that /// no longer have strong references to them. pub(crate) fn push(&mut self, value: Weak) { if self.inner.len() == self.inner.capacity() { // Iterating backwards has the advantage that we don't do more work than we have to. for i in (0..self.inner.len()).rev() { if self.inner[i].strong_count() == 0 { self.inner.swap_remove(i); } } // Make sure our capacity is twice the number of live elements. // Leaving some spare capacity ensures that we won't re-scan immediately. self.inner.reserve_exact(self.inner.len()); } self.inner.push(value); } } pub(crate) struct WeakVecIter { inner: std::vec::IntoIter>, } impl Iterator for WeakVecIter { type Item = Weak; fn next(&mut self) -> Option { self.inner.next() } } impl IntoIterator for WeakVec { type Item = Weak; type IntoIter = WeakVecIter; fn into_iter(self) -> Self::IntoIter { WeakVecIter { inner: self.inner.into_iter(), } } } } pub(crate) use weak_vec::WeakVec; pub fn eq_f32(lhs: f32, rhs: f32) -> bool { use core::num::FpCategory::*; match (lhs.classify(), rhs.classify()) { (Zero, Zero) | (Nan, Nan) => true, (Infinite, Infinite) => lhs.signum() == rhs.signum(), _ => lhs == rhs, } } pub fn ord_f32(lhs: f32, rhs: f32) -> core::cmp::Ordering { use core::cmp::Ordering; use core::num::FpCategory::*; match (lhs.classify(), rhs.classify()) { (Zero, Zero) | (Nan, Nan) => Ordering::Equal, (Infinite, Infinite) => { core::cmp::PartialOrd::partial_cmp(&lhs.signum(), &rhs.signum()).unwrap() } _ => core::cmp::PartialOrd::partial_cmp(&lhs, &rhs).unwrap(), } } pub fn hash_f32(state: &mut H, f: f32) { use std::hash::Hash; let classify = f.classify(); match classify { std::num::FpCategory::Nan => (classify as u8).hash(state), std::num::FpCategory::Infinite | std::num::FpCategory::Zero => { (classify as u8, f.signum() as i8).hash(state) } std::num::FpCategory::Subnormal | std::num::FpCategory::Normal => f.to_bits().hash(state), } } #[repr(transparent)] #[derive(Debug, Clone, Copy)] pub struct F32(f32); impl F32 { #[inline] pub fn from_bits(bits: u32) -> Self { Self(f32::from_bits(bits)) } #[inline] pub fn into_bits(self) -> u32 { self.0.to_bits() } } impl From for F32 { fn from(value: f32) -> Self { Self(value) } } impl From for f32 { fn from(value: F32) -> Self { value.0 } } impl std::ops::Deref for F32 { type Target = f32; fn deref(&self) -> &Self::Target { &self.0 } } impl std::ops::DerefMut for F32 { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl PartialEq for F32 { fn eq(&self, other: &Self) -> bool { eq_f32(self.0, other.0) } } impl Eq for F32 {} impl PartialOrd for F32 { fn partial_cmp(&self, other: &Self) -> Option { Some(ord_f32(self.0, other.0)) } } impl Ord for F32 { fn cmp(&self, other: &Self) -> std::cmp::Ordering { ord_f32(self.0, other.0) } } impl core::hash::Hash for F32 { fn hash(&self, state: &mut H) { hash_f32(state, self.0) } }