yui_core/misc/
index_list.rs

1use std::fmt::Debug;
2use std::hash::Hash;
3use std::ops::Index;
4
5use bimap::BiHashMap;
6use ahash::RandomState as ARandomState;
7use itertools::Itertools;
8
9#[derive(Default, Clone, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11#[cfg_attr(feature = "serde", serde(transparent))]
12pub struct IndexList<E>
13where E: Eq + Hash {
14    data: BiHashMap<usize, E, ARandomState, ARandomState>
15}
16
17impl<E> IndexList<E>
18where E: Eq + Hash {
19    pub fn new() -> Self {
20        Self { data: BiHashMap::with_hashers(ARandomState::new(), ARandomState::new()) }
21    }
22
23    pub fn len(&self) -> usize { 
24        self.data.len()
25    }
26
27    pub fn is_empty(&self) -> bool { 
28        self.data.is_empty()
29    }
30
31    pub fn contains(&self, x: &E) -> bool { 
32        self.data.contains_right(x)
33    }
34
35    pub fn index_of(&self, x: &E) -> Option<usize> {
36        self.data.get_by_right(x).cloned()
37    }
38
39    pub fn iter(&self) -> impl Iterator<Item = &E> { 
40        let n = self.len();
41        (0..n).map(|i| 
42            self.data.get_by_left(&i).unwrap()
43        )
44    }
45}
46
47impl<E> Debug for IndexList<E>
48where E: Eq + Hash + Debug {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        write!(f, "{:?}", self.iter().collect_vec())
51    }
52}
53
54impl<E> FromIterator<E> for IndexList<E>
55where E: Eq + Hash {
56    fn from_iter<T: IntoIterator<Item = E>>(iter: T) -> Self {
57        let data = iter.into_iter().enumerate().collect();
58        Self { data }
59    }
60}
61
62impl<E> IntoIterator for IndexList<E>
63where E: Eq + Hash {
64    type Item = E;
65    type IntoIter = std::vec::IntoIter<E>;
66
67    fn into_iter(self) -> Self::IntoIter {
68        let mut data = self.data;
69        let n = data.len();
70        (0..n).map(move |i| 
71            data.remove_by_left(&i).unwrap().1
72        ).collect_vec().into_iter()
73    }
74}
75
76impl<E> Index<usize> for IndexList<E>
77where E: Eq + Hash {
78    type Output = E;
79
80    fn index(&self, index: usize) -> &Self::Output {
81        self.data.get_by_left(&index).unwrap()
82    }
83}
84
85#[cfg(test)]
86mod tests { 
87    use super::*;
88
89    #[test]
90    fn display() {
91        let list = IndexList::from_iter([3,7,4,5,1]);
92        assert_eq!(format!("{:?}", list), "[3, 7, 4, 5, 1]");
93    }
94    
95    #[test]
96    fn index_of() {
97        let list = IndexList::from_iter([3,7,4,5,1]);
98        assert_eq!(list[0], 3);
99        assert_eq!(list[4], 1);
100        assert_eq!(list.index_of(&3), Some(0));
101        assert_eq!(list.index_of(&4), Some(2));
102        assert_eq!(list.index_of(&2), None);
103    }
104
105    #[test]
106    fn into_iter() {
107        let list = IndexList::from_iter([3,7,4,5,1]);
108        let into = list.into_iter().collect_vec();
109        assert_eq!(into, vec![3,7,4,5,1]);
110    }
111}