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