facet_reflect/peek/
list.rs1use super::Peek;
2use core::{fmt::Debug, marker::PhantomData};
3use facet_core::{ListDef, PtrConst, PtrMut};
4
5pub struct PeekListIter<'mem, 'facet, 'shape> {
7 state: PeekListIterState<'mem>,
8 index: usize,
9 len: usize,
10 def: ListDef<'shape>,
11 _list: PhantomData<Peek<'mem, 'facet, 'shape>>,
12}
13
14impl<'mem, 'facet, 'shape> Iterator for PeekListIter<'mem, 'facet, 'shape> {
15 type Item = Peek<'mem, 'facet, 'shape>;
16
17 fn next(&mut self) -> Option<Self::Item> {
18 let item_ptr = match self.state {
19 PeekListIterState::Ptr { data, stride } => {
20 if self.index >= self.len {
21 return None;
22 }
23
24 unsafe { data.field(stride * self.index) }
25 }
26 PeekListIterState::Iter { iter } => unsafe {
27 (self.def.vtable.iter_vtable.next)(iter)?
28 },
29 };
30
31 self.index += 1;
34
35 Some(unsafe { Peek::unchecked_new(item_ptr, self.def.t()) })
36 }
37
38 fn size_hint(&self) -> (usize, Option<usize>) {
39 let remaining = self.len.saturating_sub(self.index);
40 (remaining, Some(remaining))
41 }
42}
43
44impl ExactSizeIterator for PeekListIter<'_, '_, '_> {}
45
46impl Drop for PeekListIter<'_, '_, '_> {
47 fn drop(&mut self) {
48 match self.state {
49 PeekListIterState::Iter { iter } => unsafe {
50 (self.def.vtable.iter_vtable.dealloc)(iter)
51 },
52 PeekListIterState::Ptr { .. } => {
53 }
55 }
56 }
57}
58
59impl<'mem, 'facet, 'shape> IntoIterator for &'mem PeekList<'mem, 'facet, 'shape> {
60 type Item = Peek<'mem, 'facet, 'shape>;
61 type IntoIter = PeekListIter<'mem, 'facet, 'shape>;
62
63 fn into_iter(self) -> Self::IntoIter {
64 self.iter()
65 }
66}
67
68enum PeekListIterState<'mem> {
69 Ptr { data: PtrConst<'mem>, stride: usize },
70 Iter { iter: PtrMut<'mem> },
71}
72
73#[derive(Clone, Copy)]
75pub struct PeekList<'mem, 'facet, 'shape> {
76 pub(crate) value: Peek<'mem, 'facet, 'shape>,
77 pub(crate) def: ListDef<'shape>,
78}
79
80impl Debug for PeekList<'_, '_, '_> {
81 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
82 f.debug_struct("PeekList").finish_non_exhaustive()
83 }
84}
85
86impl<'mem, 'facet, 'shape> PeekList<'mem, 'facet, 'shape> {
87 pub fn new(value: Peek<'mem, 'facet, 'shape>, def: ListDef<'shape>) -> Self {
89 Self { value, def }
90 }
91
92 pub fn len(&self) -> usize {
94 unsafe { (self.def.vtable.len)(self.value.data()) }
95 }
96
97 pub fn is_empty(&self) -> bool {
99 self.len() == 0
100 }
101
102 pub fn get(&self, index: usize) -> Option<Peek<'mem, 'facet, 'shape>> {
104 let item = unsafe { (self.def.vtable.get)(self.value.data(), index)? };
105
106 Some(unsafe { Peek::unchecked_new(item, self.def.t()) })
107 }
108
109 pub fn iter(self) -> PeekListIter<'mem, 'facet, 'shape> {
111 let state = if let Some(as_ptr_fn) = self.def.vtable.as_ptr {
112 let data = unsafe { as_ptr_fn(self.value.data()) };
113 let layout = self
114 .def
115 .t()
116 .layout
117 .sized_layout()
118 .expect("can only iterate over sized list elements");
119 let stride = layout.size();
120
121 PeekListIterState::Ptr { data, stride }
122 } else {
123 let iter = unsafe {
124 (self.def.vtable.iter_vtable.init_with_value.unwrap())(self.value.data())
125 };
126 PeekListIterState::Iter { iter }
127 };
128
129 PeekListIter {
130 state,
131 index: 0,
132 len: self.len(),
133 def: self.def(),
134 _list: PhantomData,
135 }
136 }
137
138 pub fn def(&self) -> ListDef<'shape> {
140 self.def
141 }
142}