mc_core/util/
palette.rs

1
2/// A palette is a vector with limited capacity that allows searching indices of elements.
3pub struct Palette<T> {
4    items: Vec<T>,
5    capacity: usize
6}
7
8impl<T> Palette<T>
9where
10    T: Clone + Copy + Eq
11{
12
13    /// Create a new empty palette with the specified capacity.
14    pub fn new(capacity: usize) -> Self {
15        assert_ne!(capacity, 0, "Given capacity is zero.");
16        Self {
17            items: Vec::with_capacity(capacity),
18            capacity
19        }
20    }
21
22    /// Create a new palette of the specified capacity and fill it with the given iterator.
23    /// At most `capacity` elements are took from the iterator.
24    pub fn with_defaults<I>(defaults: I, capacity: usize) -> Self
25    where
26        I: IntoIterator<Item = T>
27    {
28        assert_ne!(capacity, 0, "Given capacity is zero.");
29        let mut items = Vec::with_capacity(capacity);
30        items.extend(defaults.into_iter().take(capacity));
31        Self {
32            items,
33            capacity
34        }
35    }
36
37    /// Create a new palette with a default element into it and with the specified capacity.
38    pub fn with_default(default: T, capacity: usize) -> Self {
39        Self::with_defaults(Some(default), capacity)
40    }
41
42    pub fn from_raw(items: Vec<T>, capacity: usize) -> Self {
43        assert_ne!(capacity, 0, "Given capacity is zero.");
44        Self {
45            items,
46            capacity
47        }
48    }
49
50    #[inline]
51    pub fn capacity(&self) -> usize {
52        self.capacity
53    }
54
55    #[inline]
56    pub fn len(&self) -> usize {
57        self.items.len()
58    }
59
60    #[inline]
61    pub fn clear(&mut self) {
62        self.items.clear()
63    }
64
65    pub fn ensure_index(&mut self, target_item: T) -> Option<usize> {
66        match self.search_index(target_item) {
67            Some(index) => Some(index),
68            None => self.insert_index(target_item)
69        }
70    }
71
72    pub fn insert_index(&mut self, target_item: T) -> Option<usize> {
73        let length = self.items.len();
74        if length < self.capacity {
75            self.items.push(target_item);
76            Some(length)
77        } else {
78            None
79        }
80    }
81
82    pub fn search_index(&self, target_item: T) -> Option<usize> {
83        return self.items.iter()
84            .position(|item| *item == target_item);
85    }
86
87    pub fn get_item(&self, index: usize) -> Option<T> {
88        self.items.get(index).copied()
89    }
90
91    pub fn iter(&self) -> impl Iterator<Item = T> + '_ {
92        self.items.iter().copied()
93    }
94
95}
96
97#[cfg(test)]
98mod tests {
99
100    use super::*;
101
102    #[test]
103    #[should_panic]
104    fn invalid_capacity() {
105        Palette::with_default("default", 0);
106    }
107
108    #[test]
109    fn valid_usage() {
110
111        let mut palette = Palette::with_default("default", 5);
112        assert_eq!(palette.get_item(0).unwrap(), "default");
113        assert_eq!(palette.search_index("default").unwrap(), 0);
114        assert_eq!(palette.ensure_index("default").unwrap(), 0);
115
116        assert_eq!(palette.ensure_index("str1").unwrap(), 1);
117        assert_eq!(palette.ensure_index("str2").unwrap(), 2);
118        assert_eq!(palette.ensure_index("str3").unwrap(), 3);
119        assert_eq!(palette.ensure_index("str4").unwrap(), 4);
120        assert!(palette.ensure_index("str5").is_none());
121
122    }
123
124}