facet_core/impls_core/
slice.rs

1use crate::*;
2
3unsafe impl<'a, T> Facet<'a> for [T]
4where
5    T: Facet<'a>,
6{
7    const VTABLE: &'static ValueVTable = &const {
8        let mut builder = ValueVTable::builder::<&Self>()
9            .type_name(|f, opts| {
10                if let Some(opts) = opts.for_children() {
11                    write!(f, "[")?;
12                    (T::SHAPE.vtable.type_name)(f, opts)?;
13                    write!(f, "]")
14                } else {
15                    write!(f, "[⋯]")
16                }
17            })
18            .marker_traits(T::SHAPE.vtable.marker_traits)
19            .default_in_place(|ptr| unsafe { ptr.put(&[]) })
20            .clone_into(|src, dst| unsafe {
21                // This works because we're cloning a shared reference (&[T]), not the actual slice data.
22                // We're just copying the fat pointer (ptr + length) that makes up the slice reference.
23                dst.put(src)
24            });
25
26        if T::SHAPE.vtable.debug.is_some() {
27            builder = builder.debug(|value, f| {
28                write!(f, "[")?;
29                for (i, item) in value.iter().enumerate() {
30                    if i > 0 {
31                        write!(f, ", ")?;
32                    }
33                    (<VTableView<T>>::of().debug().unwrap())(item, f)?;
34                }
35                write!(f, "]")
36            });
37        }
38
39        if T::SHAPE.vtable.eq.is_some() {
40            builder = builder.eq(|a, b| {
41                if a.len() != b.len() {
42                    return false;
43                }
44                for (x, y) in a.iter().zip(b.iter()) {
45                    if !(<VTableView<T>>::of().eq().unwrap())(x, y) {
46                        return false;
47                    }
48                }
49                true
50            });
51        }
52
53        if T::SHAPE.vtable.ord.is_some() {
54            builder = builder.ord(|a, b| {
55                for (x, y) in a.iter().zip(b.iter()) {
56                    let ord = (<VTableView<T>>::of().ord().unwrap())(x, y);
57                    if ord != core::cmp::Ordering::Equal {
58                        return ord;
59                    }
60                }
61                a.len().cmp(&b.len())
62            });
63        }
64
65        if T::SHAPE.vtable.partial_ord.is_some() {
66            builder = builder.partial_ord(|a, b| {
67                for (x, y) in a.iter().zip(b.iter()) {
68                    let ord = (<VTableView<T>>::of().partial_ord().unwrap())(x, y);
69                    match ord {
70                        Some(core::cmp::Ordering::Equal) => continue,
71                        Some(order) => return Some(order),
72                        None => return None,
73                    }
74                }
75                a.len().partial_cmp(&b.len())
76            });
77        }
78
79        if T::SHAPE.vtable.hash.is_some() {
80            builder = builder.hash(|value, state, hasher| {
81                for item in value.iter() {
82                    (<VTableView<T>>::of().hash().unwrap())(item, state, hasher);
83                }
84            });
85        }
86
87        builder.build()
88    };
89
90    const SHAPE: &'static Shape<'static> = &const {
91        Shape::builder_for_unsized::<Self>()
92            .type_params(&[TypeParam {
93                name: "T",
94                shape: || T::SHAPE,
95            }])
96            .ty(Type::Sequence(SequenceType::Slice(SliceType {
97                t: T::SHAPE,
98            })))
99            .def(Def::Slice(
100                SliceDef::builder()
101                    .vtable(
102                        &const {
103                            SliceVTable::builder()
104                                .len(|ptr| unsafe {
105                                    let slice = ptr.get::<&[T]>();
106                                    slice.len()
107                                })
108                                .as_ptr(|ptr| unsafe {
109                                    let slice = ptr.get::<&[T]>();
110                                    PtrConst::new(slice.as_ptr())
111                                })
112                                .as_mut_ptr(|ptr| unsafe {
113                                    let slice = ptr.as_mut::<&mut [T]>();
114                                    PtrMut::new(slice.as_mut_ptr())
115                                })
116                                .build()
117                        },
118                    )
119                    .t(T::SHAPE)
120                    .build(),
121            ))
122            .build()
123    };
124}