Coverage Report

Created: 2026-05-30 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/num-conv-0.2.2/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. The crate is currently in the process of being uplifted into the
4
//! standard library; see [rust-lang/rust#154330](https://github.com/rust-lang/rust/issues/154330)
5
//! for details.
6
7
#![no_std]
8
9
/// Anonymously import all extension traits.
10
///
11
/// This allows you to use the methods without worrying about polluting the namespace or importing
12
/// them individually.
13
///
14
/// ```rust
15
/// use num_conv::prelude::*;
16
/// ```
17
pub mod prelude {
18
    #[allow(deprecated)]
19
    pub use crate::{Extend as _, Truncate as _, Widen as _};
20
}
21
22
mod sealed {
23
    pub trait Integer {}
24
25
    macro_rules! impl_integer {
26
        ($($t:ty)*) => {$(
27
            impl Integer for $t {}
28
        )*};
29
    }
30
31
    impl_integer! {
32
        u8 u16 u32 u64 u128 usize
33
        i8 i16 i32 i64 i128 isize
34
    }
35
36
    #[deprecated(since = "0.2.2", note = "use `WidenTargetSealed` instead")]
37
    pub trait ExtendTargetSealed<T> {
38
        #[deprecated(since = "0.2.2", note = "use `widen` instead")]
39
        fn extend(self) -> T;
40
    }
41
42
    pub trait WidenTargetSealed<T> {
43
        fn widen(self) -> T;
44
    }
45
46
    pub trait TruncateTargetSealed<T> {
47
        fn truncate(self) -> T;
48
        fn saturating_truncate(self) -> T;
49
        fn checked_truncate(self) -> Option<T>;
50
    }
51
}
52
53
/// A type that can be used with turbofish syntax in [`Extend::extend`].
54
///
55
/// It is unlikely that you will want to use this trait directly. You are probably looking for the
56
/// [`Extend`] trait.
57
#[deprecated(since = "0.2.2", note = "use `WidenTarget` instead")]
58
#[allow(deprecated)]
59
pub trait ExtendTarget<T>: sealed::ExtendTargetSealed<T> {}
60
61
/// A type that can be used with turbofish syntax in [`Widen::widen`].
62
///
63
/// It is unlikely that you will want to use this trait directly. You are probably looking for the
64
/// [`Widen`] trait.
65
pub trait WidenTarget<T>: sealed::WidenTargetSealed<T> {}
66
67
/// A type that can be used with turbofish syntax in [`Truncate::truncate`].
68
///
69
/// It is unlikely that you will want to use this trait directly. You are probably looking for the
70
/// [`Truncate`] trait.
71
pub trait TruncateTarget<T>: sealed::TruncateTargetSealed<T> {}
72
73
/// Widen to an integer of the same size or larger, preserving its value.
74
///
75
/// ```rust
76
/// # use num_conv::Widen;
77
/// assert_eq!(0_u8.widen::<u16>(), 0_u16);
78
/// assert_eq!(0_u16.widen::<u32>(), 0_u32);
79
/// assert_eq!(0_u32.widen::<u64>(), 0_u64);
80
/// assert_eq!(0_u64.widen::<u128>(), 0_u128);
81
/// ```
82
///
83
/// ```rust
84
/// # use num_conv::Widen;
85
/// assert_eq!((-1_i8).widen::<i16>(), -1_i16);
86
/// assert_eq!((-1_i16).widen::<i32>(), -1_i32);
87
/// assert_eq!((-1_i32).widen::<i64>(), -1_i64);
88
/// assert_eq!((-1_i64).widen::<i128>(), -1_i128);
89
/// ```
90
pub trait Widen: sealed::Integer {
91
    /// Widen an integer to an integer of the same size or larger, preserving its value.
92
    fn widen<T>(self) -> T
93
    where
94
        Self: WidenTarget<T>;
95
}
96
97
impl<T: sealed::Integer> Widen for T {
98
    fn widen<U>(self) -> U
99
    where
100
        T: WidenTarget<U>,
101
    {
102
        sealed::WidenTargetSealed::widen(self)
103
    }
104
}
105
106
/// Extend to an integer of the same size or larger, preserving its value.
107
///
108
/// ```rust
109
/// # use num_conv::Extend;
110
/// assert_eq!(0_u8.extend::<u16>(), 0_u16);
111
/// assert_eq!(0_u16.extend::<u32>(), 0_u32);
112
/// assert_eq!(0_u32.extend::<u64>(), 0_u64);
113
/// assert_eq!(0_u64.extend::<u128>(), 0_u128);
114
/// ```
115
///
116
/// ```rust
117
/// # use num_conv::Extend;
118
/// assert_eq!((-1_i8).extend::<i16>(), -1_i16);
119
/// assert_eq!((-1_i16).extend::<i32>(), -1_i32);
120
/// assert_eq!((-1_i32).extend::<i64>(), -1_i64);
121
/// assert_eq!((-1_i64).extend::<i128>(), -1_i128);
122
/// ```
123
#[deprecated(since = "0.2.2", note = "use `Widen` instead")]
124
#[allow(deprecated)]
125
pub trait Extend: sealed::Integer {
126
    /// Extend an integer to an integer of the same size or larger, preserving its value.
127
    fn extend<T>(self) -> T
128
    where
129
        Self: ExtendTarget<T>;
130
}
131
132
#[allow(deprecated)]
133
impl<T: sealed::Integer> Extend for T {
134
39.2k
    fn extend<U>(self) -> U
135
39.2k
    where
136
39.2k
        T: ExtendTarget<U>,
137
    {
138
39.2k
        sealed::ExtendTargetSealed::extend(self)
139
39.2k
    }
<u8 as num_conv::Extend>::extend::<usize>
Line
Count
Source
134
10.0k
    fn extend<U>(self) -> U
135
10.0k
    where
136
10.0k
        T: ExtendTarget<U>,
137
    {
138
10.0k
        sealed::ExtendTargetSealed::extend(self)
139
10.0k
    }
<u8 as num_conv::Extend>::extend::<u32>
Line
Count
Source
134
8.81k
    fn extend<U>(self) -> U
135
8.81k
    where
136
8.81k
        T: ExtendTarget<U>,
137
    {
138
8.81k
        sealed::ExtendTargetSealed::extend(self)
139
8.81k
    }
Unexecuted instantiation: <u8 as num_conv::Extend>::extend::<u16>
<i16 as num_conv::Extend>::extend::<i32>
Line
Count
Source
134
20.3k
    fn extend<U>(self) -> U
135
20.3k
    where
136
20.3k
        T: ExtendTarget<U>,
137
    {
138
20.3k
        sealed::ExtendTargetSealed::extend(self)
139
20.3k
    }
Unexecuted instantiation: <u16 as num_conv::Extend>::extend::<usize>
Unexecuted instantiation: <u16 as num_conv::Extend>::extend::<u32>
140
}
141
142
/// Truncate to an integer of the same size or smaller.
143
///
144
/// Preserve the least significant bits with `.truncate()`:
145
///
146
/// ```rust
147
/// # use num_conv::Truncate;
148
/// assert_eq!(u16::MAX.truncate::<u8>(), u8::MAX);
149
/// assert_eq!(u32::MAX.truncate::<u16>(), u16::MAX);
150
/// assert_eq!(u64::MAX.truncate::<u32>(), u32::MAX);
151
/// assert_eq!(u128::MAX.truncate::<u64>(), u64::MAX);
152
/// ```
153
///
154
/// ```rust
155
/// # use num_conv::Truncate;
156
/// assert_eq!((-1_i16).truncate::<i8>(), -1_i8);
157
/// assert_eq!((-1_i32).truncate::<i16>(), -1_i16);
158
/// assert_eq!((-1_i64).truncate::<i32>(), -1_i32);
159
/// assert_eq!((-1_i128).truncate::<i64>(), -1_i64);
160
/// ```
161
///
162
/// Saturate to the numeric bounds with `.saturating_truncate()`:
163
///
164
/// ```rust
165
/// # use num_conv::Truncate;
166
/// assert_eq!(500_u16.saturating_truncate::<u8>(), u8::MAX);
167
/// assert_eq!(u32::MAX.saturating_truncate::<u16>(), u16::MAX);
168
/// assert_eq!(u64::MAX.saturating_truncate::<u32>(), u32::MAX);
169
/// assert_eq!(u128::MAX.saturating_truncate::<u64>(), u64::MAX);
170
/// ```
171
///
172
/// ```rust
173
/// # use num_conv::Truncate;
174
/// assert_eq!((-500_i16).saturating_truncate::<i8>(), i8::MIN);
175
/// assert_eq!(i32::MIN.saturating_truncate::<i16>(), i16::MIN);
176
/// assert_eq!(i64::MIN.saturating_truncate::<i32>(), i32::MIN);
177
/// assert_eq!(i128::MIN.saturating_truncate::<i64>(), i64::MIN);
178
/// ```
179
///
180
/// Checked with `.checked_truncate()`, returning `None` if the value is out of range:
181
///
182
/// ```rust
183
/// # use num_conv::Truncate;
184
/// assert_eq!(u16::MAX.checked_truncate::<u8>(), None);
185
/// assert_eq!(u32::MAX.checked_truncate::<u16>(), None);
186
/// assert_eq!(u64::MAX.checked_truncate::<u32>(), None);
187
/// assert_eq!(u128::MAX.checked_truncate::<u64>(), None);
188
/// ```
189
///
190
/// ```rust
191
/// # use num_conv::Truncate;
192
/// assert_eq!(i16::MIN.checked_truncate::<i8>(), None);
193
/// assert_eq!(i32::MIN.checked_truncate::<i16>(), None);
194
/// assert_eq!(i64::MIN.checked_truncate::<i32>(), None);
195
/// assert_eq!(i128::MIN.checked_truncate::<i64>(), None);
196
/// ```
197
pub trait Truncate: sealed::Integer {
198
    /// Truncate an integer to an integer of the same size or smaller, preserving the least
199
    /// significant bits.
200
    fn truncate<T>(self) -> T
201
    where
202
        Self: TruncateTarget<T>;
203
204
    /// Truncate an integer to an integer of the same size or smaller, saturating to the numeric
205
    /// bounds instead of wrapping.
206
    fn saturating_truncate<T>(self) -> T
207
    where
208
        Self: TruncateTarget<T>;
209
210
    /// Truncate an integer to an integer of the same size or smaller, returning `None` if the value
211
    /// is out of range.
212
    fn checked_truncate<T>(self) -> Option<T>
213
    where
214
        Self: TruncateTarget<T>;
215
}
216
217
impl<T: sealed::Integer> Truncate for T {
218
9.77k
    fn truncate<U>(self) -> U
219
9.77k
    where
220
9.77k
        T: TruncateTarget<U>,
221
    {
222
9.77k
        sealed::TruncateTargetSealed::truncate(self)
223
9.77k
    }
<usize as num_conv::Truncate>::truncate::<u8>
Line
Count
Source
218
5.02k
    fn truncate<U>(self) -> U
219
5.02k
    where
220
5.02k
        T: TruncateTarget<U>,
221
    {
222
5.02k
        sealed::TruncateTargetSealed::truncate(self)
223
5.02k
    }
Unexecuted instantiation: <i32 as num_conv::Truncate>::truncate::<i8>
Unexecuted instantiation: <i32 as num_conv::Truncate>::truncate::<i16>
<u32 as num_conv::Truncate>::truncate::<u8>
Line
Count
Source
218
4.75k
    fn truncate<U>(self) -> U
219
4.75k
    where
220
4.75k
        T: TruncateTarget<U>,
221
    {
222
4.75k
        sealed::TruncateTargetSealed::truncate(self)
223
4.75k
    }
224
225
    fn saturating_truncate<U>(self) -> U
226
    where
227
        T: TruncateTarget<U>,
228
    {
229
        sealed::TruncateTargetSealed::saturating_truncate(self)
230
    }
231
232
    fn checked_truncate<U>(self) -> Option<U>
233
    where
234
        T: TruncateTarget<U>,
235
    {
236
        sealed::TruncateTargetSealed::checked_truncate(self)
237
    }
238
}
239
240
macro_rules! impl_widen {
241
    ($($from:ty => $($to:ty),+;)*) => {$($(
242
        const _: () = assert!(
243
            core::mem::size_of::<$from>() <= core::mem::size_of::<$to>(),
244
            concat!(
245
                "cannot widen ",
246
                stringify!($from),
247
                " to ",
248
                stringify!($to),
249
                " because ",
250
                stringify!($from),
251
                " is larger than ",
252
                stringify!($to)
253
            )
254
        );
255
256
        #[allow(deprecated)]
257
        impl sealed::ExtendTargetSealed<$to> for $from {
258
            #[inline]
259
39.2k
            fn extend(self) -> $to {
260
39.2k
                self as _
261
39.2k
            }
<u8 as num_conv::sealed::ExtendTargetSealed<usize>>::extend
Line
Count
Source
259
10.0k
            fn extend(self) -> $to {
260
10.0k
                self as _
261
10.0k
            }
<i16 as num_conv::sealed::ExtendTargetSealed<i32>>::extend
Line
Count
Source
259
20.3k
            fn extend(self) -> $to {
260
20.3k
                self as _
261
20.3k
            }
Unexecuted instantiation: <u8 as num_conv::sealed::ExtendTargetSealed<u16>>::extend
<u8 as num_conv::sealed::ExtendTargetSealed<u32>>::extend
Line
Count
Source
259
8.81k
            fn extend(self) -> $to {
260
8.81k
                self as _
261
8.81k
            }
Unexecuted instantiation: <u16 as num_conv::sealed::ExtendTargetSealed<usize>>::extend
Unexecuted instantiation: <u16 as num_conv::sealed::ExtendTargetSealed<u32>>::extend
262
        }
263
264
        impl sealed::WidenTargetSealed<$to> for $from {
265
            #[inline]
266
            fn widen(self) -> $to {
267
                self as _
268
            }
269
        }
270
271
        #[allow(deprecated)]
272
        impl ExtendTarget<$to> for $from {}
273
        impl WidenTarget<$to> for $from {}
274
    )+)*};
275
}
276
277
macro_rules! impl_truncate {
278
    ($($($from:ty),+ => $to:ty;)*) => {$($(
279
        const _: () = assert!(
280
            core::mem::size_of::<$from>() >= core::mem::size_of::<$to>(),
281
            concat!(
282
                "cannot truncate ",
283
                stringify!($from),
284
                " to ",
285
                stringify!($to),
286
                " because ",
287
                stringify!($from),
288
                " is smaller than ",
289
                stringify!($to)
290
            )
291
        );
292
293
        impl sealed::TruncateTargetSealed<$to> for $from {
294
            #[inline]
295
9.77k
            fn truncate(self) -> $to {
296
9.77k
                self as _
297
9.77k
            }
<usize as num_conv::sealed::TruncateTargetSealed<u8>>::truncate
Line
Count
Source
295
5.02k
            fn truncate(self) -> $to {
296
5.02k
                self as _
297
5.02k
            }
Unexecuted instantiation: <i32 as num_conv::sealed::TruncateTargetSealed<i8>>::truncate
<u32 as num_conv::sealed::TruncateTargetSealed<u8>>::truncate
Line
Count
Source
295
4.75k
            fn truncate(self) -> $to {
296
4.75k
                self as _
297
4.75k
            }
Unexecuted instantiation: <i32 as num_conv::sealed::TruncateTargetSealed<i16>>::truncate
298
299
            #[inline]
300
            fn saturating_truncate(self) -> $to {
301
                if self > <$to>::MAX as _ {
302
                    <$to>::MAX
303
                } else if self < <$to>::MIN as _ {
304
                    <$to>::MIN
305
                } else {
306
                    self as _
307
                }
308
            }
309
310
            #[inline]
311
            fn checked_truncate(self) -> Option<$to> {
312
                if self > <$to>::MAX as _ || self < <$to>::MIN as _ {
313
                    None
314
                } else {
315
                    Some(self as _)
316
                }
317
            }
318
        }
319
320
        impl TruncateTarget<$to> for $from {}
321
    )+)*};
322
}
323
324
impl_widen! {
325
    u8 => u8, u16, u32, u64, u128, usize;
326
    u16 => u16, u32, u64, u128, usize;
327
    u32 => u32, u64, u128;
328
    u64 => u64, u128;
329
    u128 => u128;
330
    usize => usize;
331
332
    i8 => i8, i16, i32, i64, i128, isize;
333
    i16 => i16, i32, i64, i128, isize;
334
    i32 => i32, i64, i128;
335
    i64 => i64, i128;
336
    i128 => i128;
337
    isize => isize;
338
}
339
340
impl_truncate! {
341
    u8, u16, u32, u64, u128, usize => u8;
342
    u16, u32, u64, u128, usize => u16;
343
    u32, u64, u128 => u32;
344
    u64, u128 => u64;
345
    u128 => u128;
346
    usize => usize;
347
348
    i8, i16, i32, i64, i128, isize => i8;
349
    i16, i32, i64, i128, isize => i16;
350
    i32, i64, i128 => i32;
351
    i64, i128 => i64;
352
    i128 => i128;
353
    isize => isize;
354
}