facet_core/impls_core/
slice.rs

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