Skip to main content

core/num/
traits.rs

1/// Definitions of traits for numeric types
2// Implementation based on `num_conv` by jhpratt, under (MIT OR Apache-2.0).
3
4/// Trait for types that this type can be truncated to
5#[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")]
6#[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")]
7pub const trait TruncateTarget<Target>: crate::sealed::Sealed {
8    #[doc(hidden)]
9    fn internal_truncate(self) -> Target;
10
11    #[doc(hidden)]
12    fn internal_saturating_truncate(self) -> Target;
13
14    #[doc(hidden)]
15    fn internal_checked_truncate(self) -> Option<Target>;
16}
17
18/// Trait for types that this type can be truncated to
19#[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")]
20#[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")]
21pub const trait ExtendTarget<Target>: crate::sealed::Sealed {
22    #[doc(hidden)]
23    fn internal_extend(self) -> Target;
24}
25
26macro_rules! impl_truncate {
27    ($($from:ty => $($to:ty),+;)*) => {$($(
28        const _: () = assert!(
29            size_of::<$from>() >= size_of::<$to>(),
30            concat!(
31                "cannot truncate ",
32                stringify!($from),
33                " to ",
34                stringify!($to),
35                " because ",
36                stringify!($from),
37                " is smaller than ",
38                stringify!($to)
39            )
40        );
41
42        #[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")]
43        #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")]
44        impl const TruncateTarget<$to> for $from {
45            #[inline]
46            fn internal_truncate(self) -> $to {
47                self as _
48            }
49
50            #[inline]
51            fn internal_saturating_truncate(self) -> $to {
52                if self > <$to>::MAX as Self {
53                    <$to>::MAX
54                } else if self < <$to>::MIN as Self {
55                    <$to>::MIN
56                } else {
57                    self as _
58                }
59            }
60
61            #[inline]
62            fn internal_checked_truncate(self) -> Option<$to> {
63                if self > <$to>::MAX as Self || self < <$to>::MIN as Self {
64                    None
65                } else {
66                    Some(self as _)
67                }
68            }
69        }
70    )+)*};
71}
72
73macro_rules! impl_extend {
74    ($($from:ty => $($to:ty),+;)*) => {$($(
75        const _: () = assert!(
76            size_of::<$from>() <= size_of::<$to>(),
77            concat!(
78                "cannot extend ",
79                stringify!($from),
80                " to ",
81                stringify!($to),
82                " because ",
83                stringify!($from),
84                " is larger than ",
85                stringify!($to)
86            )
87        );
88
89        #[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")]
90        #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")]
91        impl const ExtendTarget<$to> for $from {
92            fn internal_extend(self) -> $to {
93                self as _
94            }
95        }
96    )+)*};
97}
98
99const _: () =
    if !(size_of::<isize>() >= size_of::<i8>()) {
        {
            crate::panicking::panic_fmt(format_args!("cannot truncate isize to i8 because isize is smaller than i8"));
        }
    };
#[unstable(feature = "num_internals", reason =
"internal implementation detail", issue = "none")]
#[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")]
impl const TruncateTarget<i8> for isize {
    #[inline]
    fn internal_truncate(self) -> i8 { self as _ }
    #[inline]
    fn internal_saturating_truncate(self) -> i8 {
        if self > <i8>::MAX as Self {
            <i8>::MAX
        } else if self < <i8>::MIN as Self { <i8>::MIN } else { self as _ }
    }
    #[inline]
    fn internal_checked_truncate(self) -> Option<i8> {
        if self > <i8>::MAX as Self || self < <i8>::MIN as Self {
            None
        } else { Some(self as _) }
    }
}impl_truncate! {
100    u8 => u8;
101    u16 => u16, u8;
102    u32 => u32, u16, u8;
103    u64 => u64, u32, u16, u8;
104    u128 => u128, u64, u32, u16, u8;
105    usize => usize, u16, u8;
106
107    i8 => i8;
108    i16 => i16, i8;
109    i32 => i32, i16, i8;
110    i64 => i64, i32, i16, i8;
111    i128 => i128, i64, i32, i16, i8;
112    isize => isize, i16, i8;
113}
114
115const _: () =
    if !(size_of::<isize>() <= size_of::<isize>()) {
        {
            crate::panicking::panic_fmt(format_args!("cannot extend isize to isize because isize is larger than isize"));
        }
    };
#[unstable(feature = "num_internals", reason =
"internal implementation detail", issue = "none")]
#[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")]
impl const ExtendTarget<isize> for isize {
    fn internal_extend(self) -> isize { self as _ }
}impl_extend! {
116    u8 => u8, u16, u32, u64, u128, usize;
117    u16 => u16, u32, u64, u128, usize;
118    u32 => u32, u64, u128;
119    u64 => u64, u128;
120    u128 => u128;
121    usize => usize;
122
123    i8 => i8, i16, i32, i64, i128, isize;
124    i16 => i16, i32, i64, i128, isize;
125    i32 => i32, i64, i128;
126    i64 => i64, i128;
127    i128 => i128;
128    isize => isize;
129}