facet_core/types/def/
iter.rs

1use crate::{PtrConst, PtrMut};
2
3/// Create a new iterator that iterates over the provided value
4///
5/// # Safety
6///
7/// The `value` parameter must point to aligned, initialized memory of the correct type.
8pub type IterInitWithValueFn = for<'value> unsafe fn(value: PtrConst<'value>) -> PtrMut<'value>;
9
10/// Advance the iterator, returning the next value from the iterator
11///
12/// # Safety
13///
14/// The `iter` parameter must point to aligned, initialized memory of the correct type.
15pub type IterNextFn<T> =
16    for<'iter> unsafe fn(iter: PtrMut<'iter>) -> Option<<T as IterItem>::Item<'iter>>;
17
18/// Advance the iterator in reverse, returning the next value from the end
19/// of the iterator.
20///
21/// # Safety
22///
23/// The `iter` parameter must point to aligned, initialized memory of the correct type.
24pub type IterNextBackFn<T> =
25    for<'iter> unsafe fn(iter: PtrMut<'iter>) -> Option<<T as IterItem>::Item<'iter>>;
26
27/// Return the lower and upper bounds of the iterator, if known.
28///
29/// # Safety
30///
31/// The `iter` parameter must point to aligned, initialized memory of the correct type.
32pub type IterSizeHintFn =
33    for<'iter> unsafe fn(iter: PtrMut<'iter>) -> Option<(usize, Option<usize>)>;
34
35/// Deallocate the iterator
36///
37/// # Safety
38///
39/// The `iter` parameter must point to aligned, initialized memory of the correct type.
40pub type IterDeallocFn = for<'iter> unsafe fn(iter: PtrMut<'iter>);
41
42/// VTable for an iterator
43#[derive(Clone, Copy, Debug)]
44#[repr(C)]
45pub struct IterVTable<T: IterItem> {
46    /// cf. [`IterInitWithValueFn`]
47    pub init_with_value: Option<IterInitWithValueFn>,
48
49    /// cf. [`IterNextFn`]
50    pub next: IterNextFn<T>,
51
52    /// cf. [`IterNextBackFn`]
53    pub next_back: Option<IterNextBackFn<T>>,
54
55    /// cf. [`IterSizeHintFn`]
56    pub size_hint: Option<IterSizeHintFn>,
57
58    /// cf. [`IterDeallocFn`]
59    pub dealloc: IterDeallocFn,
60}
61
62impl<T: IterItem> IterVTable<T> {
63    /// Returns a builder for [`IterVTable`]
64    pub const fn builder() -> IterVTableBuilder<T> {
65        IterVTableBuilder::new()
66    }
67}
68
69/// Builds an [`IterVTable`]
70pub struct IterVTableBuilder<T: IterItem> {
71    init_with_value: Option<IterInitWithValueFn>,
72    next: Option<IterNextFn<T>>,
73    next_back: Option<IterNextBackFn<T>>,
74    size_hint: Option<IterSizeHintFn>,
75    dealloc: Option<IterDeallocFn>,
76}
77
78impl<T: IterItem> IterVTableBuilder<T> {
79    /// Creates a new [`IterVTableBuilder`] with all fields set to `None`.
80    #[allow(clippy::new_without_default)]
81    pub const fn new() -> Self {
82        Self {
83            init_with_value: None,
84            next: None,
85            next_back: None,
86            size_hint: None,
87            dealloc: None,
88        }
89    }
90
91    /// Sets the `init_with_value` function
92    pub const fn init_with_value(mut self, f: IterInitWithValueFn) -> Self {
93        self.init_with_value = Some(f);
94        self
95    }
96
97    /// Sets the `next` function
98    pub const fn next(mut self, f: IterNextFn<T>) -> Self {
99        self.next = Some(f);
100        self
101    }
102
103    /// Sets the `next_back` function
104    pub const fn next_back(mut self, f: IterNextBackFn<T>) -> Self {
105        self.next_back = Some(f);
106        self
107    }
108
109    /// Sets the `dealloc` function
110    pub const fn dealloc(mut self, f: IterDeallocFn) -> Self {
111        self.dealloc = Some(f);
112        self
113    }
114
115    /// Builds the [`IterVTable`] from the current state of the builder.
116    ///
117    /// # Panics
118    ///
119    /// Panic if any of the required fields (init_with_value, next, dealloc) are `None`.
120    pub const fn build(self) -> IterVTable<T> {
121        assert!(self.init_with_value.is_some());
122        IterVTable {
123            init_with_value: self.init_with_value,
124            next: self.next.unwrap(),
125            next_back: self.next_back,
126            size_hint: self.size_hint,
127            dealloc: self.dealloc.unwrap(),
128        }
129    }
130}
131
132/// A kind of item that an [`IterVTable`] returns
133///
134/// This trait is needed as a utility, so the functions within [`IterVTable`]
135/// can apply the appropriate lifetime to their result types. In other words,
136/// this trait acts like a higher-kinded type that takes a lifetime.
137pub trait IterItem {
138    /// The output type of the iterator, bound by the lifetime `'a`
139    type Item<'a>;
140}
141
142impl IterItem for PtrConst<'_> {
143    type Item<'a> = PtrConst<'a>;
144}
145
146impl<T, U> IterItem for (T, U)
147where
148    T: IterItem,
149    U: IterItem,
150{
151    type Item<'a> = (T::Item<'a>, U::Item<'a>);
152}