facet_core/impls_core/
slice.rs

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