use std::fmt::{self, Debug}; use std::slice; pub(crate) use self::ordered::OrderedSet; pub(crate) use self::unordered::UnorderedSet; mod ordered { use super::{Iter, UnorderedSet}; use std::hash::Hash; pub(crate) struct OrderedSet { set: UnorderedSet, vec: Vec, } impl<'a, T> OrderedSet<&'a T> where T: Hash + Eq, { pub(crate) fn new() -> Self { OrderedSet { set: UnorderedSet::new(), vec: Vec::new(), } } pub(crate) fn insert(&mut self, value: &'a T) -> bool { let new = self.set.insert(value); if new { self.vec.push(value); } new } } impl<'a, T> OrderedSet<&'a T> { pub(crate) fn is_empty(&self) -> bool { self.vec.is_empty() } pub(crate) fn iter(&self) -> Iter<'_, 'a, T> { Iter(self.vec.iter()) } } impl<'s, 'a, T> IntoIterator for &'s OrderedSet<&'a T> { type Item = &'a T; type IntoIter = Iter<'s, 'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter() } } } mod unordered { use std::borrow::Borrow; use std::collections::HashSet; use std::hash::Hash; // Wrapper prohibits accidentally introducing iteration over the set, which // could lead to nondeterministic generated code. pub(crate) struct UnorderedSet(HashSet); impl UnorderedSet where T: Hash + Eq, { pub(crate) fn new() -> Self { UnorderedSet(HashSet::new()) } pub(crate) fn insert(&mut self, value: T) -> bool { self.0.insert(value) } pub(crate) fn contains(&self, value: &Q) -> bool where T: Borrow, Q: ?Sized + Hash + Eq, { self.0.contains(value) } #[allow(dead_code)] // only used by cxx-build, not cxxbridge-cmd pub(crate) fn get(&self, value: &Q) -> Option<&T> where T: Borrow, Q: ?Sized + Hash + Eq, { self.0.get(value) } pub(crate) fn retain(&mut self, f: impl FnMut(&T) -> bool) { self.0.retain(f); } } } pub(crate) struct Iter<'s, 'a, T>(slice::Iter<'s, &'a T>); impl<'s, 'a, T> Iterator for Iter<'s, 'a, T> { type Item = &'a T; fn next(&mut self) -> Option { self.0.next().copied() } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } impl<'a, T> Debug for OrderedSet<&'a T> where T: Debug, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.debug_set().entries(self).finish() } }