/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 | | } |