musli_zerocopy/pointer/
coerce_slice.rs

1use crate::pointer::Size;
2
3mod sealed {
4    pub trait Sealed<U: ?Sized> {}
5}
6
7/// Trait to coerce slice metadata, which defines its length.
8///
9/// Coercing from one kind of slice to another means that the length must be
10/// adjusted. We can only perform upwards adjustments such as `[u32]` to `[u16]`
11/// since independent of the length of the slice we know that it defines a
12/// region of memory which is appropriately sized.
13pub trait CoerceSlice<U: ?Sized>: self::sealed::Sealed<U> {
14    /// Resize with the given `factor`.
15    #[doc(hidden)]
16    fn resize<O: Size>(factor: O) -> O;
17
18    /// Try to resize with the given `factor`.
19    #[doc(hidden)]
20    fn try_resize<O: Size>(factor: O) -> Option<O>;
21}
22
23macro_rules! self_impl_inner {
24    ($from:ty, {$($to:ty),*}) => {
25        $(
26            impl self::sealed::Sealed<[$to]> for [$from] {}
27
28            #[doc = concat!("Defines the coercion from `[", stringify!($from) ,"]` to `[", stringify!($to), "]`.")]
29            ///
30            /// # Examples
31            ///
32            /// ```
33            /// use musli_zerocopy::Ref;
34            ///
35            #[doc = concat!("let reference: Ref<", stringify!($from), "> = Ref::zero();")]
36            #[doc = concat!("let reference2 = reference.coerce::<[", stringify!($from), "]>();")]
37            /// assert_eq!(reference2.len(), 1);
38            ///
39            #[doc = concat!("let reference3 = reference.coerce::<", stringify!($to), ">();")]
40            #[doc = concat!("let reference4 = reference2.coerce::<[", stringify!($to), "]>();")]
41            /// assert_eq!(reference4.len(), 1);
42            /// ```
43            impl CoerceSlice<[$to]> for [$from] {
44                #[inline]
45                fn resize<O: Size>(len: O) -> O {
46                    len
47                }
48
49                #[inline]
50                fn try_resize<O: Size>(len: O) -> Option<O> {
51                    Some(len)
52                }
53            }
54        )*
55    }
56}
57
58macro_rules! self_impl {
59    ([$({$($from:ty),*}),*], [$($to:tt),*]) => {
60        $(
61            $(
62                self_impl_inner!($from, $to);
63            )*
64        )*
65    };
66}
67
68macro_rules! coerce_slice_inner {
69    ($factor:ident, $value:literal, $from:ty, {$($to:ty),*}) => {
70        $(
71            impl self::sealed::Sealed<[$to]> for [$from] {}
72
73            #[doc = concat!("Defines the coercion from `[", stringify!($from) ,"]` to `[", stringify!($to), "]`.")]
74            ///
75            /// # Examples
76            ///
77            /// ```
78            /// use musli_zerocopy::Ref;
79            ///
80            #[doc = concat!("let reference: Ref<", stringify!($from), "> = Ref::zero();")]
81            #[doc = concat!("let reference2 = reference.coerce::<[", stringify!($to), "]>();")]
82            #[doc = concat!("assert_eq!(reference2.len(), ", stringify!($value), ");")]
83            ///
84            #[doc = concat!("let reference: Ref<[", stringify!($from), "]> = Ref::with_metadata(0, 5);")]
85            #[doc = concat!("let reference2 = reference.coerce::<[", stringify!($to), "]>();")]
86            #[doc = concat!("assert_eq!(reference2.len(), 5 * ", stringify!($value), ");")]
87            /// ```
88            impl CoerceSlice<[$to]> for [$from] {
89                #[inline]
90                fn resize<O: Size>(len: O) -> O {
91                    len.wrapping_mul(O::$factor)
92                }
93
94                #[inline]
95                fn try_resize<O: Size>(len: O) -> Option<O> {
96                    len.checked_mul(O::$factor)
97                }
98            }
99        )*
100    }
101}
102
103macro_rules! coerce_slice {
104    ($factor:ident, $value:literal, [$({$($from:ty),*}),*], [$($to:tt),*]) => {
105        $(
106            $(
107                coerce_slice_inner!($factor, $value, $from, $to);
108            )*
109        )*
110    }
111}
112
113self_impl! {
114    [
115        {u8, i8},
116        {u16, i16},
117        {u32, i32},
118        {u64, i64},
119        {u128, i128}
120    ],
121    [
122        {u8, i8},
123        {u16, i16, [u8; 2], [i8; 2]},
124        {u32, i32, [u16; 2], [i16; 2], [u8; 4], [i8; 4]},
125        {u64, i64, [u32; 2], [i32; 2], [u16; 4], [i16; 4], [u8; 8], [i8; 8]},
126        {u128, i128, [u64; 2], [i64; 2], [u32; 4], [i32; 4], [u16; 8], [i16; 8], [u8; 16], [i8; 16]}
127    ]
128}
129
130coerce_slice! {
131    N2, 2,
132    [
133        {u16, i16},
134        {u32, i32},
135        {u64, i64},
136        {u128, i128}
137    ],
138    [
139        {u8, i8},
140        {u16, i16, [u8; 2], [i8; 2]},
141        {u32, i32, [u16; 2], [i16; 2], [u8; 4], [i8; 4]},
142        {u64, i64, [u32; 2], [i32; 2], [u16; 4], [i16; 4], [u8; 8], [i8; 8]}
143    ]
144}
145
146coerce_slice! {
147    N4, 4,
148    [
149        {u32, i32},
150        {u64, i64},
151        {u128, i128}
152    ],
153    [
154        {u8, i8},
155        {u16, i16, [u8; 2], [i8; 2]},
156        {u32, i32, [u16; 2], [i16; 2], [u8; 4], [i8; 4]}
157    ]
158}
159
160coerce_slice! {
161    N8, 8,
162    [
163        {u64, i64},
164        {u128, i128}
165    ],
166    [
167        {u8, i8},
168        {u16, i16, [u8; 2], [i8; 2]}
169    ]
170}
171
172coerce_slice! {
173    N16, 16,
174    [
175        {u128, i128}
176    ],
177    [
178        {u8, i8}
179    ]
180}