1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

/// A palette is a vector with limited capacity that allows searching indices of elements.
pub struct Palette<T> {
    items: Vec<T>,
    capacity: usize
}

impl<T> Palette<T>
where
    T: Clone + Copy + Eq
{

    /// Create a new empty palette with the specified capacity.
    pub fn new(capacity: usize) -> Self {
        assert_ne!(capacity, 0, "Given capacity is zero.");
        Self {
            items: Vec::with_capacity(capacity),
            capacity
        }
    }

    /// Create a new palette of the specified capacity and fill it with the given iterator.
    /// At most `capacity` elements are took from the iterator.
    pub fn with_defaults<I>(defaults: I, capacity: usize) -> Self
    where
        I: IntoIterator<Item = T>
    {
        assert_ne!(capacity, 0, "Given capacity is zero.");
        let mut items = Vec::with_capacity(capacity);
        items.extend(defaults.into_iter().take(capacity));
        Self {
            items,
            capacity
        }
    }

    /// Create a new palette with a default element into it and with the specified capacity.
    pub fn with_default(default: T, capacity: usize) -> Self {
        Self::with_defaults(Some(default), capacity)
    }

    pub fn from_raw(items: Vec<T>, capacity: usize) -> Self {
        assert_ne!(capacity, 0, "Given capacity is zero.");
        Self {
            items,
            capacity
        }
    }

    #[inline]
    pub fn capacity(&self) -> usize {
        self.capacity
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.items.len()
    }

    #[inline]
    pub fn clear(&mut self) {
        self.items.clear()
    }

    pub fn ensure_index(&mut self, target_item: T) -> Option<usize> {
        match self.search_index(target_item) {
            Some(index) => Some(index),
            None => self.insert_index(target_item)
        }
    }

    pub fn insert_index(&mut self, target_item: T) -> Option<usize> {
        let length = self.items.len();
        if length < self.capacity {
            self.items.push(target_item);
            Some(length)
        } else {
            None
        }
    }

    pub fn search_index(&self, target_item: T) -> Option<usize> {
        return self.items.iter()
            .position(|item| *item == target_item);
    }

    pub fn get_item(&self, index: usize) -> Option<T> {
        self.items.get(index).copied()
    }

    pub fn iter(&self) -> impl Iterator<Item = T> + '_ {
        self.items.iter().copied()
    }

}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    #[should_panic]
    fn invalid_capacity() {
        Palette::with_default("default", 0);
    }

    #[test]
    fn valid_usage() {

        let mut palette = Palette::with_default("default", 5);
        assert_eq!(palette.get_item(0).unwrap(), "default");
        assert_eq!(palette.search_index("default").unwrap(), 0);
        assert_eq!(palette.ensure_index("default").unwrap(), 0);

        assert_eq!(palette.ensure_index("str1").unwrap(), 1);
        assert_eq!(palette.ensure_index("str2").unwrap(), 2);
        assert_eq!(palette.ensure_index("str3").unwrap(), 3);
        assert_eq!(palette.ensure_index("str4").unwrap(), 4);
        assert!(palette.ensure_index("str5").is_none());

    }

}