Skip to main content

reliakit_primitives/
collections.rs

1use crate::{PrimitiveError, PrimitiveResult};
2use alloc::vec::Vec;
3use core::ops::Deref;
4
5/// Owned vector guaranteed to contain at least one element.
6#[derive(Debug, Clone, PartialEq, Eq, Hash)]
7pub struct NonEmptyVec<T>(Vec<T>);
8
9impl<T> NonEmptyVec<T> {
10    /// Creates a `NonEmptyVec` from a `Vec`. Returns `Empty` if the vec is empty.
11    pub fn new(vec: Vec<T>) -> PrimitiveResult<Self> {
12        if vec.is_empty() {
13            return Err(PrimitiveError::Empty);
14        }
15        Ok(Self(vec))
16    }
17
18    /// Creates a `NonEmptyVec` containing a single item. Never fails.
19    pub fn from_one(item: T) -> Self {
20        Self(alloc::vec![item])
21    }
22
23    /// Returns the number of elements.
24    pub fn len(&self) -> usize {
25        self.0.len()
26    }
27
28    /// Always returns `false`.
29    pub fn is_empty(&self) -> bool {
30        false
31    }
32
33    /// Returns a reference to the first element.
34    pub fn first(&self) -> &T {
35        &self.0[0]
36    }
37
38    /// Returns a reference to the last element.
39    pub fn last(&self) -> &T {
40        &self.0[self.0.len() - 1]
41    }
42
43    /// Appends an element to the end.
44    pub fn push(&mut self, item: T) {
45        self.0.push(item);
46    }
47
48    /// Returns the inner slice.
49    pub fn as_slice(&self) -> &[T] {
50        &self.0
51    }
52
53    /// Consumes the wrapper and returns the inner `Vec`.
54    pub fn into_inner(self) -> Vec<T> {
55        self.0
56    }
57
58    /// Returns an iterator over the elements.
59    pub fn iter(&self) -> core::slice::Iter<'_, T> {
60        self.0.iter()
61    }
62}
63
64impl<T> Deref for NonEmptyVec<T> {
65    type Target = [T];
66
67    fn deref(&self) -> &Self::Target {
68        self.as_slice()
69    }
70}
71
72impl<T> TryFrom<Vec<T>> for NonEmptyVec<T> {
73    type Error = PrimitiveError;
74
75    fn try_from(vec: Vec<T>) -> Result<Self, Self::Error> {
76        Self::new(vec)
77    }
78}
79
80impl<T> From<NonEmptyVec<T>> for Vec<T> {
81    fn from(value: NonEmptyVec<T>) -> Self {
82        value.into_inner()
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::NonEmptyVec;
89    use crate::PrimitiveError;
90
91    #[test]
92    fn rejects_empty_vec() {
93        assert_eq!(
94            NonEmptyVec::<i32>::new(alloc::vec![]).unwrap_err(),
95            PrimitiveError::Empty
96        );
97    }
98
99    #[test]
100    fn accepts_non_empty_vec() {
101        let v = NonEmptyVec::new(alloc::vec![1, 2, 3]).unwrap();
102        assert_eq!(v.len(), 3);
103        assert!(!v.is_empty());
104    }
105
106    #[test]
107    fn from_one() {
108        let v = NonEmptyVec::from_one(42);
109        assert_eq!(v.first(), &42);
110        assert_eq!(v.last(), &42);
111    }
112
113    #[test]
114    fn first_and_last() {
115        let v = NonEmptyVec::new(alloc::vec![10, 20, 30]).unwrap();
116        assert_eq!(v.first(), &10);
117        assert_eq!(v.last(), &30);
118    }
119
120    #[test]
121    fn push_increases_len() {
122        let mut v = NonEmptyVec::from_one(1);
123        v.push(2);
124        assert_eq!(v.len(), 2);
125    }
126
127    #[test]
128    fn deref_to_slice() {
129        let v = NonEmptyVec::new(alloc::vec![1, 2, 3]).unwrap();
130        assert_eq!(&v[..], &[1, 2, 3]);
131    }
132
133    #[test]
134    fn into_inner() {
135        let v = NonEmptyVec::new(alloc::vec![1, 2]).unwrap();
136        assert_eq!(v.into_inner(), alloc::vec![1, 2]);
137    }
138
139    #[test]
140    fn try_from_vec() {
141        assert!(NonEmptyVec::<i32>::try_from(alloc::vec![]).is_err());
142        assert!(NonEmptyVec::try_from(alloc::vec![1]).is_ok());
143    }
144
145    #[test]
146    fn from_into_vec() {
147        let v = NonEmptyVec::from_one(99);
148        let inner: alloc::vec::Vec<i32> = alloc::vec::Vec::from(v);
149        assert_eq!(inner, alloc::vec![99]);
150    }
151
152    #[test]
153    fn iter() {
154        let v = NonEmptyVec::new(alloc::vec![1, 2, 3]).unwrap();
155        let sum: i32 = v.iter().sum();
156        assert_eq!(sum, 6);
157    }
158}