/rust/registry/src/index.crates.io-1949cf8c6b5b557f/num-conv-0.2.1/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 | | fn saturating_truncate(self) -> T; |
40 | | fn checked_truncate(self) -> Option<T>; |
41 | | } |
42 | | } |
43 | | |
44 | | /// A type that can be used with turbofish syntax in [`Extend::extend`]. |
45 | | /// |
46 | | /// It is unlikely that you will want to use this trait directly. You are probably looking for the |
47 | | /// [`Extend`] trait. |
48 | | pub trait ExtendTarget<T>: sealed::ExtendTargetSealed<T> {} |
49 | | |
50 | | /// A type that can be used with turbofish syntax in [`Truncate::truncate`]. |
51 | | /// |
52 | | /// It is unlikely that you will want to use this trait directly. You are probably looking for the |
53 | | /// [`Truncate`] trait. |
54 | | pub trait TruncateTarget<T>: sealed::TruncateTargetSealed<T> {} |
55 | | |
56 | | /// Extend to an integer of the same size or larger, preserving its value. |
57 | | /// |
58 | | /// ```rust |
59 | | /// # use num_conv::Extend; |
60 | | /// assert_eq!(0_u8.extend::<u16>(), 0_u16); |
61 | | /// assert_eq!(0_u16.extend::<u32>(), 0_u32); |
62 | | /// assert_eq!(0_u32.extend::<u64>(), 0_u64); |
63 | | /// assert_eq!(0_u64.extend::<u128>(), 0_u128); |
64 | | /// ``` |
65 | | /// |
66 | | /// ```rust |
67 | | /// # use num_conv::Extend; |
68 | | /// assert_eq!((-1_i8).extend::<i16>(), -1_i16); |
69 | | /// assert_eq!((-1_i16).extend::<i32>(), -1_i32); |
70 | | /// assert_eq!((-1_i32).extend::<i64>(), -1_i64); |
71 | | /// assert_eq!((-1_i64).extend::<i128>(), -1_i128); |
72 | | /// ``` |
73 | | pub trait Extend: sealed::Integer { |
74 | | /// Extend an integer to an integer of the same size or larger, preserving its value. |
75 | | fn extend<T>(self) -> T |
76 | | where |
77 | | Self: ExtendTarget<T>; |
78 | | } |
79 | | |
80 | | impl<T: sealed::Integer> Extend for T { |
81 | 38.2k | fn extend<U>(self) -> U |
82 | 38.2k | where |
83 | 38.2k | T: ExtendTarget<U>, |
84 | | { |
85 | 38.2k | sealed::ExtendTargetSealed::extend(self) |
86 | 38.2k | } <u8 as num_conv::Extend>::extend::<usize> Line | Count | Source | 81 | 10.7k | fn extend<U>(self) -> U | 82 | 10.7k | where | 83 | 10.7k | T: ExtendTarget<U>, | 84 | | { | 85 | 10.7k | sealed::ExtendTargetSealed::extend(self) | 86 | 10.7k | } |
<u8 as num_conv::Extend>::extend::<u32> Line | Count | Source | 81 | 7.93k | fn extend<U>(self) -> U | 82 | 7.93k | where | 83 | 7.93k | T: ExtendTarget<U>, | 84 | | { | 85 | 7.93k | sealed::ExtendTargetSealed::extend(self) | 86 | 7.93k | } |
Unexecuted instantiation: <u8 as num_conv::Extend>::extend::<u16> <i16 as num_conv::Extend>::extend::<i32> Line | Count | Source | 81 | 19.5k | fn extend<U>(self) -> U | 82 | 19.5k | where | 83 | 19.5k | T: ExtendTarget<U>, | 84 | | { | 85 | 19.5k | sealed::ExtendTargetSealed::extend(self) | 86 | 19.5k | } |
Unexecuted instantiation: <u16 as num_conv::Extend>::extend::<usize> Unexecuted instantiation: <u16 as num_conv::Extend>::extend::<u32> |
87 | | } |
88 | | |
89 | | /// Truncate to an integer of the same size or smaller. |
90 | | /// |
91 | | /// Preserve the least significant bits with `.truncate()`: |
92 | | /// |
93 | | /// ```rust |
94 | | /// # use num_conv::Truncate; |
95 | | /// assert_eq!(u16::MAX.truncate::<u8>(), u8::MAX); |
96 | | /// assert_eq!(u32::MAX.truncate::<u16>(), u16::MAX); |
97 | | /// assert_eq!(u64::MAX.truncate::<u32>(), u32::MAX); |
98 | | /// assert_eq!(u128::MAX.truncate::<u64>(), u64::MAX); |
99 | | /// ``` |
100 | | /// |
101 | | /// ```rust |
102 | | /// # use num_conv::Truncate; |
103 | | /// assert_eq!((-1_i16).truncate::<i8>(), -1_i8); |
104 | | /// assert_eq!((-1_i32).truncate::<i16>(), -1_i16); |
105 | | /// assert_eq!((-1_i64).truncate::<i32>(), -1_i32); |
106 | | /// assert_eq!((-1_i128).truncate::<i64>(), -1_i64); |
107 | | /// ``` |
108 | | /// |
109 | | /// Saturate to the numeric bounds with `.saturating_truncate()`: |
110 | | /// |
111 | | /// ```rust |
112 | | /// # use num_conv::Truncate; |
113 | | /// assert_eq!(500_u16.saturating_truncate::<u8>(), u8::MAX); |
114 | | /// assert_eq!(u32::MAX.saturating_truncate::<u16>(), u16::MAX); |
115 | | /// assert_eq!(u64::MAX.saturating_truncate::<u32>(), u32::MAX); |
116 | | /// assert_eq!(u128::MAX.saturating_truncate::<u64>(), u64::MAX); |
117 | | /// ``` |
118 | | /// |
119 | | /// ```rust |
120 | | /// # use num_conv::Truncate; |
121 | | /// assert_eq!((-500_i16).saturating_truncate::<i8>(), i8::MIN); |
122 | | /// assert_eq!(i32::MIN.saturating_truncate::<i16>(), i16::MIN); |
123 | | /// assert_eq!(i64::MIN.saturating_truncate::<i32>(), i32::MIN); |
124 | | /// assert_eq!(i128::MIN.saturating_truncate::<i64>(), i64::MIN); |
125 | | /// ``` |
126 | | /// |
127 | | /// Checked with `.checked_truncate()`, returning `None` if the value is out of range: |
128 | | /// |
129 | | /// ```rust |
130 | | /// # use num_conv::Truncate; |
131 | | /// assert_eq!(u16::MAX.checked_truncate::<u8>(), None); |
132 | | /// assert_eq!(u32::MAX.checked_truncate::<u16>(), None); |
133 | | /// assert_eq!(u64::MAX.checked_truncate::<u32>(), None); |
134 | | /// assert_eq!(u128::MAX.checked_truncate::<u64>(), None); |
135 | | /// ``` |
136 | | /// |
137 | | /// ```rust |
138 | | /// # use num_conv::Truncate; |
139 | | /// assert_eq!(i16::MIN.checked_truncate::<i8>(), None); |
140 | | /// assert_eq!(i32::MIN.checked_truncate::<i16>(), None); |
141 | | /// assert_eq!(i64::MIN.checked_truncate::<i32>(), None); |
142 | | /// assert_eq!(i128::MIN.checked_truncate::<i64>(), None); |
143 | | /// ``` |
144 | | pub trait Truncate: sealed::Integer { |
145 | | /// Truncate an integer to an integer of the same size or smaller, preserving the least |
146 | | /// significant bits. |
147 | | fn truncate<T>(self) -> T |
148 | | where |
149 | | Self: TruncateTarget<T>; |
150 | | |
151 | | /// Truncate an integer to an integer of the same size or smaller, saturating to the numeric |
152 | | /// bounds instead of wrapping. |
153 | | fn saturating_truncate<T>(self) -> T |
154 | | where |
155 | | Self: TruncateTarget<T>; |
156 | | |
157 | | /// Truncate an integer to an integer of the same size or smaller, returning `None` if the value |
158 | | /// is out of range. |
159 | | fn checked_truncate<T>(self) -> Option<T> |
160 | | where |
161 | | Self: TruncateTarget<T>; |
162 | | } |
163 | | |
164 | | impl<T: sealed::Integer> Truncate for T { |
165 | 10.5k | fn truncate<U>(self) -> U |
166 | 10.5k | where |
167 | 10.5k | T: TruncateTarget<U>, |
168 | | { |
169 | 10.5k | sealed::TruncateTargetSealed::truncate(self) |
170 | 10.5k | } <usize as num_conv::Truncate>::truncate::<u8> Line | Count | Source | 165 | 5.39k | fn truncate<U>(self) -> U | 166 | 5.39k | where | 167 | 5.39k | T: TruncateTarget<U>, | 168 | | { | 169 | 5.39k | sealed::TruncateTargetSealed::truncate(self) | 170 | 5.39k | } |
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 | 165 | 5.13k | fn truncate<U>(self) -> U | 166 | 5.13k | where | 167 | 5.13k | T: TruncateTarget<U>, | 168 | | { | 169 | 5.13k | sealed::TruncateTargetSealed::truncate(self) | 170 | 5.13k | } |
|
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 | | |
187 | | macro_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 | 38.2k | fn extend(self) -> $to { |
206 | 38.2k | self as _ |
207 | 38.2k | } <u8 as num_conv::sealed::ExtendTargetSealed<usize>>::extend Line | Count | Source | 205 | 10.7k | fn extend(self) -> $to { | 206 | 10.7k | self as _ | 207 | 10.7k | } |
Unexecuted instantiation: <u8 as num_conv::sealed::ExtendTargetSealed<u16>>::extend <u8 as num_conv::sealed::ExtendTargetSealed<u32>>::extend Line | Count | Source | 205 | 7.93k | fn extend(self) -> $to { | 206 | 7.93k | self as _ | 207 | 7.93k | } |
<i16 as num_conv::sealed::ExtendTargetSealed<i32>>::extend Line | Count | Source | 205 | 19.5k | fn extend(self) -> $to { | 206 | 19.5k | self as _ | 207 | 19.5k | } |
Unexecuted instantiation: <u16 as num_conv::sealed::ExtendTargetSealed<u32>>::extend Unexecuted instantiation: <u16 as num_conv::sealed::ExtendTargetSealed<usize>>::extend |
208 | | } |
209 | | |
210 | | impl ExtendTarget<$to> for $from {} |
211 | | )+)*}; |
212 | | } |
213 | | |
214 | | macro_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 | 10.5k | fn truncate(self) -> $to { |
233 | 10.5k | self as _ |
234 | 10.5k | } <usize as num_conv::sealed::TruncateTargetSealed<u8>>::truncate Line | Count | Source | 232 | 5.39k | fn truncate(self) -> $to { | 233 | 5.39k | self as _ | 234 | 5.39k | } |
Unexecuted instantiation: <i32 as num_conv::sealed::TruncateTargetSealed<i8>>::truncate Unexecuted instantiation: <i32 as num_conv::sealed::TruncateTargetSealed<i16>>::truncate <u32 as num_conv::sealed::TruncateTargetSealed<u8>>::truncate Line | Count | Source | 232 | 5.13k | fn truncate(self) -> $to { | 233 | 5.13k | self as _ | 234 | 5.13k | } |
|
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 | | |
261 | | 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 | | |
277 | | 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 | | } |