1use crate::error::{CoerceError, CoerceErrorKind};
2use crate::pointer::Size;
3
4mod sealed {
5 pub trait Sealed<U: ?Sized> {}
6}
7
8pub trait CoerceSlice<U>
15where
16 Self: self::sealed::Sealed<U>,
17 U: ?Sized,
18{
19 #[doc(hidden)]
21 fn resize<O>(factor: O) -> O
22 where
23 O: Size;
24
25 #[doc(hidden)]
27 fn try_resize<O>(factor: O) -> Result<O, CoerceError>
28 where
29 O: Size;
30}
31
32macro_rules! self_impl_inner {
33 ($from:ty, {$($to:ty),*}) => {
34 $(
35 impl self::sealed::Sealed<[$to]> for [$from] {}
36
37 #[doc = concat!("Defines the coercion from `[", stringify!($from) ,"]` to `[", stringify!($to), "]`.")]
38 #[doc = concat!("let reference: Ref<", stringify!($from), "> = Ref::zero();")]
45 #[doc = concat!("let reference2 = reference.coerce::<[", stringify!($from), "]>();")]
46 #[doc = concat!("let reference3 = reference.coerce::<", stringify!($to), ">();")]
49 #[doc = concat!("let reference4 = reference2.coerce::<[", stringify!($to), "]>();")]
50 impl CoerceSlice<[$to]> for [$from] {
53 #[inline]
54 fn resize<O: Size>(len: O) -> O {
55 len
56 }
57
58 #[inline]
59 fn try_resize<O: Size>(len: O) -> Result<O, CoerceError> {
60 Ok(len)
61 }
62 }
63 )*
64 }
65}
66
67macro_rules! self_impl {
68 ([$({$($from:ty),*}),*], [$($to:tt),*]) => {
69 $(
70 $(
71 self_impl_inner!($from, $to);
72 )*
73 )*
74 };
75}
76
77macro_rules! coerce_slice_inner {
78 ($factor:ident, $value:literal, $from:ty, {$($to:ty),*}) => {
79 $(
80 impl self::sealed::Sealed<[$to]> for [$from] {}
81
82 #[doc = concat!("Defines the coercion from `[", stringify!($from) ,"]` to `[", stringify!($to), "]`.")]
83 #[doc = concat!("let reference: Ref<", stringify!($from), "> = Ref::zero();")]
90 #[doc = concat!("let reference2 = reference.coerce::<[", stringify!($to), "]>();")]
91 #[doc = concat!("assert_eq!(reference2.len(), ", stringify!($value), ");")]
92 #[doc = concat!("let reference: Ref<[", stringify!($from), "]> = Ref::with_metadata(0u32, 5);")]
94 #[doc = concat!("let reference2 = reference.coerce::<[", stringify!($to), "]>();")]
95 #[doc = concat!("assert_eq!(reference2.len(), 5 * ", stringify!($value), ");")]
96 impl CoerceSlice<[$to]> for [$from] {
98 #[inline]
99 fn resize<O>(len: O) -> O
100 where
101 O: Size,
102 {
103 len.wrapping_mul(O::$factor)
104 }
105
106 #[inline]
107 fn try_resize<O>(len: O) -> Result<O, CoerceError>
108 where
109 O: Size,
110 {
111 let Some(len) = len.checked_mul(O::$factor) else {
112 return Err(CoerceError::new(CoerceErrorKind::SliceLengthOverflow {
113 item: len.as_usize(),
114 len: O::$factor.as_usize(),
115 }));
116 };
117
118 Ok(len)
119 }
120 }
121 )*
122 }
123}
124
125macro_rules! coerce_slice {
126 ($factor:ident, $value:literal, [$({$($from:ty),*}),*], [$($to:tt),*]) => {
127 $(
128 $(
129 coerce_slice_inner!($factor, $value, $from, $to);
130 )*
131 )*
132 }
133}
134
135self_impl! {
136 [
137 {u8, i8},
138 {u16, i16},
139 {u32, i32},
140 {u64, i64},
141 {u128, i128}
142 ],
143 [
144 {u8, i8},
145 {u16, i16, [u8; 2], [i8; 2]},
146 {u32, i32, [u16; 2], [i16; 2], [u8; 4], [i8; 4]},
147 {u64, i64, [u32; 2], [i32; 2], [u16; 4], [i16; 4], [u8; 8], [i8; 8]},
148 {u128, i128, [u64; 2], [i64; 2], [u32; 4], [i32; 4], [u16; 8], [i16; 8], [u8; 16], [i8; 16]}
149 ]
150}
151
152coerce_slice! {
153 N2, 2,
154 [
155 {u16, i16},
156 {u32, i32},
157 {u64, i64},
158 {u128, i128}
159 ],
160 [
161 {u8, i8},
162 {u16, i16, [u8; 2], [i8; 2]},
163 {u32, i32, [u16; 2], [i16; 2], [u8; 4], [i8; 4]},
164 {u64, i64, [u32; 2], [i32; 2], [u16; 4], [i16; 4], [u8; 8], [i8; 8]}
165 ]
166}
167
168coerce_slice! {
169 N4, 4,
170 [
171 {u32, i32},
172 {u64, i64},
173 {u128, i128}
174 ],
175 [
176 {u8, i8},
177 {u16, i16, [u8; 2], [i8; 2]},
178 {u32, i32, [u16; 2], [i16; 2], [u8; 4], [i8; 4]}
179 ]
180}
181
182coerce_slice! {
183 N8, 8,
184 [
185 {u64, i64},
186 {u128, i128}
187 ],
188 [
189 {u8, i8},
190 {u16, i16, [u8; 2], [i8; 2]}
191 ]
192}
193
194coerce_slice! {
195 N16, 16,
196 [
197 {u128, i128}
198 ],
199 [
200 {u8, i8}
201 ]
202}