cons_rs/
immutable.rs

1//! An immutable list using [`Rc`](Rc).
2//!
3//! This list does not allow direct modification of its elements,
4//! but modification of the [pointers](Rc) between them.
5use alloc::rc::Rc;
6
7use super::{FusedIterator, fmt, Debug};
8
9/// A singly linked immutable list.
10/// See the [module-level documentation](self) for more.
11pub struct List<T> {
12    head: Link<T>,
13}
14
15struct Node<T> {
16    elem: T,
17    next: Link<T>,
18}
19
20type Link<T> = Option<Rc<Node<T>>>;
21
22impl<T> List<T> {
23    /// Creates a new `List`.
24    ///
25    /// # Examples
26    ///
27    /// ```
28    /// use cons_rs::immutable::List;
29    /// 
30    /// let list: List<i32> = List::new();
31    /// ```
32    #[inline]
33    pub const fn new() -> List<T> {
34        List { head: None }
35    }
36
37    /// Prepends a given element to the list,
38    /// returning a copy of the list with the added element.
39    ///
40    /// # Examples
41    ///
42    /// ```
43    /// use cons_rs::immutable::List;
44    /// 
45    /// let list = List::new().prepend(1);
46    ///
47    /// assert_eq!(list.head(), Some(&1));
48    /// ```
49    pub fn prepend(&self, element: T) -> List<T> {
50        List { head: Some(Rc::new(Node {
51            elem: element,
52            next: self.head.clone()
53        }))}
54    }
55
56    /// Returns a copy of the list with the first element removed.
57    ///
58    /// # Examples
59    ///
60    /// ```
61    /// use cons_rs::immutable::List;
62    /// 
63    /// let list = List::new().prepend(1);
64    /// assert_eq!(list.tail().head(), None);
65    ///
66    /// let list = List::new().prepend(1).prepend(2);
67    /// assert_eq!(list.tail().head(), Some(&1));
68    /// ```
69    pub fn tail(&self) -> List<T> {
70        List {
71            head: self.head.as_ref().and_then(|node| node.next.clone()) 
72        }
73    }
74
75    /// Returns a reference to the first element in the list,
76    /// if it exists.
77    ///
78    /// # Examples
79    ///
80    /// ```
81    /// use cons_rs::immutable::List;
82    /// 
83    /// let list = List::new().prepend(1);
84    ///
85    /// assert_eq!(list.head(), Some(&1));
86    /// ```
87    pub fn head(&self) -> Option<&T> {
88        self.head.as_ref().map(|node| &node.elem)
89    }
90
91    /// Returns the length of the list.
92    ///
93    /// # Examples
94    ///
95    /// ```
96    /// use cons_rs::immutable::List;
97    /// 
98    /// let list = List::new();
99    /// assert_eq!(list.len(), 0);
100    ///
101    /// let list = list.prepend(3);
102    /// assert_eq!(list.len(), 1);
103    /// ```
104    pub fn len(&self) -> usize {
105        self.iter().len()
106    }
107
108    /// Checks if the list is empty.
109    ///
110    /// # Examples
111    ///
112    /// ```
113    /// use cons_rs::immutable::List;
114    /// 
115    /// let list = List::new();
116    /// assert!(list.is_empty());
117    ///
118    /// let list = list.prepend(1);
119    /// assert!(!list.is_empty());
120    /// ```
121    #[inline]
122    pub fn is_empty(&self) -> bool {
123        self.head.is_none()
124    }
125    
126    /// Creates an [iterator that yields references](Iter)
127    /// to all the elements in the list.
128    ///
129    /// # Examples
130    ///
131    /// ```
132    /// use cons_rs::immutable::List;
133    /// 
134    /// let list = List::new().prepend(1).prepend(2);
135    ///
136    /// let mut iter = list.iter();
137    ///
138    /// assert_eq!(iter.next(), Some(&2));
139    /// assert_eq!(iter.next(), Some(&1));
140    /// assert_eq!(iter.next(), None);
141    /// ```
142    pub fn iter(&self) -> Iter<'_, T> {
143        Iter { next: self.head.as_deref() }
144    }
145}
146
147impl<T> Clone for List<T> {
148    fn clone(&self) -> Self {
149        List { head: self.head.clone() }
150    }
151}
152
153impl<T: Debug> Debug for List<T> {
154    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155        f.debug_list().entries(self.iter()).finish()
156    }
157}
158
159impl<T> Default for List<T> {
160    #[inline]
161    fn default() -> Self {
162        Self::new()
163    }
164}
165
166impl<T> Drop for List<T> {
167    fn drop(&mut self) {
168        let mut head = self.head.take();
169        while let Some(node) = head {
170            if let Ok(mut node) = Rc::try_unwrap(node) {
171                head = node.next.take();
172            } else {
173                break;
174            }
175        }
176    }
177}
178
179into_iter_impl!{ref, Iter<'a, T>, List::iter}
180
181/// An [iterator](Iterator) that yields references
182/// to all the elements in a list.
183pub struct Iter<'a, T> {
184    next: Option<&'a Node<T>>
185}
186
187impl<'a, T> Iterator for Iter<'a, T> {
188    type Item = &'a T;
189
190    fn next(&mut self) -> Option<Self::Item> {
191        self.next.map(|node| {
192            self.next = node.next.as_deref();
193            &node.elem
194        })
195    }
196
197    fn size_hint(&self) -> (usize, Option<usize>) {
198        let mut len = 0;
199        let mut curr = self.next;
200        while let Some(node) = curr {
201            curr = node.next.as_deref();
202            len += 1;
203        }
204        (len, Some(len))
205    }
206}
207
208// No methods because default impls are fine
209impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
210
211impl<'a, T> FusedIterator for Iter<'a, T> {}
212
213#[cfg(test)]
214mod tests {
215    use super::List;
216
217    #[test]
218    fn head_tail_prepend() {
219        let list = List::new();
220
221        let list = list.prepend(1).prepend(2);
222        assert_eq!(list.head(), Some(&2));
223
224        let list = list.tail();
225        assert_eq!(list.head(), Some(&1));
226
227        let list = list.tail();
228        assert_eq!(list.head(), None);
229        
230        let list = list.tail();
231        assert_eq!(list.head(), None);
232    }
233
234    #[test]
235    fn len() {
236        let list = List::new();
237        assert_eq!(list.len(), 0);
238        assert_eq!(list.iter().size_hint(), (0, Some(0)));
239
240        let list = list.prepend(1);
241        assert_eq!(list.len(), 1);
242        assert_eq!(list.iter().size_hint(), (1, Some(1)));
243    }
244    
245    #[test]
246    fn iter() {
247        let list = List::new().prepend(1).prepend(2);
248
249        let mut iter = list.iter();
250        
251        assert_eq!(iter.next(), Some(&2));
252        assert_eq!(iter.next(), Some(&1));
253        assert_eq!(iter.next(), None);
254    }
255
256    #[test]
257    fn into_iter() {
258        let list = List::new().prepend(1).prepend(2);
259
260        let mut iter = list.into_iter();
261
262        assert_eq!(iter.next(), Some(&2));
263        assert_eq!(iter.next(), Some(&1));
264        assert_eq!(iter.next(), None);
265    }
266}