1use super::Poke;
2use core::{fmt::Debug, marker::PhantomData, mem::ManuallyDrop, ptr::NonNull};
3use facet_core::{FieldError, ListDef, PtrMut, PtrUninit, Shape};
4
5use crate::{Guard, HeapValue, ReflectError, ReflectErrorKind};
6
7pub struct PokeListIter<'mem, 'facet> {
13 data: PtrMut,
14 stride: usize,
15 index: usize,
16 len: usize,
17 elem_shape: &'static Shape,
18 _list: PhantomData<Poke<'mem, 'facet>>,
19}
20
21impl<'mem, 'facet> Iterator for PokeListIter<'mem, 'facet> {
22 type Item = Poke<'mem, 'facet>;
23
24 #[inline]
25 fn next(&mut self) -> Option<Self::Item> {
26 if self.index >= self.len {
27 return None;
28 }
29 let item_ptr = unsafe { self.data.field(self.stride * self.index) };
30 self.index += 1;
31 Some(unsafe { Poke::from_raw_parts(item_ptr, self.elem_shape) })
32 }
33
34 #[inline]
35 fn size_hint(&self) -> (usize, Option<usize>) {
36 let remaining = self.len.saturating_sub(self.index);
37 (remaining, Some(remaining))
38 }
39}
40
41impl ExactSizeIterator for PokeListIter<'_, '_> {}
42
43pub struct PokeList<'mem, 'facet> {
45 value: Poke<'mem, 'facet>,
46 def: ListDef,
47}
48
49impl Debug for PokeList<'_, '_> {
50 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
51 f.debug_struct("PokeList").finish_non_exhaustive()
52 }
53}
54
55impl<'mem, 'facet> PokeList<'mem, 'facet> {
56 #[inline]
68 pub const unsafe fn new(value: Poke<'mem, 'facet>, def: ListDef) -> Self {
69 Self { value, def }
70 }
71
72 #[inline]
74 pub fn len(&self) -> usize {
75 unsafe { (self.def.vtable.len)(self.value.data()) }
76 }
77
78 #[inline]
80 pub fn is_empty(&self) -> bool {
81 self.len() == 0
82 }
83
84 #[inline]
86 pub fn get(&self, index: usize) -> Option<crate::Peek<'_, 'facet>> {
87 let item = unsafe { (self.def.vtable.get)(self.value.data(), index, self.value.shape())? };
88
89 Some(unsafe { crate::Peek::unchecked_new(item, self.def.t()) })
90 }
91
92 #[inline]
94 pub fn get_mut(&mut self, index: usize) -> Option<Poke<'_, 'facet>> {
95 let get_mut_fn = self.def.vtable.get_mut?;
96 let item = unsafe { get_mut_fn(self.value.data, index, self.value.shape())? };
97
98 Some(unsafe { Poke::from_raw_parts(item, self.def.t()) })
99 }
100
101 pub fn iter_mut(self) -> Result<PokeListIter<'mem, 'facet>, ReflectError> {
111 let elem_shape = self.def.t();
112 let stride = match elem_shape.layout {
113 facet_core::ShapeLayout::Sized(layout) => layout.size(),
114 facet_core::ShapeLayout::Unsized => {
115 return Err(self.value.err(ReflectErrorKind::OperationFailed {
116 shape: self.value.shape(),
117 operation: "iter_mut requires sized element type",
118 }));
119 }
120 };
121
122 let Some(as_mut_ptr_fn) = self.def.vtable.as_mut_ptr else {
123 return Err(self.value.err(ReflectErrorKind::OperationFailed {
124 shape: self.value.shape(),
125 operation:
126 "iter_mut requires a contiguous `as_mut_ptr` vtable entry; use `get_mut` per index",
127 }));
128 };
129
130 let data = unsafe { as_mut_ptr_fn(self.value.data) };
131 let len = self.len();
132 Ok(PokeListIter {
133 data,
134 stride,
135 index: 0,
136 len,
137 elem_shape,
138 _list: PhantomData,
139 })
140 }
141
142 pub fn push<T: facet_core::Facet<'facet>>(&mut self, value: T) -> Result<(), ReflectError> {
148 if self.def.t() != T::SHAPE {
149 return Err(self.value.err(ReflectErrorKind::WrongShape {
150 expected: self.def.t(),
151 actual: T::SHAPE,
152 }));
153 }
154 let push_fn = self.push_fn()?;
155 let mut value = ManuallyDrop::new(value);
156 unsafe {
157 let item_ptr = PtrMut::new(&mut value as *mut ManuallyDrop<T> as *mut u8);
158 push_fn(self.value.data_mut(), item_ptr);
159 }
160 Ok(())
161 }
162
163 pub fn push_from_heap<const BORROW: bool>(
168 &mut self,
169 value: HeapValue<'facet, BORROW>,
170 ) -> Result<(), ReflectError> {
171 if self.def.t() != value.shape() {
172 return Err(self.value.err(ReflectErrorKind::WrongShape {
173 expected: self.def.t(),
174 actual: value.shape(),
175 }));
176 }
177 let push_fn = self.push_fn()?;
178 let mut value = value;
179 let guard = value
180 .guard
181 .take()
182 .expect("HeapValue guard was already taken");
183 unsafe {
184 let item_ptr = PtrMut::new(guard.ptr.as_ptr());
185 push_fn(self.value.data_mut(), item_ptr);
186 }
187 drop(guard);
188 Ok(())
189 }
190
191 pub fn pop(&mut self) -> Result<Option<HeapValue<'facet, true>>, ReflectError> {
196 let pop_fn = self.def.pop().ok_or_else(|| {
197 self.value.err(ReflectErrorKind::OperationFailed {
198 shape: self.value.shape(),
199 operation: "pop: list type does not support pop",
200 })
201 })?;
202 let elem_shape = self.def.t();
203 let layout = elem_shape.layout.sized_layout().map_err(|_| {
204 self.value.err(ReflectErrorKind::Unsized {
205 shape: elem_shape,
206 operation: "pop",
207 })
208 })?;
209 let ptr = if layout.size() == 0 {
210 NonNull::<u8>::dangling()
211 } else {
212 let raw = unsafe { alloc::alloc::alloc(layout) };
213 match NonNull::new(raw) {
214 Some(p) => p,
215 None => alloc::alloc::handle_alloc_error(layout),
216 }
217 };
218 let out = PtrUninit::new(ptr.as_ptr());
219 let popped = unsafe { pop_fn(self.value.data_mut(), out) };
220 if !popped {
221 if layout.size() != 0 {
222 unsafe { alloc::alloc::dealloc(ptr.as_ptr(), layout) };
223 }
224 return Ok(None);
225 }
226 Ok(Some(HeapValue {
227 guard: Some(Guard {
228 ptr,
229 layout,
230 should_dealloc: layout.size() != 0,
231 }),
232 shape: elem_shape,
233 phantom: PhantomData,
234 }))
235 }
236
237 pub fn swap(&mut self, a: usize, b: usize) -> Result<(), ReflectError> {
243 let swap_fn = self.def.vtable.swap.ok_or_else(|| {
244 self.value.err(ReflectErrorKind::OperationFailed {
245 shape: self.value.shape(),
246 operation: "swap: list type does not support swap",
247 })
248 })?;
249 let len = self.len();
250 let ok = unsafe { swap_fn(self.value.data_mut(), a, b, self.value.shape()) };
251 if !ok {
252 let out_of_bounds = if a >= len { a } else { b };
253 return Err(self.value.err(ReflectErrorKind::FieldError {
254 shape: self.value.shape(),
255 field_error: FieldError::IndexOutOfBounds {
256 index: out_of_bounds,
257 bound: len,
258 },
259 }));
260 }
261 Ok(())
262 }
263
264 #[inline]
266 fn push_fn(&self) -> Result<facet_core::ListPushFn, ReflectError> {
267 self.def.push().ok_or_else(|| {
268 self.value.err(ReflectErrorKind::OperationFailed {
269 shape: self.value.shape(),
270 operation: "push: list type does not support push",
271 })
272 })
273 }
274
275 #[inline]
277 pub const fn def(&self) -> ListDef {
278 self.def
279 }
280
281 #[inline]
283 pub fn into_inner(self) -> Poke<'mem, 'facet> {
284 self.value
285 }
286
287 #[inline]
289 pub fn as_peek_list(&self) -> crate::PeekList<'_, 'facet> {
290 unsafe { crate::PeekList::new(self.value.as_peek(), self.def) }
291 }
292}
293
294#[cfg(test)]
295mod tests {
296 use alloc::vec::Vec;
297
298 use super::*;
299
300 #[test]
301 fn poke_list_len() {
302 let mut v: Vec<i32> = alloc::vec![1, 2, 3, 4, 5];
303 let poke = Poke::new(&mut v);
304 let list = poke.into_list().unwrap();
305 assert_eq!(list.len(), 5);
306 }
307
308 #[test]
309 fn poke_list_get() {
310 let mut v: Vec<i32> = alloc::vec![10, 20, 30];
311 let poke = Poke::new(&mut v);
312 let list = poke.into_list().unwrap();
313
314 let item = list.get(1).unwrap();
315 assert_eq!(*item.get::<i32>().unwrap(), 20);
316 }
317
318 #[test]
319 fn poke_list_get_mut() {
320 let mut v: Vec<i32> = alloc::vec![10, 20, 30];
321 let poke = Poke::new(&mut v);
322 let mut list = poke.into_list().unwrap();
323
324 {
325 let mut item = list.get_mut(1).unwrap();
326 item.set(99i32).unwrap();
327 }
328
329 let item = list.get(1).unwrap();
331 assert_eq!(*item.get::<i32>().unwrap(), 99);
332 }
333
334 #[test]
335 fn poke_list_iter_mut() {
336 let mut v: Vec<i32> = alloc::vec![1, 2, 3];
337 let poke = Poke::new(&mut v);
338 let list = poke.into_list().unwrap();
339
340 let mut sum = 0;
341 for mut item in list.iter_mut().unwrap() {
342 let val = *item.get::<i32>().unwrap();
343 item.set(val * 10).unwrap();
344 sum += val;
345 }
346
347 assert_eq!(sum, 6);
348 assert_eq!(v, alloc::vec![10, 20, 30]);
349 }
350
351 #[test]
352 fn poke_list_push_pop() {
353 let mut v: Vec<i32> = alloc::vec![];
354 {
355 let poke = Poke::new(&mut v);
356 let mut list = poke.into_list().unwrap();
357 list.push(1i32).unwrap();
358 list.push(2i32).unwrap();
359 list.push(3i32).unwrap();
360 }
361 assert_eq!(v, alloc::vec![1, 2, 3]);
362
363 {
364 let poke = Poke::new(&mut v);
365 let mut list = poke.into_list().unwrap();
366 let popped = list.pop().unwrap().unwrap();
367 assert_eq!(popped.materialize::<i32>().unwrap(), 3);
368 }
369 assert_eq!(v, alloc::vec![1, 2]);
370 }
371
372 #[test]
373 fn poke_list_pop_empty_returns_none() {
374 let mut v: Vec<i32> = alloc::vec![];
375 let poke = Poke::new(&mut v);
376 let mut list = poke.into_list().unwrap();
377 let popped = list.pop().unwrap();
378 assert!(popped.is_none());
379 }
380
381 #[test]
382 fn poke_list_push_wrong_shape_fails() {
383 let mut v: Vec<i32> = alloc::vec![];
384 let poke = Poke::new(&mut v);
385 let mut list = poke.into_list().unwrap();
386 let res = list.push(7u32);
387 assert!(matches!(
388 res,
389 Err(ref err) if matches!(err.kind, ReflectErrorKind::WrongShape { .. })
390 ));
391 }
392
393 #[test]
394 fn poke_list_push_from_heap() {
395 let mut v: Vec<i32> = alloc::vec![];
396 let poke = Poke::new(&mut v);
397 let mut list = poke.into_list().unwrap();
398
399 let hv = crate::Partial::alloc::<i32>()
400 .unwrap()
401 .set(42i32)
402 .unwrap()
403 .build()
404 .unwrap();
405 list.push_from_heap(hv).unwrap();
406 assert_eq!(v, alloc::vec![42]);
407 }
408
409 #[test]
410 fn poke_list_pop_string() {
411 let mut v: Vec<alloc::string::String> = alloc::vec![
412 alloc::string::String::from("a"),
413 alloc::string::String::from("b"),
414 ];
415 let poke = Poke::new(&mut v);
416 let mut list = poke.into_list().unwrap();
417 let popped = list.pop().unwrap().unwrap();
418 assert_eq!(popped.materialize::<alloc::string::String>().unwrap(), "b");
419 assert_eq!(v, alloc::vec![alloc::string::String::from("a")]);
420 }
421
422 #[test]
423 fn poke_list_swap() {
424 let mut v: Vec<i32> = alloc::vec![1, 2, 3];
425 let poke = Poke::new(&mut v);
426 let mut list = poke.into_list().unwrap();
427 list.swap(0, 2).unwrap();
428 assert_eq!(v, alloc::vec![3, 2, 1]);
429 }
430
431 #[test]
432 fn poke_list_swap_self_is_noop() {
433 let mut v: Vec<i32> = alloc::vec![1, 2, 3];
434 let poke = Poke::new(&mut v);
435 let mut list = poke.into_list().unwrap();
436 list.swap(1, 1).unwrap();
437 assert_eq!(v, alloc::vec![1, 2, 3]);
438 }
439
440 #[test]
441 fn poke_list_swap_out_of_bounds_fails() {
442 let mut v: Vec<i32> = alloc::vec![1, 2, 3];
443 let poke = Poke::new(&mut v);
444 let mut list = poke.into_list().unwrap();
445 let res = list.swap(0, 10);
446 assert!(matches!(
447 res,
448 Err(ref err) if matches!(err.kind, ReflectErrorKind::FieldError { .. })
449 ));
450 }
451}