Coverage Report

Created: 2026-05-30 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/num-conv-0.2.0/src/lib.rs
Line
Count
Source
1
//! `num_conv` is a crate to convert between integer types without using `as` casts. This provides
2
//! better certainty when refactoring, makes the exact behavior of code more explicit, and allows
3
//! using turbofish syntax.
4
5
#![no_std]
6
7
/// Anonymously import all extension traits.
8
///
9
/// This allows you to use the methods without worrying about polluting the namespace or importing
10
/// them individually.
11
///
12
/// ```rust
13
/// use num_conv::prelude::*;
14
/// ```
15
pub mod prelude {
16
    pub use crate::{Extend as _, Truncate as _};
17
}
18
19
mod 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! {
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
    }
40
}
41
42
/// A type that can be used with turbofish syntax in [`Extend::extend`].
43
///
44
/// It is unlikely that you will want to use this trait directly. You are probably looking for the
45
/// [`Extend`] trait.
46
pub trait ExtendTarget<T>: sealed::ExtendTargetSealed<T> {}
47
48
/// A type that can be used with turbofish syntax in [`Truncate::truncate`].
49
///
50
/// It is unlikely that you will want to use this trait directly. You are probably looking for the
51
/// [`Truncate`] trait.
52
pub trait TruncateTarget<T>: sealed::TruncateTargetSealed<T> {}
53
54
/// Extend to an integer of the same size or larger, preserving its value.
55
///
56
/// ```rust
57
/// # use num_conv::Extend;
58
/// assert_eq!(0_u8.extend::<u16>(), 0_u16);
59
/// assert_eq!(0_u16.extend::<u32>(), 0_u32);
60
/// assert_eq!(0_u32.extend::<u64>(), 0_u64);
61
/// assert_eq!(0_u64.extend::<u128>(), 0_u128);
62
/// ```
63
///
64
/// ```rust
65
/// # use num_conv::Extend;
66
/// assert_eq!((-1_i8).extend::<i16>(), -1_i16);
67
/// assert_eq!((-1_i16).extend::<i32>(), -1_i32);
68
/// assert_eq!((-1_i32).extend::<i64>(), -1_i64);
69
/// assert_eq!((-1_i64).extend::<i128>(), -1_i128);
70
/// ```
71
pub trait Extend: sealed::Integer {
72
    /// Extend an integer to an integer of the same size or larger, preserving its value.
73
    fn extend<T>(self) -> T
74
    where
75
        Self: ExtendTarget<T>;
76
}
77
78
impl<T: sealed::Integer> Extend for T {
79
0
    fn extend<U>(self) -> U
80
0
    where
81
0
        T: ExtendTarget<U>,
82
    {
83
0
        sealed::ExtendTargetSealed::extend(self)
84
0
    }
Unexecuted instantiation: <u8 as num_conv::Extend>::extend::<usize>
Unexecuted instantiation: <_ as num_conv::Extend>::extend::<_>
85
}
86
87
/// Truncate to an integer of the same size or smaller, preserving the least significant bits.
88
///
89
/// ```rust
90
/// # use num_conv::Truncate;
91
/// assert_eq!(u16::MAX.truncate::<u8>(), u8::MAX);
92
/// assert_eq!(u32::MAX.truncate::<u16>(), u16::MAX);
93
/// assert_eq!(u64::MAX.truncate::<u32>(), u32::MAX);
94
/// assert_eq!(u128::MAX.truncate::<u64>(), u64::MAX);
95
/// ```
96
///
97
/// ```rust
98
/// # use num_conv::Truncate;
99
/// assert_eq!((-1_i16).truncate::<i8>(), -1_i8);
100
/// assert_eq!((-1_i32).truncate::<i16>(), -1_i16);
101
/// assert_eq!((-1_i64).truncate::<i32>(), -1_i32);
102
/// assert_eq!((-1_i128).truncate::<i64>(), -1_i64);
103
/// ```
104
pub trait Truncate: sealed::Integer {
105
    /// Truncate an integer to an integer of the same size or smaller, preserving the least
106
    /// significant bits.
107
    fn truncate<T>(self) -> T
108
    where
109
        Self: TruncateTarget<T>;
110
}
111
112
impl<T: sealed::Integer> Truncate for T {
113
0
    fn truncate<U>(self) -> U
114
0
    where
115
0
        T: TruncateTarget<U>,
116
    {
117
0
        sealed::TruncateTargetSealed::truncate(self)
118
0
    }
Unexecuted instantiation: <u32 as num_conv::Truncate>::truncate::<u8>
Unexecuted instantiation: <_ as num_conv::Truncate>::truncate::<_>
119
}
120
121
macro_rules! impl_extend {
122
    ($($from:ty => $($to:ty),+;)*) => {$($(
123
        const _: () = assert!(
124
            core::mem::size_of::<$from>() <= core::mem::size_of::<$to>(),
125
            concat!(
126
                "cannot extend ",
127
                stringify!($from),
128
                " to ",
129
                stringify!($to),
130
                " because ",
131
                stringify!($from),
132
                " is larger than ",
133
                stringify!($to)
134
            )
135
        );
136
137
        impl sealed::ExtendTargetSealed<$to> for $from {
138
0
            fn extend(self) -> $to {
139
0
                self as _
140
0
            }
Unexecuted instantiation: <u8 as num_conv::sealed::ExtendTargetSealed<u8>>::extend
Unexecuted instantiation: <i32 as num_conv::sealed::ExtendTargetSealed<i128>>::extend
Unexecuted instantiation: <i64 as num_conv::sealed::ExtendTargetSealed<i64>>::extend
Unexecuted instantiation: <i64 as num_conv::sealed::ExtendTargetSealed<i128>>::extend
Unexecuted instantiation: <i128 as num_conv::sealed::ExtendTargetSealed<i128>>::extend
Unexecuted instantiation: <isize as num_conv::sealed::ExtendTargetSealed<isize>>::extend
Unexecuted instantiation: <u8 as num_conv::sealed::ExtendTargetSealed<u16>>::extend
Unexecuted instantiation: <u8 as num_conv::sealed::ExtendTargetSealed<u32>>::extend
Unexecuted instantiation: <u8 as num_conv::sealed::ExtendTargetSealed<u64>>::extend
Unexecuted instantiation: <u8 as num_conv::sealed::ExtendTargetSealed<u128>>::extend
Unexecuted instantiation: <i8 as num_conv::sealed::ExtendTargetSealed<i8>>::extend
Unexecuted instantiation: <i8 as num_conv::sealed::ExtendTargetSealed<i16>>::extend
Unexecuted instantiation: <i8 as num_conv::sealed::ExtendTargetSealed<i32>>::extend
Unexecuted instantiation: <i8 as num_conv::sealed::ExtendTargetSealed<i64>>::extend
Unexecuted instantiation: <i8 as num_conv::sealed::ExtendTargetSealed<i128>>::extend
Unexecuted instantiation: <i8 as num_conv::sealed::ExtendTargetSealed<isize>>::extend
Unexecuted instantiation: <i16 as num_conv::sealed::ExtendTargetSealed<i16>>::extend
Unexecuted instantiation: <i16 as num_conv::sealed::ExtendTargetSealed<i32>>::extend
Unexecuted instantiation: <i16 as num_conv::sealed::ExtendTargetSealed<i64>>::extend
Unexecuted instantiation: <i16 as num_conv::sealed::ExtendTargetSealed<i128>>::extend
Unexecuted instantiation: <i16 as num_conv::sealed::ExtendTargetSealed<isize>>::extend
Unexecuted instantiation: <i32 as num_conv::sealed::ExtendTargetSealed<i32>>::extend
Unexecuted instantiation: <i32 as num_conv::sealed::ExtendTargetSealed<i64>>::extend
Unexecuted instantiation: <u8 as num_conv::sealed::ExtendTargetSealed<usize>>::extend
Unexecuted instantiation: <u16 as num_conv::sealed::ExtendTargetSealed<u16>>::extend
Unexecuted instantiation: <u16 as num_conv::sealed::ExtendTargetSealed<u32>>::extend
Unexecuted instantiation: <u16 as num_conv::sealed::ExtendTargetSealed<u64>>::extend
Unexecuted instantiation: <u16 as num_conv::sealed::ExtendTargetSealed<u128>>::extend
Unexecuted instantiation: <u16 as num_conv::sealed::ExtendTargetSealed<usize>>::extend
Unexecuted instantiation: <u32 as num_conv::sealed::ExtendTargetSealed<u32>>::extend
Unexecuted instantiation: <u32 as num_conv::sealed::ExtendTargetSealed<u64>>::extend
Unexecuted instantiation: <u32 as num_conv::sealed::ExtendTargetSealed<u128>>::extend
Unexecuted instantiation: <u64 as num_conv::sealed::ExtendTargetSealed<u64>>::extend
Unexecuted instantiation: <u64 as num_conv::sealed::ExtendTargetSealed<u128>>::extend
Unexecuted instantiation: <u128 as num_conv::sealed::ExtendTargetSealed<u128>>::extend
Unexecuted instantiation: <usize as num_conv::sealed::ExtendTargetSealed<usize>>::extend
141
        }
142
143
        impl ExtendTarget<$to> for $from {}
144
    )+)*};
145
}
146
147
macro_rules! impl_truncate {
148
    ($($($from:ty),+ => $to:ty;)*) => {$($(
149
        const _: () = assert!(
150
            core::mem::size_of::<$from>() >= core::mem::size_of::<$to>(),
151
            concat!(
152
                "cannot truncate ",
153
                stringify!($from),
154
                " to ",
155
                stringify!($to),
156
                " because ",
157
                stringify!($from),
158
                " is smaller than ",
159
                stringify!($to)
160
            )
161
        );
162
163
        impl sealed::TruncateTargetSealed<$to> for $from {
164
0
            fn truncate(self) -> $to {
165
0
                self as _
166
0
            }
Unexecuted instantiation: <u128 as num_conv::sealed::TruncateTargetSealed<u32>>::truncate
Unexecuted instantiation: <u64 as num_conv::sealed::TruncateTargetSealed<u64>>::truncate
Unexecuted instantiation: <u128 as num_conv::sealed::TruncateTargetSealed<u64>>::truncate
Unexecuted instantiation: <u128 as num_conv::sealed::TruncateTargetSealed<u128>>::truncate
Unexecuted instantiation: <usize as num_conv::sealed::TruncateTargetSealed<usize>>::truncate
Unexecuted instantiation: <i8 as num_conv::sealed::TruncateTargetSealed<i8>>::truncate
Unexecuted instantiation: <i16 as num_conv::sealed::TruncateTargetSealed<i8>>::truncate
Unexecuted instantiation: <i32 as num_conv::sealed::TruncateTargetSealed<i8>>::truncate
Unexecuted instantiation: <i64 as num_conv::sealed::TruncateTargetSealed<i8>>::truncate
Unexecuted instantiation: <i128 as num_conv::sealed::TruncateTargetSealed<i8>>::truncate
Unexecuted instantiation: <isize as num_conv::sealed::TruncateTargetSealed<i8>>::truncate
Unexecuted instantiation: <i16 as num_conv::sealed::TruncateTargetSealed<i16>>::truncate
Unexecuted instantiation: <i32 as num_conv::sealed::TruncateTargetSealed<i16>>::truncate
Unexecuted instantiation: <u8 as num_conv::sealed::TruncateTargetSealed<u8>>::truncate
Unexecuted instantiation: <u16 as num_conv::sealed::TruncateTargetSealed<u8>>::truncate
Unexecuted instantiation: <u32 as num_conv::sealed::TruncateTargetSealed<u8>>::truncate
Unexecuted instantiation: <u64 as num_conv::sealed::TruncateTargetSealed<u8>>::truncate
Unexecuted instantiation: <u128 as num_conv::sealed::TruncateTargetSealed<u8>>::truncate
Unexecuted instantiation: <usize as num_conv::sealed::TruncateTargetSealed<u8>>::truncate
Unexecuted instantiation: <u16 as num_conv::sealed::TruncateTargetSealed<u16>>::truncate
Unexecuted instantiation: <u32 as num_conv::sealed::TruncateTargetSealed<u16>>::truncate
Unexecuted instantiation: <u64 as num_conv::sealed::TruncateTargetSealed<u16>>::truncate
Unexecuted instantiation: <u128 as num_conv::sealed::TruncateTargetSealed<u16>>::truncate
Unexecuted instantiation: <usize as num_conv::sealed::TruncateTargetSealed<u16>>::truncate
Unexecuted instantiation: <u32 as num_conv::sealed::TruncateTargetSealed<u32>>::truncate
Unexecuted instantiation: <u64 as num_conv::sealed::TruncateTargetSealed<u32>>::truncate
Unexecuted instantiation: <i64 as num_conv::sealed::TruncateTargetSealed<i16>>::truncate
Unexecuted instantiation: <i128 as num_conv::sealed::TruncateTargetSealed<i16>>::truncate
Unexecuted instantiation: <isize as num_conv::sealed::TruncateTargetSealed<i16>>::truncate
Unexecuted instantiation: <i32 as num_conv::sealed::TruncateTargetSealed<i32>>::truncate
Unexecuted instantiation: <i64 as num_conv::sealed::TruncateTargetSealed<i32>>::truncate
Unexecuted instantiation: <i128 as num_conv::sealed::TruncateTargetSealed<i32>>::truncate
Unexecuted instantiation: <i64 as num_conv::sealed::TruncateTargetSealed<i64>>::truncate
Unexecuted instantiation: <i128 as num_conv::sealed::TruncateTargetSealed<i64>>::truncate
Unexecuted instantiation: <i128 as num_conv::sealed::TruncateTargetSealed<i128>>::truncate
Unexecuted instantiation: <isize as num_conv::sealed::TruncateTargetSealed<isize>>::truncate
167
        }
168
169
        impl TruncateTarget<$to> for $from {}
170
    )+)*};
171
}
172
173
impl_extend! {
174
    u8 => u8, u16, u32, u64, u128, usize;
175
    u16 => u16, u32, u64, u128, usize;
176
    u32 => u32, u64, u128;
177
    u64 => u64, u128;
178
    u128 => u128;
179
    usize => usize;
180
181
    i8 => i8, i16, i32, i64, i128, isize;
182
    i16 => i16, i32, i64, i128, isize;
183
    i32 => i32, i64, i128;
184
    i64 => i64, i128;
185
    i128 => i128;
186
    isize => isize;
187
}
188
189
impl_truncate! {
190
    u8, u16, u32, u64, u128, usize => u8;
191
    u16, u32, u64, u128, usize => u16;
192
    u32, u64, u128 => u32;
193
    u64, u128 => u64;
194
    u128 => u128;
195
    usize => usize;
196
197
    i8, i16, i32, i64, i128, isize => i8;
198
    i16, i32, i64, i128, isize => i16;
199
    i32, i64, i128 => i32;
200
    i64, i128 => i64;
201
    i128 => i128;
202
    isize => isize;
203
}