use core::convert::Infallible;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::hash::Hash;
use std::rc::Rc;
pub fn unique<T: Hash + Eq>(
it: impl IntoIterator<Item = T>,
) -> Result<impl Iterator<Item = Rc<T>>, Infallible> {
let mut set = HashMap::new();
Ok(it.into_iter().filter_map(move |elem| {
if let Entry::Vacant(entry) = set.entry(Rc::new(elem)) {
Some(Rc::clone(entry.insert_entry(()).key()))
} else {
None
}
}))
}
#[cfg(test)]
mod test {
use alloc::vec; use alloc::vec::Vec;
use super::*;
#[test]
fn test_unique() {
assert_eq!(
unique(["a", "b", "a", "c"]).unwrap().collect::<Vec<_>>(),
vec![Rc::new("a"), Rc::new("b"), Rc::new("c")]
);
assert_eq!(
unique([1, 1, 1, 2, 1]).unwrap().collect::<Vec<_>>(),
vec![Rc::new(1), Rc::new(2)]
);
assert_eq!(
unique("hello".chars()).unwrap().collect::<Vec<_>>(),
vec![Rc::new('h'), Rc::new('e'), Rc::new('l'), Rc::new('o')]
);
}
}