facet_trait/impls/
slice_impl.rs

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