yui_core/misc/
index_list.rs1use 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}