facet_core/types/def/
list.rs

1use crate::ptr::{PtrConst, PtrMut, PtrUninit};
2
3use super::{IterVTable, Shape};
4
5/// Fields for list types
6#[derive(Clone, Copy, Debug)]
7#[repr(C)]
8pub struct ListDef {
9    /// vtable for interacting with the list
10    pub vtable: &'static ListVTable,
11    /// shape of the items in the list
12    pub t: fn() -> &'static Shape,
13}
14
15impl ListDef {
16    /// Returns a builder for ListDef
17    pub const fn builder() -> ListDefBuilder {
18        ListDefBuilder::new()
19    }
20
21    /// Returns the shape of the items in the list
22    pub fn t(&self) -> &'static Shape {
23        (self.t)()
24    }
25}
26
27/// Builder for ListDef
28pub struct ListDefBuilder {
29    vtable: Option<&'static ListVTable>,
30    t: Option<fn() -> &'static Shape>,
31}
32
33impl ListDefBuilder {
34    /// Creates a new ListDefBuilder
35    #[allow(clippy::new_without_default)]
36    pub const fn new() -> Self {
37        Self {
38            vtable: None,
39            t: None,
40        }
41    }
42
43    /// Sets the vtable for the ListDef
44    pub const fn vtable(mut self, vtable: &'static ListVTable) -> Self {
45        self.vtable = Some(vtable);
46        self
47    }
48
49    /// Sets the item shape for the ListDef
50    pub const fn t(mut self, t: fn() -> &'static Shape) -> Self {
51        self.t = Some(t);
52        self
53    }
54
55    /// Builds the ListDef
56    pub const fn build(self) -> ListDef {
57        ListDef {
58            vtable: self.vtable.unwrap(),
59            t: self.t.unwrap(),
60        }
61    }
62}
63
64/// Initialize a list in place with a given capacity
65///
66/// # Safety
67///
68/// The `list` parameter must point to uninitialized memory of sufficient size.
69/// The function must properly initialize the memory.
70pub type ListInitInPlaceWithCapacityFn =
71    for<'mem> unsafe fn(list: PtrUninit<'mem>, capacity: usize) -> PtrMut<'mem>;
72
73/// Push an item to the list
74///
75/// # Safety
76///
77/// The `list` parameter must point to aligned, initialized memory of the correct type.
78/// `item` is moved out of (with [`core::ptr::read`]) — it should be deallocated afterwards (e.g.
79/// with [`core::mem::forget`]) but NOT dropped.
80pub type ListPushFn = unsafe fn(list: PtrMut, item: PtrMut);
81// FIXME: this forces allocating item separately, copying it, and then dropping it — it's not great.
82
83/// Get the number of items in the list
84///
85/// # Safety
86///
87/// The `list` parameter must point to aligned, initialized memory of the correct type.
88pub type ListLenFn = unsafe fn(list: PtrConst) -> usize;
89
90/// Get pointer to the element at `index` in the list, or `None` if the
91/// index is out of bounds.
92///
93/// # Safety
94///
95/// The `list` parameter must point to aligned, initialized memory of the correct type.
96pub type ListGetFn = unsafe fn(list: PtrConst, index: usize) -> Option<PtrConst>;
97
98/// Get mutable pointer to the element at `index` in the list, or `None` if the
99/// index is out of bounds.
100///
101/// # Safety
102///
103/// The `list` parameter must point to aligned, initialized memory of the correct type.
104pub type ListGetMutFn = unsafe fn(list: PtrMut, index: usize) -> Option<PtrMut>;
105
106/// Get pointer to the data buffer of the list.
107///
108/// # Safety
109///
110/// The `list` parameter must point to aligned, initialized memory of the correct type.
111pub type ListAsPtrFn = unsafe fn(list: PtrConst) -> PtrConst;
112
113/// Get mutable pointer to the data buffer of the list.
114///
115/// # Safety
116///
117/// The `list` parameter must point to aligned, initialized memory of the correct type.
118pub type ListAsMutPtrFn = unsafe fn(list: PtrMut) -> PtrMut;
119
120/// Virtual table for a list-like type (like `Vec<T>`)
121#[derive(Clone, Copy, Debug)]
122#[repr(C)]
123pub struct ListVTable {
124    /// cf. [`ListInitInPlaceWithCapacityFn`].
125    /// Unbuildable lists exist, like arrays.
126    pub init_in_place_with_capacity: Option<ListInitInPlaceWithCapacityFn>,
127
128    /// cf. [`ListPushFn`]
129    /// Only available for mutable lists
130    pub push: Option<ListPushFn>,
131
132    /// cf. [`ListLenFn`]
133    pub len: ListLenFn,
134
135    /// cf. [`ListGetFn`]
136    pub get: ListGetFn,
137
138    /// cf. [`ListGetMutFn`]
139    /// Only available for mutable lists
140    pub get_mut: Option<ListGetMutFn>,
141
142    /// cf. [`ListAsPtrFn`]
143    /// Only available for types that can be accessed as a contiguous array
144    pub as_ptr: Option<ListAsPtrFn>,
145
146    /// cf. [`ListAsMutPtrFn`]
147    /// Only available for types that can be accessed as a contiguous array
148    pub as_mut_ptr: Option<ListAsMutPtrFn>,
149
150    /// Virtual table for list iterator operations
151    pub iter_vtable: IterVTable<PtrConst<'static>>,
152}
153
154impl ListVTable {
155    /// Returns a builder for ListVTable
156    pub const fn builder() -> ListVTableBuilder {
157        ListVTableBuilder::new()
158    }
159}
160
161/// Builds a [`ListVTable`]
162pub struct ListVTableBuilder {
163    init_in_place_with_capacity: Option<ListInitInPlaceWithCapacityFn>,
164    push: Option<ListPushFn>,
165    len: Option<ListLenFn>,
166    get: Option<ListGetFn>,
167    get_mut: Option<ListGetMutFn>,
168    as_ptr: Option<ListAsPtrFn>,
169    as_mut_ptr: Option<ListAsMutPtrFn>,
170    iter_vtable: Option<IterVTable<PtrConst<'static>>>,
171}
172
173impl ListVTableBuilder {
174    /// Creates a new [`ListVTableBuilder`] with all fields set to `None`.
175    #[allow(clippy::new_without_default)]
176    pub const fn new() -> Self {
177        Self {
178            init_in_place_with_capacity: None,
179            push: None,
180            len: None,
181            get: None,
182            get_mut: None,
183            as_ptr: None,
184            as_mut_ptr: None,
185            iter_vtable: None,
186        }
187    }
188
189    /// Sets the init_in_place_with_capacity field
190    pub const fn init_in_place_with_capacity(mut self, f: ListInitInPlaceWithCapacityFn) -> Self {
191        self.init_in_place_with_capacity = Some(f);
192        self
193    }
194
195    /// Sets the push field
196    pub const fn push(mut self, f: ListPushFn) -> Self {
197        self.push = Some(f);
198        self
199    }
200
201    /// Sets the len field
202    pub const fn len(mut self, f: ListLenFn) -> Self {
203        self.len = Some(f);
204        self
205    }
206
207    /// Sets the get field
208    pub const fn get(mut self, f: ListGetFn) -> Self {
209        self.get = Some(f);
210        self
211    }
212
213    /// Sets the get_mut field
214    pub const fn get_mut(mut self, f: ListGetMutFn) -> Self {
215        self.get_mut = Some(f);
216        self
217    }
218
219    /// Sets the as_ptr field
220    pub const fn as_ptr(mut self, f: ListAsPtrFn) -> Self {
221        self.as_ptr = Some(f);
222        self
223    }
224
225    /// Sets the as_mut_ptr field
226    pub const fn as_mut_ptr(mut self, f: ListAsMutPtrFn) -> Self {
227        self.as_mut_ptr = Some(f);
228        self
229    }
230
231    /// Sets the iter_vtable field
232    pub const fn iter_vtable(mut self, vtable: IterVTable<PtrConst<'static>>) -> Self {
233        self.iter_vtable = Some(vtable);
234        self
235    }
236
237    /// Builds the [`ListVTable`] from the current state of the builder.
238    ///
239    /// # Panics
240    ///
241    /// Panic if any of the required fields (len, get, as_ptr, iter_vtable) are `None`.
242    pub const fn build(self) -> ListVTable {
243        assert!(self.as_ptr.is_some());
244        ListVTable {
245            init_in_place_with_capacity: self.init_in_place_with_capacity,
246            push: self.push,
247            len: self.len.unwrap(),
248            get: self.get.unwrap(),
249            get_mut: self.get_mut,
250            as_ptr: self.as_ptr,
251            as_mut_ptr: self.as_mut_ptr,
252            iter_vtable: self.iter_vtable.unwrap(),
253        }
254    }
255}