1#![no_std]
6
7pub mod prelude {
16 pub use crate::{Extend as _, Truncate as _};
17}
18
19mod sealed {
20 pub trait Integer {}
21
22 macro_rules! impl_integer {
23 ($($t:ty)*) => {$(
24 impl Integer for $t {}
25 )*};
26 }
27
28 impl Integer for isize {}impl_integer! {
29 u8 u16 u32 u64 u128 usize
30 i8 i16 i32 i64 i128 isize
31 }
32
33 pub trait ExtendTargetSealed<T> {
34 fn extend(self) -> T;
35 }
36
37 pub trait TruncateTargetSealed<T> {
38 fn truncate(self) -> T;
39 fn saturating_truncate(self) -> T;
40 fn checked_truncate(self) -> Option<T>;
41 }
42}
43
44pub trait ExtendTarget<T>: sealed::ExtendTargetSealed<T> {}
49
50pub trait TruncateTarget<T>: sealed::TruncateTargetSealed<T> {}
55
56pub trait Extend: sealed::Integer {
74 fn extend<T>(self) -> T
76 where
77 Self: ExtendTarget<T>;
78}
79
80impl<T: sealed::Integer> Extend for T {
81 fn extend<U>(self) -> U
82 where
83 T: ExtendTarget<U>,
84 {
85 sealed::ExtendTargetSealed::extend(self)
86 }
87}
88
89pub trait Truncate: sealed::Integer {
145 fn truncate<T>(self) -> T
148 where
149 Self: TruncateTarget<T>;
150
151 fn saturating_truncate<T>(self) -> T
154 where
155 Self: TruncateTarget<T>;
156
157 fn checked_truncate<T>(self) -> Option<T>
160 where
161 Self: TruncateTarget<T>;
162}
163
164impl<T: sealed::Integer> Truncate for T {
165 fn truncate<U>(self) -> U
166 where
167 T: TruncateTarget<U>,
168 {
169 sealed::TruncateTargetSealed::truncate(self)
170 }
171
172 fn saturating_truncate<U>(self) -> U
173 where
174 T: TruncateTarget<U>,
175 {
176 sealed::TruncateTargetSealed::saturating_truncate(self)
177 }
178
179 fn checked_truncate<U>(self) -> Option<U>
180 where
181 T: TruncateTarget<U>,
182 {
183 sealed::TruncateTargetSealed::checked_truncate(self)
184 }
185}
186
187macro_rules! impl_extend {
188 ($($from:ty => $($to:ty),+;)*) => {$($(
189 const _: () = assert!(
190 core::mem::size_of::<$from>() <= core::mem::size_of::<$to>(),
191 concat!(
192 "cannot extend ",
193 stringify!($from),
194 " to ",
195 stringify!($to),
196 " because ",
197 stringify!($from),
198 " is larger than ",
199 stringify!($to)
200 )
201 );
202
203 impl sealed::ExtendTargetSealed<$to> for $from {
204 #[inline]
205 fn extend(self) -> $to {
206 self as _
207 }
208 }
209
210 impl ExtendTarget<$to> for $from {}
211 )+)*};
212}
213
214macro_rules! impl_truncate {
215 ($($($from:ty),+ => $to:ty;)*) => {$($(
216 const _: () = assert!(
217 core::mem::size_of::<$from>() >= core::mem::size_of::<$to>(),
218 concat!(
219 "cannot truncate ",
220 stringify!($from),
221 " to ",
222 stringify!($to),
223 " because ",
224 stringify!($from),
225 " is smaller than ",
226 stringify!($to)
227 )
228 );
229
230 impl sealed::TruncateTargetSealed<$to> for $from {
231 #[inline]
232 fn truncate(self) -> $to {
233 self as _
234 }
235
236 #[inline]
237 fn saturating_truncate(self) -> $to {
238 if self > <$to>::MAX as _ {
239 <$to>::MAX
240 } else if self < <$to>::MIN as _ {
241 <$to>::MIN
242 } else {
243 self as _
244 }
245 }
246
247 #[inline]
248 fn checked_truncate(self) -> Option<$to> {
249 if self > <$to>::MAX as _ || self < <$to>::MIN as _ {
250 None
251 } else {
252 Some(self as _)
253 }
254 }
255 }
256
257 impl TruncateTarget<$to> for $from {}
258 )+)*};
259}
260
261const _: () =
if !(core::mem::size_of::<isize>() <= core::mem::size_of::<isize>()) {
{
::core::panicking::panic_fmt(format_args!("cannot extend isize to isize because isize is larger than isize"));
}
};
impl sealed::ExtendTargetSealed<isize> for isize {
#[inline]
fn extend(self) -> isize { self as _ }
}
impl ExtendTarget<isize> for isize {}impl_extend! {
262 u8 => u8, u16, u32, u64, u128, usize;
263 u16 => u16, u32, u64, u128, usize;
264 u32 => u32, u64, u128;
265 u64 => u64, u128;
266 u128 => u128;
267 usize => usize;
268
269 i8 => i8, i16, i32, i64, i128, isize;
270 i16 => i16, i32, i64, i128, isize;
271 i32 => i32, i64, i128;
272 i64 => i64, i128;
273 i128 => i128;
274 isize => isize;
275}
276
277const _: () =
if !(core::mem::size_of::<isize>() >= core::mem::size_of::<isize>()) {
{
::core::panicking::panic_fmt(format_args!("cannot truncate isize to isize because isize is smaller than isize"));
}
};
impl sealed::TruncateTargetSealed<isize> for isize {
#[inline]
fn truncate(self) -> isize { self as _ }
#[inline]
fn saturating_truncate(self) -> isize {
if self > <isize>::MAX as _ {
<isize>::MAX
} else if self < <isize>::MIN as _ { <isize>::MIN } else { self as _ }
}
#[inline]
fn checked_truncate(self) -> Option<isize> {
if self > <isize>::MAX as _ || self < <isize>::MIN as _ {
None
} else { Some(self as _) }
}
}
impl TruncateTarget<isize> for isize {}impl_truncate! {
278 u8, u16, u32, u64, u128, usize => u8;
279 u16, u32, u64, u128, usize => u16;
280 u32, u64, u128 => u32;
281 u64, u128 => u64;
282 u128 => u128;
283 usize => usize;
284
285 i8, i16, i32, i64, i128, isize => i8;
286 i16, i32, i64, i128, isize => i16;
287 i32, i64, i128 => i32;
288 i64, i128 => i64;
289 i128 => i128;
290 isize => isize;
291}