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}