facet_trait/impls/
slice_impl.rs

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