facet_core/_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 SHAPE: &'static Shape = &const {
9        Shape::builder()
10            .layout(Layout::new::<&[T]>())
11            .def(Def::List(
12                ListDef::builder()
13                    .vtable(
14                        &const {
15                            ListVTable::builder()
16                        .init_in_place_with_capacity(|_, _| Err(()))
17                        .push(|_, _| {
18                            panic!("Cannot push to &[T]");
19                        })
20                        .len(|ptr| unsafe {
21                            let slice = ptr.as_ref::<&[T]>();
22                            slice.len()
23                        })
24                        .get_item_ptr(|ptr, index| unsafe {
25                            let slice = ptr.as_ref::<&[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                            OpaqueConst::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()
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.write(&[] as &[T]) })
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.write(src.as_ref::<&[T]>())
58                        });
59
60                    if T::SHAPE.vtable.debug.is_some() {
61                        builder = builder.debug(|value, f| {
62                            let value = unsafe { value.as_ref::<&[T]>() };
63                            write!(f, "[")?;
64                            for (i, item) in value.iter().enumerate() {
65                                if i > 0 {
66                                    write!(f, ", ")?;
67                                }
68                                unsafe {
69                                    (T::SHAPE.vtable.debug.unwrap_unchecked())(
70                                        OpaqueConst::new(item as *const _),
71                                        f,
72                                    )?;
73                                }
74                            }
75                            write!(f, "]")
76                        });
77                    }
78
79                    if T::SHAPE.vtable.eq.is_some() {
80                        builder = builder.eq(|a, b| {
81                            let a = unsafe { a.as_ref::<&[T]>() };
82                            let b = unsafe { b.as_ref::<&[T]>() };
83                            if a.len() != b.len() {
84                                return false;
85                            }
86                            for (x, y) in a.iter().zip(b.iter()) {
87                                if !unsafe {
88                                    (T::SHAPE.vtable.eq.unwrap_unchecked())(
89                                        OpaqueConst::new(x as *const _),
90                                        OpaqueConst::new(y as *const _),
91                                    )
92                                } {
93                                    return false;
94                                }
95                            }
96                            true
97                        });
98                    }
99
100                    if T::SHAPE.vtable.ord.is_some() {
101                        builder = builder.ord(|a, b| {
102                            let a = unsafe { a.as_ref::<&[T]>() };
103                            let b = unsafe { b.as_ref::<&[T]>() };
104                            for (x, y) in a.iter().zip(b.iter()) {
105                                let ord = unsafe {
106                                    (T::SHAPE.vtable.ord.unwrap_unchecked())(
107                                        OpaqueConst::new(x as *const _),
108                                        OpaqueConst::new(y as *const _),
109                                    )
110                                };
111                                if ord != core::cmp::Ordering::Equal {
112                                    return ord;
113                                }
114                            }
115                            a.len().cmp(&b.len())
116                        });
117                    }
118
119                    if T::SHAPE.vtable.partial_ord.is_some() {
120                        builder = builder.partial_ord(|a, b| {
121                            let a = unsafe { a.as_ref::<&[T]>() };
122                            let b = unsafe { b.as_ref::<&[T]>() };
123                            for (x, y) in a.iter().zip(b.iter()) {
124                                let ord = unsafe {
125                                    (T::SHAPE.vtable.partial_ord.unwrap_unchecked())(
126                                        OpaqueConst::new(x as *const _),
127                                        OpaqueConst::new(y as *const _),
128                                    )
129                                };
130                                match ord {
131                                    Some(core::cmp::Ordering::Equal) => continue,
132                                    Some(order) => return Some(order),
133                                    None => return None,
134                                }
135                            }
136                            a.len().partial_cmp(&b.len())
137                        });
138                    }
139
140                    if T::SHAPE.vtable.hash.is_some() {
141                        builder = builder.hash(|value, state, hasher| {
142                            let value = unsafe { value.as_ref::<&[T]>() };
143                            for item in value.iter() {
144                                unsafe {
145                                    (T::SHAPE.vtable.hash.unwrap_unchecked())(
146                                        OpaqueConst::new(item as *const _),
147                                        state,
148                                        hasher,
149                                    )
150                                };
151                            }
152                        });
153                    }
154
155                    builder.build()
156                },
157            )
158            .build()
159    };
160}