1use core::convert::Infallible;
2use std::collections::HashMap;
3use std::collections::hash_map::Entry;
4use std::hash::Hash;
5use std::rc::Rc;
6
7pub fn unique<T: Hash + Eq>(
26 it: impl IntoIterator<Item = T>,
27) -> Result<impl Iterator<Item = Rc<T>>, Infallible> {
28 let mut set = HashMap::new();
29
30 Ok(it.into_iter().filter_map(move |elem| {
31 if let Entry::Vacant(entry) = set.entry(Rc::new(elem)) {
34 Some(Rc::clone(entry.insert_entry(()).key()))
35 } else {
36 None
37 }
38 }))
39}
40
41#[cfg(test)]
42mod test {
43 use alloc::vec; use alloc::vec::Vec;
45
46 use super::*;
47
48 #[test]
49 fn test_unique() {
50 assert_eq!(
51 unique(["a", "b", "a", "c"]).unwrap().collect::<Vec<_>>(),
52 vec![Rc::new("a"), Rc::new("b"), Rc::new("c")]
53 );
54 assert_eq!(
55 unique([1, 1, 1, 2, 1]).unwrap().collect::<Vec<_>>(),
56 vec![Rc::new(1), Rc::new(2)]
57 );
58 assert_eq!(
59 unique("hello".chars()).unwrap().collect::<Vec<_>>(),
60 vec![Rc::new('h'), Rc::new('e'), Rc::new('l'), Rc::new('o')]
61 );
62 }
63}