#![doc(hidden)]
use rustc_hash::FxHashSet;
use std::hash::Hash;
use std::iter::FromIterator;
use std::ops::Deref;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NodeRefs<'a, N>(FxHashSet<&'a N>)
where
N: Eq + Hash + Clone;
impl<'a, N: Eq + Hash + Clone> FromIterator<&'a N> for NodeRefs<'a, N> {
fn from_iter<T: IntoIterator<Item = &'a N>>(iter: T) -> Self {
NodeRefs(FxHashSet::from_iter(iter))
}
}
impl<'a, N: Eq + Hash + Clone> From<&'a N> for NodeRefs<'a, N> {
fn from(value: &'a N) -> Self {
NodeRefs(FxHashSet::from_iter([value]))
}
}
impl<'a, N: Eq + Hash + Clone> IntoIterator for NodeRefs<'a, N> {
type Item = &'a N;
type IntoIter = std::collections::hash_set::IntoIter<&'a N>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<'a, N: Eq + Hash + Clone> IntoIterator for &'a NodeRefs<'a, N> {
type Item = &'a N;
type IntoIter = std::iter::Copied<std::collections::hash_set::Iter<'a, &'a N>>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter().copied()
}
}
impl<'a, N: Eq + Hash + Clone> Deref for NodeRefs<'a, N> {
type Target = FxHashSet<&'a N>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[cfg(test)]
mod tests {
use super::*;
use itertools::Itertools;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
struct Node(u8);
#[test]
fn test_from_iterator() {
let nodes = [Node(1), Node(2), Node(3)];
let refs = NodeRefs::from_iter(&nodes);
assert_eq!(
refs.0,
FxHashSet::from_iter([&nodes[0], &nodes[1], &nodes[2]])
);
}
#[test]
fn test_from_single_ref() {
let node = Node(42);
let refs = NodeRefs::from(&node);
assert_eq!(refs.0, FxHashSet::from_iter([&node]));
}
#[test]
fn test_into_iterator() {
let nodes = [Node(1), Node(2), Node(3)];
let refs = NodeRefs::from_iter(&nodes);
let v = refs.into_iter().sorted().collect::<Vec<_>>();
assert_eq!(v, vec![&nodes[0], &nodes[1], &nodes[2]]);
}
#[test]
fn test_ref_into_iterator() {
let nodes = [Node(1), Node(2), Node(3)];
let refs = NodeRefs::from_iter(&nodes);
let v = (&refs).into_iter().sorted().collect::<Vec<_>>();
assert_eq!(v, vec![&nodes[0], &nodes[1], &nodes[2]]);
}
}