deepmesa_collections/linkedlist/
iter.rs

1/*
2   Linked List: A fast and flexible doubly linked list that
3   allows for O(1) inserts and removes from the middle of the
4   list. This list preallocates memory and doesn't have to allocate
5   and deallocate memory on every insert / remove operation
6
7   Copyright 2021 "Rahul Singh <rsingh@arrsingh.com>"
8
9   Licensed under the Apache License, Version 2.0 (the "License");
10   you may not use this file except in compliance with the License.
11   You may obtain a copy of the License at
12
13       http://www.apache.org/licenses/LICENSE-2.0
14
15   Unless required by applicable law or agreed to in writing, software
16   distributed under the License is distributed on an "AS IS" BASIS,
17   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   See the License for the specific language governing permissions and
19   limitations under the License.
20*/
21use crate::{linkedlist::list::LinkedList, linkedlist::node::NodeHandle};
22
23#[derive(Debug)]
24enum IterDirection {
25    HeadToTail,
26    TailToHead,
27}
28
29/// A bidirectional iterator over the nodes of the
30/// [`LinkedList`](LinkedList).
31///
32/// This struct is created by the [`.iter()`](LinkedList#method.iter)
33/// of the [`LinkedList`](LinkedList).
34///
35/// # Examples
36/// ```
37/// use deepmesa_collections::LinkedList;
38/// use deepmesa_collections::linkedlist::Iter;
39///
40/// let mut list = LinkedList::<u8>::new();
41/// list.push_front(1);
42/// list.push_front(2);
43/// list.push_front(3);
44/// list.push_front(4);
45/// list.push_front(5);
46///
47/// let mut iter:Iter<u8> = list.iter();
48/// assert_eq!(iter.next(), Some(&5));
49/// assert_eq!(iter.next(), Some(&4));
50/// assert_eq!(iter.next(), Some(&3));
51/// iter = iter.reverse();
52/// assert_eq!(iter.next(), Some(&4));
53/// assert_eq!(iter.next(), Some(&5));
54/// assert_eq!(iter.next(), None);
55/// ```
56#[derive(Debug)]
57pub struct Iter<'a, T> {
58    list: &'a LinkedList<T>,
59    cursor: Option<NodeHandle<T>>,
60    dir: IterDirection,
61}
62
63/// A bidirectional iterator over the node of the [`LinkedList`] with
64/// mutable references that allows the value to be modified.
65///
66/// This struct is created by the
67/// [`.iter_mut()`](LinkedList#method.iter_mut) method of the
68/// [`LinkedList`](LinkedList).
69///
70/// # Examples
71/// ```
72/// use deepmesa_collections::LinkedList;
73/// use deepmesa_collections::linkedlist::IterMut;
74/// use deepmesa_collections::linkedlist::Iter;
75///
76/// let mut list = LinkedList::<u8>::new();
77/// list.push_front(1);
78/// list.push_front(2);
79/// list.push_front(3);
80///
81/// let mut iter_mut: IterMut<u8> = list.iter_mut();
82/// for e in iter_mut {
83///     *e += 100;
84/// }
85///
86/// let mut iter:Iter<u8> = list.iter();
87/// assert_eq!(iter.next(), Some(&103));
88/// assert_eq!(iter.next(), Some(&102));
89/// assert_eq!(iter.next(), Some(&101));
90/// assert_eq!(iter.next(), None);
91/// ```
92#[derive(Debug)]
93pub struct IterMut<'a, T> {
94    list: &'a mut LinkedList<T>,
95    cursor: Option<NodeHandle<T>>,
96    dir: IterDirection,
97}
98
99macro_rules! iter_reverse {
100    ($self: ident) => {
101        /// Reverses the direction of the iterator
102        pub fn reverse(mut $self) -> Self {
103            match &$self.cursor {
104                None => match $self.dir {
105                    IterDirection::HeadToTail => {
106                        $self.dir = IterDirection::TailToHead;
107                        $self.cursor = $self.list.tail_node();
108                    }
109                    IterDirection::TailToHead => {
110                        $self.dir = IterDirection::HeadToTail;
111                        $self.cursor = $self.list.head_node();
112                    }
113                },
114                Some(node) => match $self.dir {
115                    IterDirection::HeadToTail => {
116                        if node.ptr == $self.list.head {
117                            $self.cursor = $self.list.tail_node();
118                        } else {
119                            $self.cursor = $self.list.prev_node(&node);
120                            if !$self.cursor.is_none() {
121                                $self.cursor = $self.list.prev_node(&$self.cursor.unwrap());
122                            }
123                        }
124                        $self.dir = IterDirection::TailToHead;
125                    }
126                    IterDirection::TailToHead => {
127                        if node.ptr == $self.list.tail {
128                            $self.cursor = $self.list.head_node();
129                        }  else {
130                            $self.cursor = $self.list.next_node(&node);
131                            if !$self.cursor.is_none() {
132                                $self.cursor = $self.list.next_node(&$self.cursor.unwrap());
133                            }
134                        }
135                        $self.dir = IterDirection::HeadToTail;
136                    }
137                },
138            }
139            $self
140        }
141    };
142}
143
144impl<'a, T> Iter<'a, T> {
145    pub(crate) fn new(list: &'a LinkedList<T>) -> Iter<T> {
146        Iter {
147            list,
148            cursor: list.head_node(),
149            dir: IterDirection::HeadToTail,
150        }
151    }
152
153    iter_reverse!(self);
154}
155
156impl<'a, T> IterMut<'a, T> {
157    pub(crate) fn new(list: &'a mut LinkedList<T>) -> IterMut<T> {
158        IterMut {
159            cursor: list.head_node(),
160            list,
161            dir: IterDirection::HeadToTail,
162        }
163    }
164
165    iter_reverse!(self);
166}
167
168impl<'a, T> Iterator for Iter<'a, T> {
169    type Item = &'a T;
170    fn next(&mut self) -> Option<&'a T> {
171        match &self.cursor {
172            None => None,
173            Some(cur) => {
174                let node_ptr = cur.ptr;
175                match self.dir {
176                    IterDirection::HeadToTail => {
177                        self.cursor = self.list.next_node(&cur);
178                    }
179                    IterDirection::TailToHead => {
180                        self.cursor = self.list.prev_node(&cur);
181                    }
182                }
183                unsafe { Some(&(*node_ptr).val) }
184            }
185        }
186    }
187}
188
189impl<'a, T> Iterator for IterMut<'a, T> {
190    type Item = &'a mut T;
191    fn next(&mut self) -> Option<&'a mut T> {
192        match &mut self.cursor {
193            None => None,
194            Some(cur) => {
195                let node_ptr = cur.ptr;
196                match self.dir {
197                    IterDirection::HeadToTail => {
198                        self.cursor = self.list.next_node(&cur);
199                    }
200                    IterDirection::TailToHead => {
201                        self.cursor = self.list.prev_node(&cur);
202                    }
203                }
204                unsafe { Some(&mut (*node_ptr).val) }
205            }
206        }
207    }
208}
209
210impl<'a, T> IntoIterator for &'a LinkedList<T> {
211    type Item = &'a T;
212    type IntoIter = Iter<'a, T>;
213    fn into_iter(self) -> Self::IntoIter {
214        self.iter()
215    }
216}
217
218impl<'a, T> IntoIterator for &'a mut LinkedList<T> {
219    type Item = &'a mut T;
220    type IntoIter = IterMut<'a, T>;
221    fn into_iter(self) -> Self::IntoIter {
222        self.iter_mut()
223    }
224}