use crate::pointer::Size;
mod sealed {
pub trait Sealed<U: ?Sized> {}
}
pub trait CoerceSlice<U: ?Sized>: self::sealed::Sealed<U> {
#[doc(hidden)]
fn resize<O: Size>(factor: O) -> O;
#[doc(hidden)]
fn try_resize<O: Size>(factor: O) -> Option<O>;
}
macro_rules! self_impl_inner {
($from:ty, {$($to:ty),*}) => {
$(
impl self::sealed::Sealed<[$to]> for [$from] {}
#[doc = concat!("Defines the coercion from `[", stringify!($from) ,"]` to `[", stringify!($to), "]`.")]
#[doc = concat!("let reference: Ref<", stringify!($from), "> = Ref::zero();")]
#[doc = concat!("let reference2 = reference.coerce::<[", stringify!($from), "]>();")]
#[doc = concat!("let reference3 = reference.coerce::<", stringify!($to), ">();")]
#[doc = concat!("let reference4 = reference2.coerce::<[", stringify!($to), "]>();")]
impl CoerceSlice<[$to]> for [$from] {
#[inline]
fn resize<O: Size>(len: O) -> O {
len
}
#[inline]
fn try_resize<O: Size>(len: O) -> Option<O> {
Some(len)
}
}
)*
}
}
macro_rules! self_impl {
([$({$($from:ty),*}),*], [$($to:tt),*]) => {
$(
$(
self_impl_inner!($from, $to);
)*
)*
};
}
macro_rules! coerce_slice_inner {
($factor:ident, $value:literal, $from:ty, {$($to:ty),*}) => {
$(
impl self::sealed::Sealed<[$to]> for [$from] {}
#[doc = concat!("Defines the coercion from `[", stringify!($from) ,"]` to `[", stringify!($to), "]`.")]
#[doc = concat!("let reference: Ref<", stringify!($from), "> = Ref::zero();")]
#[doc = concat!("let reference2 = reference.coerce::<[", stringify!($to), "]>();")]
#[doc = concat!("assert_eq!(reference2.len(), ", stringify!($value), ");")]
#[doc = concat!("let reference: Ref<[", stringify!($from), "]> = Ref::with_metadata(0, 5);")]
#[doc = concat!("let reference2 = reference.coerce::<[", stringify!($to), "]>();")]
#[doc = concat!("assert_eq!(reference2.len(), 5 * ", stringify!($value), ");")]
impl CoerceSlice<[$to]> for [$from] {
#[inline]
fn resize<O: Size>(len: O) -> O {
len.wrapping_mul(O::$factor)
}
#[inline]
fn try_resize<O: Size>(len: O) -> Option<O> {
len.checked_mul(O::$factor)
}
}
)*
}
}
macro_rules! coerce_slice {
($factor:ident, $value:literal, [$({$($from:ty),*}),*], [$($to:tt),*]) => {
$(
$(
coerce_slice_inner!($factor, $value, $from, $to);
)*
)*
}
}
self_impl! {
[
{u8, i8},
{u16, i16},
{u32, i32},
{u64, i64},
{u128, i128}
],
[
{u8, i8},
{u16, i16, [u8; 2], [i8; 2]},
{u32, i32, [u16; 2], [i16; 2], [u8; 4], [i8; 4]},
{u64, i64, [u32; 2], [i32; 2], [u16; 4], [i16; 4], [u8; 8], [i8; 8]},
{u128, i128, [u64; 2], [i64; 2], [u32; 4], [i32; 4], [u16; 8], [i16; 8], [u8; 16], [i8; 16]}
]
}
coerce_slice! {
N2, 2,
[
{u16, i16},
{u32, i32},
{u64, i64},
{u128, i128}
],
[
{u8, i8},
{u16, i16, [u8; 2], [i8; 2]},
{u32, i32, [u16; 2], [i16; 2], [u8; 4], [i8; 4]},
{u64, i64, [u32; 2], [i32; 2], [u16; 4], [i16; 4], [u8; 8], [i8; 8]}
]
}
coerce_slice! {
N4, 4,
[
{u32, i32},
{u64, i64},
{u128, i128}
],
[
{u8, i8},
{u16, i16, [u8; 2], [i8; 2]},
{u32, i32, [u16; 2], [i16; 2], [u8; 4], [i8; 4]}
]
}
coerce_slice! {
N8, 8,
[
{u64, i64},
{u128, i128}
],
[
{u8, i8},
{u16, i16, [u8; 2], [i8; 2]}
]
}
coerce_slice! {
N16, 16,
[
{u128, i128}
],
[
{u8, i8}
]
}