1#![no_std]
2use core::marker::PhantomData;
3
4pub struct AsmCast<Out, In>(PhantomData<(Out, In)>);
12
13pub trait AsmCastTrait<Out, In> {
15 type Type;
16
17 fn cast_in(_: &mut Out, x: In) -> Self::Type;
18 fn cast_out(out: &mut Out, _: In, x: Self::Type);
19}
20
21macro_rules! impl_triple {
22 {<$($param:ident),*> ($out:ty, $in:ty) => $inner:ty} => {
23 impl<$($param),*> AsmCastTrait<$out, $in> for AsmCast<$out, $in> {
24 type Type = $inner;
25
26 fn cast_in(_: &mut $out, x: $in) -> Self::Type {
27 x as Self::Type
28 }
29
30 fn cast_out(out: &mut $out, _: $in, x: Self::Type) {
31 *out = x as $out;
32 }
33 }
34 }
35}
36
37macro_rules! impl_triple2 {
38 {<$($param:ident),*> ($out:ty, $in:ty) => $inner:ty} => {
39 impl_triple!{<$($param),*> ($out, $in) => $inner}
40 impl_triple!{<$($param),*> ($in, $out) => $inner}
41 }
42}
43
44macro_rules! impl_pair_higher {
45 {$inner:ty: [$(<$($param:ident),*> $ty1:ty),*]} => {
46 impl_triple!{<> ($inner, $inner) => $inner}
47 $(impl_triple2!{<$($param),*> ($inner, $ty1) => $inner})*
48 }
49}
50
51macro_rules! impl_triple_list {
52 {$inner:ty: [$($ty1:ty: ($(<$($param:ident),*> $ty2:ty),*)),*]} => {
53 $($(impl_triple2!{<$($param),*> ($ty1, $ty2) => $inner})*)*
54 }
55}
56
57impl_triple! {<T, U> (*const T, *const U) => usize}
59impl_triple! {<T, U> (*const T, *mut U) => usize}
60impl_triple! {<T, U> (*mut T, *const U) => usize}
61impl_triple! {<T, U> (*mut T, *mut U) => usize}
62
63impl_pair_higher! {u8: [<>i8]}
64impl_pair_higher! {u16: [<>u8, <>i8, <>i16]}
65impl_pair_higher! {u32: [<>u8, <>u16, <>i8, <>i16, <>i32]}
66impl_pair_higher! {u64: [<>u8, <>u16, <>u32, <>i8, <>i16, <>i32, <>i64, <>usize, <>isize]}
67impl_pair_higher! {i8: []}
68impl_pair_higher! {i16: [<>u8, <>i8]}
69impl_pair_higher! {i32: [<>u8, <>u16, <>i8, <>i16]}
70impl_pair_higher! {i64: [<>u8, <>u16, <>u32, <>i8, <>i16, <>i32, <>usize, <>isize]}
71impl_pair_higher! {usize: [<>u8, <>u16, <>i8, <>i16, <>isize]}
72impl_pair_higher! {isize: [<>u8, <>u16, <>i8, <>i16]}
73
74impl_triple_list! {usize: [u8: (<T>*const T, <T>*mut T),
76 u16: (<T>*const T, <T>*mut T),
77 i8: (<T>*const T, <T>*mut T),
78 i16: (<T>*const T, <T>*mut T),
79 usize: (<T>*const T, <T>*mut T),
80 isize: (<T>*const T, <T>*mut T)]
81}
82
83impl_triple_list! {u64: [u64: (<T>*const T, <T>*mut T)]}
85impl_triple_list! {i64: [i64: (<T>*const T, <T>*mut T)]}
86
87#[cfg(target_pointer_width = "64")]
89impl_triple_list! {u64: [usize: (<>u32, <>i32),
90 isize: (<>u32, <>i32),
91 u32: (<T>*const T, <T>*mut T),
92 i32: (<T>*const T, <T>*mut T)]
93}
94
95#[cfg(target_pointer_width = "32")]
96impl_triple_list! {u32: [usize: (<>u32, <>i32),
97 isize: (<>u32, <>i32),
98 u32: (<T>*const T, <T>*mut T),
99 i32: (<T>*const T, <T>*mut T)]
100}
101
102#[cfg(target_pointer_width = "16")]
103impl_triple_list! {u32: [usize: (<>u32, <>i32),
104 isize: (<>u32, <>i32),
105 u32: (<T>*const T, <T>*mut T),
106 i32: (<T>*const T, <T>*mut T)]
107}
108
109#[cfg(test)]
113mod tests {
114 #[allow(clippy::zero_ptr)]
120 #[test]
121 fn test_coverage() {
122 macro_rules! test_combo {
123 ($ty1:ty, [$($ty2:ty),*]) => {
124 $({
125 use super::{AsmCast, AsmCastTrait};
126
127 let x = 42usize as $ty1;
128 let mut y: $ty2 = 0 as $ty2;
129 let z = AsmCast::cast_in(&mut y, x) + 1;
130 AsmCast::cast_out(&mut y, x, z);
131 assert_eq!(y as u64, 43);
132 })*
133 }
134 }
135
136 test_combo!(u8, [u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, *const u8, *mut u8]);
138 test_combo!(u16, [u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, *const u8, *mut u8]);
139 test_combo!(u32, [u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, *const u8, *mut u8]);
140 test_combo!(u64, [u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, *const u8, *mut u8]);
141 test_combo!(usize, [u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, *const u8, *mut u8]);
142 test_combo!(i8, [u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, *const u8, *mut u8]);
143 test_combo!(i16, [u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, *const u8, *mut u8]);
144 test_combo!(i32, [u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, *const u8, *mut u8]);
145 test_combo!(i64, [u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, *const u8, *mut u8]);
146 test_combo!(isize, [u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, *const u8, *mut u8]);
147 test_combo!(*const u8, [u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, *const u8, *mut u8]);
148 test_combo!(*mut u8, [u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, *const u8, *mut u8]);
149 test_combo!(*const u16, [u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, *const u8, *mut u8]);
150 test_combo!(*mut u16, [u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, *const u8, *mut u8]);
151 }
152}