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}