1use core::mem;
8
9pub trait Truncate<T>: Sized {
11 fn truncate(self) -> T;
13}
14
15impl<T> Truncate<T> for T {
17 #[inline]
18 fn truncate(self) -> T {
19 self
20 }
21}
22
23macro_rules! impl_truncate {
29 ($T:ty => $($U:ty),* $(,)?) => {
30 $(
31 ::static_assertions::const_assert!(mem::size_of::<$T>() > mem::size_of::<$U>());
33
34 impl Truncate<$U> for $T {
35 #[inline]
36 #[allow(clippy::as_conversions)]
37 fn truncate(self) -> $U {
38 self as $U
40 }
41 }
42
43 impl<'a> Truncate<$U> for &'a $T {
44 #[inline]
45 fn truncate(self) -> $U {
46 <$T as Truncate<$U>>::truncate(*self)
47 }
48 }
49 )*
50 };
51}
52
53impl_truncate! { u128 => u64, u32, u16, u8 }
55impl_truncate! { u64 => u32, u16, u8 }
56impl_truncate! { u32 => u16, u8 }
57impl_truncate! { u16 => u8 }
58
59impl_truncate! { i128 => i64, i32, i16, i8 }
61impl_truncate! { i64 => i32, i16, i8 }
62impl_truncate! { i32 => i16, i8 }
63impl_truncate! { i16 => i8 }
64
65pub trait Truncated {
67 #[inline]
69 fn truncated<T>(self) -> T
70 where
71 Self: Truncate<T>,
72 {
73 self.truncate()
74 }
75}
76impl<T> Truncated for T {}
77
78static_assertions::assert_impl_all! { i128 : Truncate<i128>, Truncate<i64>, Truncate<i32>, Truncate<i16>, Truncate<i8> }
80static_assertions::assert_impl_all! { i64 : Truncate<i64>, Truncate<i32>, Truncate<i16>, Truncate<i8> }
81static_assertions::assert_impl_all! { i32 : Truncate<i32>, Truncate<i16>, Truncate<i8> }
82static_assertions::assert_impl_all! { i16 : Truncate<i16>, Truncate<i8> }
83static_assertions::assert_impl_all! { i8 : Truncate<i8> }
84static_assertions::assert_impl_all! { u128 : Truncate<u128>, Truncate<u64>, Truncate<u32>, Truncate<u16>, Truncate<u8> }
85static_assertions::assert_impl_all! { u64 : Truncate<u64>, Truncate<u32>, Truncate<u16>, Truncate<u8> }
86static_assertions::assert_impl_all! { u32 : Truncate<u32>, Truncate<u16>, Truncate<u8> }
87static_assertions::assert_impl_all! { u16 : Truncate<u16>, Truncate<u8> }
88static_assertions::assert_impl_all! { u8 : Truncate<u8> }
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 #[rustfmt::skip]
96 fn truncate_unsigned() {
97 assert_eq!(u128::truncated::<u128>(1), 1);
98 assert_eq!(u128::truncated::< u64>(1), 1);
99 assert_eq!(u128::truncated::< u32>(1), 1);
100 assert_eq!(u128::truncated::< u16>(1), 1);
101 assert_eq!(u128::truncated::< u8>(1), 1);
102 assert_eq!( u64::truncated::< u64>(1), 1);
103 assert_eq!( u64::truncated::< u32>(1), 1);
104 assert_eq!( u64::truncated::< u16>(1), 1);
105 assert_eq!( u64::truncated::< u8>(1), 1);
106 assert_eq!( u32::truncated::< u32>(1), 1);
107 assert_eq!( u32::truncated::< u16>(1), 1);
108 assert_eq!( u32::truncated::< u8>(1), 1);
109 assert_eq!( u16::truncated::< u16>(1), 1);
110 assert_eq!( u16::truncated::< u8>(1), 1);
111 assert_eq!( u8::truncated::< u8>(1), 1);
112 }
113
114 #[test]
115 #[rustfmt::skip]
116 fn truncate_signed() {
117 assert_eq!(i128::truncated::<i128>(-1), -1);
118 assert_eq!(i128::truncated::< i64>(-1), -1);
119 assert_eq!(i128::truncated::< i32>(-1), -1);
120 assert_eq!(i128::truncated::< i16>(-1), -1);
121 assert_eq!(i128::truncated::< i8>(-1), -1);
122 assert_eq!( i64::truncated::< i64>(-1), -1);
123 assert_eq!( i64::truncated::< i32>(-1), -1);
124 assert_eq!( i64::truncated::< i16>(-1), -1);
125 assert_eq!( i64::truncated::< i8>(-1), -1);
126 assert_eq!( i32::truncated::< i32>(-1), -1);
127 assert_eq!( i32::truncated::< i16>(-1), -1);
128 assert_eq!( i32::truncated::< i8>(-1), -1);
129 assert_eq!( i16::truncated::< i16>(-1), -1);
130 assert_eq!( i16::truncated::< i8>(-1), -1);
131 assert_eq!( i8::truncated::< i8>(-1), -1);
132 }
133}