facet_core/impls_core/slice.rs
1use crate::*;
2
3unsafe impl<'a, T> Facet<'a> for &'a [T]
4where
5 T: Facet<'a>,
6{
7 const SHAPE: &'static Shape = &const {
8 Shape::builder_for_sized::<Self>()
9 .type_params(&[
10 TypeParam {
11 name: "T",
12 shape: || T::SHAPE,
13 }
14 ])
15 .def(Def::Slice(
16 SliceDef::builder()
17 .vtable(
18 &const {
19 SliceVTable::builder()
20 .len(|ptr| unsafe {
21 let slice = ptr.get::<&[T]>();
22 slice.len()
23 })
24 .get_item_ptr(|ptr, index| unsafe {
25 let slice = ptr.get::<&[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 PtrConst::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::<Self>()
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.put(&[]) })
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.put(src)
58 });
59
60 if T::SHAPE.vtable.debug.is_some() {
61 builder = builder.debug(|value, f| {
62 write!(f, "[")?;
63 for (i, item) in value.iter().enumerate() {
64 if i > 0 {
65 write!(f, ", ")?;
66 }
67 (<VTableView<T>>::of().debug().unwrap())(
68 item,
69 f,
70 )?;
71 }
72 write!(f, "]")
73 });
74 }
75
76 if T::SHAPE.vtable.eq.is_some() {
77 builder = builder.eq(|a, b| {
78 if a.len() != b.len() {
79 return false;
80 }
81 for (x, y) in a.iter().zip(b.iter()) {
82 if !
83 (<VTableView<T>>::of().eq().unwrap())(
84 x,
85 y,
86 )
87 {
88 return false;
89 }
90 }
91 true
92 });
93 }
94
95 if T::SHAPE.vtable.ord.is_some() {
96 builder = builder.ord(|a, b| {
97 for (x, y) in a.iter().zip(b.iter()) {
98 let ord = (<VTableView<T>>::of().ord().unwrap())(
99 x,
100 y,
101 );
102 if ord != core::cmp::Ordering::Equal {
103 return ord;
104 }
105 }
106 a.len().cmp(&b.len())
107 });
108 }
109
110 if T::SHAPE.vtable.partial_ord.is_some() {
111 builder = builder.partial_ord(|a, b| {
112 for (x, y) in a.iter().zip(b.iter()) {
113 let ord = (<VTableView<T>>::of().partial_ord().unwrap())(
114 x,
115 y,
116 );
117 match ord {
118 Some(core::cmp::Ordering::Equal) => continue,
119 Some(order) => return Some(order),
120 None => return None,
121 }
122 }
123 a.len().partial_cmp(&b.len())
124 });
125 }
126
127 if T::SHAPE.vtable.hash.is_some() {
128 builder = builder.hash(|value, state, hasher| {
129 for item in value.iter() {
130 (<VTableView<T>>::of().hash().unwrap())(
131 item,
132 state,
133 hasher,
134 );
135 }
136 });
137 }
138
139 builder.build()
140 },
141 )
142 .build()
143 };
144}