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}