standard_lib/collections/linked/list/
linked_list.rs

1use std::fmt::{self, Debug, Display, Formatter};
2use std::hash::{Hash, Hasher};
3use std::marker::PhantomData;
4use std::mem;
5use std::ops::{Index, IndexMut};
6
7use derive_more::IsVariant;
8
9use super::{Iter, IterMut, Length, Node, NodePtr, ONE};
10use crate::collections::contiguous::Vector;
11use crate::collections::linked::cursor::{Cursor, CursorContents, CursorPosition, CursorState};
12#[doc(inline)]
13pub use crate::util::error::{CapacityOverflow, IndexOutOfBounds};
14use crate::util::result::ResultExtension;
15
16/// A list with links in both directions. See also: [`Cursor`] for bi-directional iteration and
17/// traversal.
18///
19/// # Time Complexity
20/// For this analysis of time complexity, variables are defined as follows:
21/// - `n`: The number of items in the LinkedList.
22/// - `i`: The index of the item in question.
23///
24/// | Method | Complexity |
25/// |-|-|
26/// | `len` | `O(1)` |
27/// | `front/back` | `O(1)` |
28/// | `push_front/back` | `O(1)` |
29/// | `pop_front/back` | `O(1)` |
30/// | `get` | `O(min(i, n-i))` |
31/// | `insert` | `O(min(i, n-i))` |
32/// | `remove` | `O(min(i, n-i))` |
33/// | `replace` | `O(min(i, n-i))` |
34/// | `append` | `O(1)` |
35/// | `contains` | `O(n)` |
36///
37/// As a general note, modern computer architecture isn't kind to linked lists, (or more
38/// importantly, favours contiguous collections) because all `O(i)` or `O(n)` operations will
39/// consist primarily of cache misses. For this reason, [`Vector`] should be preferred for most
40/// applications unless LinkedList and the accompanying [`Cursor`] type's `O(1)` methods are being
41/// heavily utilized.
42#[derive(PartialEq, Eq, Hash)]
43pub struct LinkedList<T> {
44    pub(crate) state: ListState<T>,
45    pub(crate) _phantom: PhantomData<T>,
46}
47
48#[derive(Default, PartialEq, Eq, Hash, IsVariant)]
49pub(crate) enum ListState<T> {
50    #[default]
51    Empty,
52    Full(ListContents<T>),
53}
54
55use ListState::*;
56
57pub(crate) struct ListContents<T> {
58    pub len: Length,
59    pub head: NodePtr<T>,
60    pub tail: NodePtr<T>,
61}
62
63impl<T> LinkedList<T> {
64    /// Creates a new LinkedList with no elements.
65    pub const fn new() -> LinkedList<T> {
66        LinkedList {
67            state: Empty,
68            _phantom: PhantomData,
69        }
70    }
71
72    /// Returns the length of the LinkedList.
73    pub const fn len(&self) -> usize {
74        self.state.len()
75    }
76
77    /// Returns true if the LinkedList contains no elements.
78    pub const fn is_empty(&self) -> bool {
79        self.state.is_empty()
80    }
81
82    /// Returns a reference to the first element in the list, if it exists.
83    pub const fn front(&self) -> Option<&T> {
84        match self.state {
85            Empty => None,
86            Full(ListContents { head, .. }) => Some(head.value()),
87        }
88    }
89
90    /// Returns a mutable reference to the first element in the list, if it exists.
91    pub const fn front_mut(&mut self) -> Option<&mut T> {
92        match self.state {
93            Empty => None,
94            Full(ListContents { mut head, .. }) => Some(head.value_mut()),
95        }
96    }
97
98    /// Returns a reference to the last element in the list, if it exists.
99    pub const fn back(&self) -> Option<&T> {
100        match self.state {
101            Empty => None,
102            Full(ListContents { tail, .. }) => Some(tail.value()),
103        }
104    }
105
106    /// Returns a mutable reference to the last element in the list, if it exists.
107    pub const fn back_mut(&mut self) -> Option<&mut T> {
108        match self.state {
109            Empty => None,
110            Full(ListContents { mut tail, .. }) => Some(tail.value_mut()),
111        }
112    }
113
114    /// Add the provided element to the front of the LinkedList.
115    pub fn push_front(&mut self, value: T) {
116        match &mut self.state {
117            Empty => self.state = ListState::single(value),
118            Full(contents) => contents.push_front(value),
119        }
120    }
121
122    /// Add the provided element to the back of the LinkedList.
123    pub fn push_back(&mut self, value: T) {
124        match &mut self.state {
125            Empty => self.state = ListState::single(value),
126            Full(contents) => contents.push_back(value),
127        }
128    }
129
130    /// Removes the first element from the list and returns it, if the list isn't empty.
131    pub fn pop_front(&mut self) -> Option<T> {
132        match &mut self.state {
133            Empty => None,
134            Full(ListContents { len, head, .. }) => {
135                let node = head.take_node();
136
137                match len.checked_sub(1) {
138                    Some(new_len) => {
139                        // SAFETY: Previous length is greater than 1, so the first element is
140                        // preceded by at least one more.
141                        let new_head = unsafe { node.next.unwrap_unchecked() };
142                        *head = new_head;
143                        *new_head.prev_mut() = None;
144                        *len = new_len;
145                    },
146                    None => self.state = Empty,
147                }
148
149                Some(node.value)
150            },
151        }
152    }
153
154    /// Removes the last element from the list and returns it, if the list isn't empty.
155    pub fn pop_back(&mut self) -> Option<T> {
156        match &mut self.state {
157            Empty => None,
158            Full(ListContents { len, tail, .. }) => {
159                let node = tail.take_node();
160
161                match len.checked_sub(1) {
162                    Some(new_len) => {
163                        // SAFETY: Previous length is greater than 1, so the last element is
164                        // preceded by at least one more.
165                        let new_tail = unsafe { node.prev.unwrap_unchecked() };
166                        *tail = new_tail;
167                        *new_tail.next_mut() = None;
168                        *len = new_len;
169                    },
170                    None => self.state = Empty,
171                }
172
173                Some(node.value)
174            },
175        }
176    }
177
178    /// Returns a reference to the element at the provided `index`, panicking on a failure.
179    ///
180    /// The same functionality can be achieved using the [`Index`] operator.
181    ///
182    /// # Panics
183    /// Panics if `index` is out of bounds of the LinkedList.
184    pub fn get(&self, index: usize) -> &T {
185        self.try_get(index).throw()
186    }
187
188    /// Returns a reference to the element at the provided `index`, returning an [`Err`] on a
189    /// failure rather than panicking.
190    ///
191    /// The same functionality can be achieved using the [`Index`] operator.
192    pub fn try_get(&self, index: usize) -> Result<&T, IndexOutOfBounds> {
193        Ok(self.checked_seek(index)?.value())
194    }
195
196    /// Returns a mutable reference to the element at the provided `index`, panicking on a failure.
197    ///
198    /// The same functionality can be achieved using the [`IndexMut`] operator.
199    ///
200    /// # Panics
201    /// Panics if `index` is out of bounds of the LinkedList.
202    pub fn get_mut(&mut self, index: usize) -> &mut T {
203        self.try_get_mut(index).throw()
204    }
205
206    /// Returns a mutable reference to the element at the provided `index`, returning an [`Err`] on
207    /// a failure rather than panicking.
208    ///
209    /// The same functionality can be achieved using the [`IndexMut`] operator.
210    pub fn try_get_mut(&mut self, index: usize) -> Result<&mut T, IndexOutOfBounds> {
211        Ok(self.checked_seek(index)?.value_mut())
212    }
213
214    pub fn insert(&mut self, index: usize, value: T) {
215        self.try_insert(index, value).throw()
216    }
217
218    pub fn try_insert(&mut self, index: usize, value: T) -> Result<(), IndexOutOfBounds> {
219        let contents = self.checked_contents_for_index_mut(index - 1)?;
220        match index {
221            0 => self.push_front(value),
222            val if val == contents.len.get() => self.push_back(value),
223            val => {
224                let prev_node = contents.seek(val - 1);
225
226                contents.len = contents.len.checked_add(1).ok_or(CapacityOverflow).throw();
227
228                let node = NodePtr::from_node(Node {
229                    value,
230                    prev: Some(prev_node),
231                    next: *prev_node.next(),
232                });
233
234                // SAFETY: For this branch, we aren't adding at the front or back, so the node
235                // before the given index has a next node.
236                unsafe { *prev_node.next().unwrap_unchecked().prev_mut() = Some(node); }
237                *prev_node.next_mut() = Some(node);
238            },
239        }
240        Ok(())
241    }
242
243    pub fn remove(&mut self, index: usize) -> T {
244        self.try_remove(index).throw()
245    }
246
247    pub fn try_remove(&mut self, index: usize) -> Result<T, IndexOutOfBounds> {
248        let contents = self.checked_contents_for_index_mut(index).throw();
249        match index {
250            0 => {
251                // SAFETY: contents is already checked to be valid for the provided index.
252                Ok(unsafe { self.pop_front().unwrap_unchecked() })
253            },
254            val if val == contents.last_index() => {
255                // SAFETY: contents is already checked to be valid for the provided index.
256                Ok(unsafe { self.pop_back().unwrap_unchecked() })
257            },
258            val => {
259                let node = contents.seek(val).take_node();
260
261                // SAFETY: For this branch, both prev and next must be defined. Head and tail
262                // versions are handled with pop front / back branches.
263                unsafe {
264                    *node.prev.unwrap_unchecked().next_mut() = node.next;
265                    *node.next.unwrap_unchecked().prev_mut() = node.prev;
266                }
267                // SAFETY: If the length was 1, we would have matched one of the previous branches.
268                contents.len = unsafe { contents.len.checked_sub(1).unwrap_unchecked() };
269
270                Ok(node.value)
271            },
272        }
273    }
274
275    pub fn replace(&mut self, index: usize, new_value: T) -> T {
276        self.try_replace(index, new_value).throw()
277    }
278
279    pub fn try_replace(&mut self, index: usize, new_value: T) -> Result<T, IndexOutOfBounds> {
280        Ok(mem::replace(
281            self.checked_seek(index)?.value_mut(),
282            new_value,
283        ))
284    }
285
286    pub fn append(&mut self, other: LinkedList<T>) {
287        match &mut self.state {
288            Empty => *self = other,
289            Full(self_contents) => match &other.state {
290                Empty => {},
291                Full(other_contents) => {
292                    self_contents.len = self_contents.len
293                        .checked_add(other_contents.len.get())
294                        .ok_or(CapacityOverflow).throw();
295
296                    *self_contents.tail.next_mut() = Some(other_contents.head);
297                    *other_contents.head.prev_mut() = Some(self_contents.tail);
298                    self_contents.tail = other_contents.tail;
299                },
300            },
301        }
302    }
303
304    pub fn cursor_head(mut self) -> Cursor<T> {
305        Cursor {
306            state: match mem::take(&mut self.state) {
307                Empty => CursorState::Empty,
308                Full(contents) => CursorState::Full(CursorContents {
309                    pos: CursorPosition::Head,
310                    list: contents,
311                }),
312            },
313            _phantom: PhantomData,
314        }
315    }
316
317    pub fn cursor_tail(mut self) -> Cursor<T> {
318        Cursor {
319            state: match mem::take(&mut self.state) {
320                Empty => CursorState::Empty,
321                Full(contents) => CursorState::Full(CursorContents {
322                    pos: CursorPosition::Tail,
323                    list: contents,
324                }),
325            },
326            _phantom: PhantomData,
327        }
328    }
329
330    pub fn cursor_front(mut self) -> Cursor<T> {
331        Cursor {
332            state: match mem::take(&mut self.state) {
333                Empty => CursorState::Empty,
334                Full(contents) => CursorState::Full(CursorContents {
335                    pos: CursorPosition::Ptr {
336                        ptr: contents.head,
337                        index: 0,
338                    },
339                    list: contents,
340                }),
341            },
342            _phantom: PhantomData,
343        }
344    }
345
346    pub fn cursor_back(mut self) -> Cursor<T> {
347        Cursor {
348            state: match mem::take(&mut self.state) {
349                Empty => CursorState::Empty,
350                Full(contents) => CursorState::Full(CursorContents {
351                    pos: CursorPosition::Ptr {
352                        ptr: contents.tail,
353                        index: contents.last_index(),
354                    },
355                    list: contents,
356                }),
357            },
358            _phantom: PhantomData,
359        }
360    }
361
362    pub fn iter_mut(&mut self) -> IterMut<'_, T> {
363        self.into_iter()
364    }
365
366    pub fn iter(&self) -> Iter<'_, T> {
367        self.into_iter()
368    }
369}
370
371impl<T: Eq> LinkedList<T> {
372    pub fn index_of(&self, item: &T) -> Option<usize> {
373        for (index, element) in self.iter().enumerate() {
374            if element == item { return Some(index); }
375        }
376        None
377    }
378
379    pub fn contains(&self, item: &T) -> bool {
380        for i in self.iter() {
381            if i == item { return true; }
382        }
383        false
384    }
385}
386
387impl<T> LinkedList<T> {
388    pub(crate) fn checked_seek(&self, index: usize) -> Result<NodePtr<T>, IndexOutOfBounds> {
389        Ok(self.checked_contents_for_index(index)?.seek(index))
390    }
391
392    pub(crate) const fn checked_contents_for_index(
393        &self,
394        index: usize,
395    ) -> Result<&ListContents<T>, IndexOutOfBounds> {
396        match &self.state {
397            Empty => Err(IndexOutOfBounds { index, len: 0 }),
398            Full(contents) => {
399                let len = contents.len.get();
400                if index < len {
401                    Ok(contents)
402                } else {
403                    Err(IndexOutOfBounds { index, len })
404                }
405            },
406        }
407    }
408
409    pub(crate) const fn checked_contents_for_index_mut(
410        &mut self,
411        index: usize,
412    ) -> Result<&mut ListContents<T>, IndexOutOfBounds> {
413        match &mut self.state {
414            Empty => Err(IndexOutOfBounds { index, len: 0 }),
415            Full(contents) => {
416                let len = contents.len.get();
417                if index < len {
418                    Ok(contents)
419                } else {
420                    Err(IndexOutOfBounds { index, len })
421                }
422            },
423        }
424    }
425
426    #[allow(clippy::unwrap_used)]
427    pub(crate) fn verify_double_links(&self) {
428        match self.state {
429            Empty => {},
430            Full(ListContents { head, tail, .. }) => {
431                let mut curr = head;
432                while let Some(next) = curr.next() {
433                    // UNWRAP: This needs to panic if prev is None.
434                    assert!(next.prev().unwrap() == curr);
435                    curr = *next;
436                }
437                assert!(tail == curr);
438            },
439        }
440    }
441}
442
443impl<T> ListContents<T> {
444    pub fn seek(&self, index: usize) -> NodePtr<T> {
445        if index < self.len.get() / 2 {
446            self.seek_fwd(index, self.head)
447        } else {
448            self.seek_bwd(self.last_index() - index, self.tail)
449        }
450    }
451
452    pub fn seek_fwd(&self, count: usize, mut node: NodePtr<T>) -> NodePtr<T> {
453        for _ in 0..count {
454            node = node.next().unwrap();
455        }
456        node
457    }
458
459    pub fn seek_bwd(&self, count: usize, mut node: NodePtr<T>) -> NodePtr<T> {
460        for _ in 0..count {
461            node = node.prev().unwrap();
462        }
463        node
464    }
465
466    pub fn push_front(&mut self, value: T) {
467        self.len = self.len.checked_add(1).ok_or(CapacityOverflow).throw();
468
469        let node = NodePtr::from_node(Node {
470            value,
471            prev: None,
472            next: Some(self.head),
473        });
474
475        *self.head.prev_mut() = Some(node);
476        self.head = node;
477    }
478
479    pub fn push_back(&mut self, value: T) {
480        self.len = self.len.checked_add(1).ok_or(CapacityOverflow).throw();
481
482        let node = NodePtr::from_node(Node {
483            value,
484            prev: Some(self.tail),
485            next: None,
486        });
487
488        *self.tail.next_mut() = Some(node);
489        self.tail = node;
490    }
491
492    pub fn wrap_one(value: T) -> ListContents<T> {
493        let node = NodePtr::from_node(Node {
494            value,
495            prev: None,
496            next: None,
497        });
498
499        ListContents {
500            len: ONE,
501            head: node,
502            tail: node,
503        }
504    }
505
506    pub const fn last_index(&self) -> usize {
507        self.len.get() - 1
508    }
509}
510
511impl<T> ListState<T> {
512    pub fn single(value: T) -> ListState<T> {
513        Full(ListContents::wrap_one(value))
514    }
515}
516
517impl<T> Index<usize> for LinkedList<T> {
518    type Output = T;
519
520    fn index(&self, index: usize) -> &Self::Output {
521        self.get(index)
522    }
523}
524
525impl<T> IndexMut<usize> for LinkedList<T> {
526    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
527        self.get_mut(index)
528    }
529}
530
531impl<T> FromIterator<T> for LinkedList<T> {
532    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
533        let mut list = LinkedList::new();
534        for item in iter.into_iter() {
535            list.push_back(item);
536        }
537        list
538    }
539}
540
541impl<T> Default for LinkedList<T> {
542    fn default() -> Self {
543        Self::new()
544    }
545}
546
547impl<T> Drop for LinkedList<T> {
548    fn drop(&mut self) {
549        match self.state {
550            Empty => {},
551            Full(ListContents { head, .. }) => {
552                let mut curr = Some(head);
553                while let Some(ptr) = curr {
554                    curr = *ptr.next();
555                    unsafe { ptr.drop_node(); }
556                }
557            },
558        }
559    }
560}
561
562impl<T: PartialEq> PartialEq for ListContents<T> {
563    fn eq(&self, other: &Self) -> bool {
564        if self.len != other.len { return false; }
565        let mut node_a = self.head;
566        let mut node_b = other.head;
567
568        loop {
569            if node_a.value() != node_b.value() {
570                break false;
571            }
572            match (node_a.next(), node_b.next()) {
573                (Some(next_a), Some(next_b)) => {
574                    node_a = *next_a;
575                    node_b = *next_b;
576                },
577                // Both sides have the same length, so if they aren't both Some, they are both None.
578                // It feels a little neater to do a catchall here then using unreachable_unchecked.
579                _ => break true,
580            }
581        }
582    }
583}
584
585impl<T: Eq> Eq for ListContents<T> {}
586
587impl<T: Hash> Hash for ListContents<T> {
588    fn hash<H: Hasher>(&self, state: &mut H) {
589        self.len.hash(state);
590        let mut node = self.head;
591
592        loop {
593            node.value().hash(state);
594            match node.next() {
595                Some(next) => {
596                    node = *next;
597                },
598                _ => break,
599            }
600        }
601
602        // Terminate variable length hashing sequence.
603        0xFF.hash(state);
604    }
605}
606
607impl<T> Clone for ListContents<T> {
608    fn clone(&self) -> Self {
609        ListContents {
610            len: self.len,
611            head: self.head,
612            tail: self.tail,
613        }
614    }
615}
616
617impl<T> ListState<T> {
618    pub const fn len(&self) -> usize {
619        match self {
620            Empty => 0,
621            Full(ListContents { len, .. }) => len.get(),
622        }
623    }
624}
625
626impl<T> Clone for ListState<T> {
627    fn clone(&self) -> Self {
628        match self {
629            Empty => Empty,
630            Full(contents) => Full(contents.clone()),
631        }
632    }
633}
634
635impl<T: Debug> Debug for LinkedList<T> {
636    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
637        f.debug_struct("LinkedList")
638            .field_with("contents", |f| f.debug_list().entries(self.iter()).finish())
639            .field("len", &self.len())
640            .finish()
641    }
642}
643
644impl<T: Debug> Display for LinkedList<T> {
645    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
646        write!(
647            f,
648            "({})",
649            self.iter()
650                .map(|i| format!("{i:?}"))
651                .collect::<Vector<String>>()
652                .join(") -> (")
653        )
654    }
655}