Skip to main content

once_list2/
iter.rs

1// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use ::allocator_api2::alloc::Allocator;
16use ::allocator_api2::alloc::Global;
17use ::allocator_api2::boxed::Box;
18
19use crate::cache_mode::NextSlot;
20
21/// An iterator over references in a [`crate::OnceList`].
22///
23/// This iterator is intentionally a named type (instead of `impl Iterator`) so that downstream
24/// crates can store it in structs without boxing or dynamic dispatch.
25///
26/// **Important**: This iterator observes newly pushed elements. If you reach the end (i.e. `next()`
27/// returns `None`) and later call `OnceList::push()`, calling `next()` again on the same `Iter`
28/// can yield the newly pushed element.
29#[derive(Clone, Copy)]
30pub struct Iter<'a, T: ?Sized, A: Allocator = Global> {
31    pub(crate) next_slot: &'a NextSlot<T, A>,
32}
33
34impl<'a, T: ?Sized + 'a, A: Allocator> Iterator for Iter<'a, T, A> {
35    type Item = &'a T;
36
37    fn next(&mut self) -> Option<Self::Item> {
38        let next_box = self.next_slot.get()?;
39        self.next_slot = &next_box.next;
40        Some(&next_box.val)
41    }
42}
43
44/// A mutable iterator over references in a [`crate::OnceList`].
45///
46/// This iterator is intentionally a named type (instead of `impl Iterator`) so that downstream
47/// crates can store it in structs without boxing or dynamic dispatch.
48///
49/// Note: Due to the singly-linked structure and internal `OnceCell`, advancing the iterator needs
50/// to update the internal pointer. To return `&'a mut T`, this iterator uses a small amount of
51/// `unsafe` internally (mirroring the previous inlined implementation of `iter_mut()`).
52pub struct IterMut<'a, T: ?Sized, A: Allocator = Global> {
53    pub(crate) next_slot: &'a mut NextSlot<T, A>,
54}
55
56impl<'a, T: ?Sized + 'a, A: Allocator> Iterator for IterMut<'a, T, A> {
57    type Item = &'a mut T;
58
59    fn next(&mut self) -> Option<Self::Item> {
60        let next_box = self.next_slot.get_mut()?;
61        // Need to cast the `self` lifetime to `&'a` to update the `Self::Item`.
62        let next_cons = unsafe { &mut *::std::ptr::from_mut(next_box.as_mut()) };
63        self.next_slot = &mut next_cons.next;
64        Some(&mut next_cons.val)
65    }
66}
67
68pub struct IntoIter<T, A: Allocator>(pub(crate) NextSlot<T, A>);
69
70impl<T, A: Allocator> Iterator for IntoIter<T, A> {
71    type Item = T;
72
73    fn next(&mut self) -> Option<Self::Item> {
74        let next_cell = self.0.take()?;
75        let next_cons = Box::into_inner(next_cell);
76        self.0 = next_cons.next;
77        Some(next_cons.val)
78    }
79}
80
81impl<'a, T: ?Sized, A: Allocator> Iter<'a, T, A> {
82    pub(crate) fn new(next_slot: &'a NextSlot<T, A>) -> Self {
83        Self { next_slot }
84    }
85}
86
87impl<'a, T: ?Sized, A: Allocator> IterMut<'a, T, A> {
88    pub(crate) fn new(next_slot: &'a mut NextSlot<T, A>) -> Self {
89        Self { next_slot }
90    }
91}