facet_reflect/peek/
list_like.rs1use facet_core::{PtrConst, Shape, ShapeLayout};
2
3use super::Peek;
4use core::fmt::Debug;
5
6#[derive(Clone, Copy)]
8pub enum ListLikeDef {
9 List(facet_core::ListDef),
13
14 Array(facet_core::ArrayDef),
18
19 Slice(facet_core::SliceDef),
23}
24
25impl ListLikeDef {
26 pub fn t(&self) -> &'static Shape {
28 match self {
29 ListLikeDef::List(v) => v.t(),
30 ListLikeDef::Array(v) => v.t(),
31 ListLikeDef::Slice(v) => v.t(),
32 }
33 }
34}
35
36pub struct PeekListLikeIter<'mem, 'facet_lifetime> {
38 list: PeekListLike<'mem, 'facet_lifetime>,
39 index: usize,
40 len: usize,
41}
42
43impl<'mem, 'facet_lifetime> Iterator for PeekListLikeIter<'mem, 'facet_lifetime> {
44 type Item = Peek<'mem, 'facet_lifetime>;
45
46 fn next(&mut self) -> Option<Self::Item> {
47 if self.index >= self.len {
48 return None;
49 }
50 let item = self.list.get(self.index);
51 self.index += 1;
52 item
53 }
54
55 fn size_hint(&self) -> (usize, Option<usize>) {
56 let remaining = self.len.saturating_sub(self.index);
57 (remaining, Some(remaining))
58 }
59}
60
61impl ExactSizeIterator for PeekListLikeIter<'_, '_> {}
62
63impl<'mem, 'facet_lifetime> IntoIterator for &'mem PeekListLike<'mem, 'facet_lifetime> {
64 type Item = Peek<'mem, 'facet_lifetime>;
65 type IntoIter = PeekListLikeIter<'mem, 'facet_lifetime>;
66
67 fn into_iter(self) -> Self::IntoIter {
68 self.iter()
69 }
70}
71
72#[derive(Clone, Copy)]
74pub struct PeekListLike<'mem, 'facet_lifetime> {
75 pub(crate) value: Peek<'mem, 'facet_lifetime>,
76 pub(crate) def: ListLikeDef,
77 len: usize,
78 as_ptr: unsafe fn(this: PtrConst) -> PtrConst,
79}
80
81impl Debug for PeekListLike<'_, '_> {
82 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
83 f.debug_struct("PeekListLike").finish_non_exhaustive()
84 }
85}
86
87impl<'mem, 'facet_lifetime> PeekListLike<'mem, 'facet_lifetime> {
88 pub fn new(value: Peek<'mem, 'facet_lifetime>, def: ListLikeDef) -> Self {
90 let (len, as_ptr_fn) = match def {
91 ListLikeDef::List(v) => (unsafe { (v.vtable.len)(value.data()) }, v.vtable.as_ptr),
92 ListLikeDef::Slice(v) => (unsafe { (v.vtable.len)(value.data()) }, v.vtable.as_ptr),
93 ListLikeDef::Array(v) => (v.n, v.vtable.as_ptr),
94 };
95 Self {
96 value,
97 def,
98 len,
99 as_ptr: as_ptr_fn,
100 }
101 }
102
103 pub fn len(&self) -> usize {
105 self.len
106 }
107
108 pub fn is_empty(&self) -> bool {
110 self.len() == 0
111 }
112
113 pub fn get(&self, index: usize) -> Option<Peek<'mem, 'facet_lifetime>> {
119 if index >= self.len() {
120 return None;
121 }
122
123 let base_ptr = unsafe { (self.as_ptr)(self.value.data()) };
125
126 let elem_layout = match self.def.t().layout {
128 ShapeLayout::Sized(layout) => layout,
129 ShapeLayout::Unsized => return None, };
131
132 let offset = index * elem_layout.size();
134
135 let item_ptr = unsafe { base_ptr.field(offset) };
137
138 Some(unsafe { Peek::unchecked_new(item_ptr, self.def.t()) })
139 }
140
141 pub fn iter(self) -> PeekListLikeIter<'mem, 'facet_lifetime> {
143 PeekListLikeIter {
144 list: self,
145 index: 0,
146 len: self.len(),
147 }
148 }
149
150 pub fn def(&self) -> ListLikeDef {
152 self.def
153 }
154}