1 | // Copyright © 2019–2021 Trevor Spiteri |
2 | |
3 | // This library is free software: you can redistribute it and/or |
4 | // modify it under the terms of either |
5 | // |
6 | // * the Apache License, Version 2.0 or |
7 | // * the MIT License |
8 | // |
9 | // at your option. |
10 | // |
11 | // You should have recieved copies of the Apache License and the MIT |
12 | // License along with the library. If not, see |
13 | // <https://www.apache.org/licenses/LICENSE-2.0> and |
14 | // <https://opensource.org/licenses/MIT>. |
15 | |
16 | /*! |
17 | # Numeric casts |
18 | |
19 | This crate provides casts and checked casts. |
20 | |
21 | ## Quick examples |
22 | |
23 | ```rust |
24 | use az::{Az, OverflowingAs, WrappingAs}; |
25 | use core::num::Wrapping; |
26 | |
27 | // Panics on overflow with `debug_assertions`, otherwise wraps |
28 | assert_eq!(12i32.az::<u32>(), 12u32); |
29 | |
30 | // Always wraps |
31 | let wrapped = 1u32.wrapping_neg(); |
32 | assert_eq!((-1).wrapping_as::<u32>(), wrapped); |
33 | assert_eq!((-1).overflowing_as::<u32>(), (wrapped, true)); |
34 | |
35 | // Wrapping can also be obtained using `Wrapping` |
36 | assert_eq!((-1).az::<Wrapping<u32>>().0, wrapped); |
37 | ``` |
38 | |
39 | Conversions from floating-point to integers are also supported. |
40 | Numbers are rounded towards zero, but the [`Round`] wrapper can be |
41 | used to convert floating-point numbers to integers with rounding to |
42 | the nearest, with ties rounded to even. |
43 | |
44 | ```rust |
45 | use az::{Az, CheckedAs, Round, SaturatingAs}; |
46 | use core::f32; |
47 | |
48 | assert_eq!(15.7.az::<i32>(), 15); |
49 | assert_eq!(Round(15.5).az::<i32>(), 16); |
50 | assert_eq!(1.5e20.saturating_as::<i32>(), i32::max_value()); |
51 | assert_eq!(f32::NAN.checked_as::<i32>(), None); |
52 | ``` |
53 | |
54 | ## Implementing casts for other types |
55 | |
56 | To provide casts for another type, you should implement the [`Cast`] |
57 | trait and if necessary the [`CheckedCast`], [`SaturatingCast`], |
58 | [`WrappingCast`], [`OverflowingCast`] and [`UnwrappedCast`] traits. |
59 | The [`Az`], [`CheckedAs`], [`SaturatingAs`], [`WrappingAs`], |
60 | [`OverflowingAs`] and [`UnwrappedAs`] traits are already implemented |
61 | for all types using blanket implementations that make use of the |
62 | former traits. |
63 | |
64 | The cast traits can also be implemented for references. This can be |
65 | useful for expensive types that are not [`Copy`]. For example if you |
66 | have your own integer type that does not implement [`Copy`], you could |
67 | implement casts like in the following example. (The type `I` could be |
68 | an expensive type, for example a bignum integer, but for the example |
69 | it is only a wrapped [`i32`].) |
70 | |
71 | ```rust |
72 | use az::{Az, Cast}; |
73 | use core::borrow::Borrow; |
74 | |
75 | struct I(i32); |
76 | impl Cast<i64> for &'_ I { |
77 | fn cast(self) -> i64 { self.0.cast() } |
78 | } |
79 | |
80 | let owned = I(12); |
81 | assert_eq!((&owned).az::<i64>(), 12); |
82 | // borrow can be used if chaining is required |
83 | assert_eq!(owned.borrow().az::<i64>(), 12); |
84 | ``` |
85 | |
86 | ## Using the *az* crate |
87 | |
88 | The *az* crate is available on [crates.io][*az* crate]. To use it in |
89 | your crate, add it as a dependency inside [*Cargo.toml*]: |
90 | |
91 | ```toml |
92 | [dependencies] |
93 | az = "1.2" |
94 | ``` |
95 | |
96 | The crate requires rustc version 1.31.0 or later. |
97 | |
98 | ## License |
99 | |
100 | This crate is free software: you can redistribute it and/or modify it |
101 | under the terms of either |
102 | |
103 | * the [Apache License, Version 2.0][LICENSE-APACHE] or |
104 | * the [MIT License][LICENSE-MIT] |
105 | |
106 | at your option. |
107 | |
108 | ### Contribution |
109 | |
110 | Unless you explicitly state otherwise, any contribution intentionally |
111 | submitted for inclusion in the work by you, as defined in the Apache |
112 | License, Version 2.0, shall be dual licensed as above, without any |
113 | additional terms or conditions. |
114 | |
115 | [*Cargo.toml*]: https://doc.rust-lang.org/cargo/guide/dependencies.html |
116 | [*az* crate]: https://crates.io/crates/az |
117 | [LICENSE-APACHE]: https://www.apache.org/licenses/LICENSE-2.0 |
118 | [LICENSE-MIT]: https://opensource.org/licenses/MIT |
119 | */ |
120 | #![no_std ] |
121 | #![warn (missing_docs)] |
122 | #![doc (html_root_url = "https://docs.rs/az/~1.2" )] |
123 | #![doc (test(attr(deny(warnings))))] |
124 | #![cfg_attr (feature = "fail-on-warnings" , deny(warnings))] |
125 | |
126 | #[cfg (test)] |
127 | extern crate std; |
128 | |
129 | mod float; |
130 | mod int; |
131 | #[cfg (test)] |
132 | mod tests; |
133 | |
134 | /** |
135 | Used to cast values. |
136 | |
137 | It is normally easier to use the [`Az`] trait instead of this trait. |
138 | |
139 | # Panics |
140 | |
141 | When debug assertions are enabled, this trait’s method panics if the |
142 | value does not fit in the destination. When debug assertions are *not* |
143 | enabled (usual in release mode), the wrapped value can be returned, |
144 | but it is not considered a breaking change if in the future it panics; |
145 | if wrapping is required use [`WrappingCast`] instead. |
146 | |
147 | This trait’s method also panics with no debug assertions if the value |
148 | does not fit and cannot be wrapped, for example when trying to cast |
149 | floating-point ∞ into an integer type. |
150 | |
151 | # Examples |
152 | |
153 | ```rust |
154 | use az::Cast; |
155 | let a: u32 = 5i32.cast(); |
156 | assert_eq!(a, 5); |
157 | assert_eq!(Cast::<u8>::cast(17.1f32), 17); |
158 | ``` |
159 | */ |
160 | pub trait Cast<Dst> { |
161 | /// Casts the value. |
162 | fn cast(self) -> Dst; |
163 | } |
164 | |
165 | /** |
166 | Used for checked casts. |
167 | |
168 | This trait’s method returns [`None`] if the value does not fit. |
169 | |
170 | It is normally easier to use the [`CheckedAs`] trait instead of this trait. |
171 | |
172 | # Examples |
173 | |
174 | ```rust |
175 | use az::CheckedCast; |
176 | use core::f32; |
177 | |
178 | let a: Option<u32> = 5i32.checked_cast(); |
179 | assert_eq!(a, Some(5)); |
180 | assert_eq!(CheckedCast::<u32>::checked_cast(-5i32), None); |
181 | assert_eq!(CheckedCast::<u8>::checked_cast(17.1f32), Some(17)); |
182 | let b: Option<u8> = f32::NAN.checked_cast(); |
183 | assert_eq!(b, None); |
184 | ``` |
185 | */ |
186 | pub trait CheckedCast<Dst> { |
187 | /// Casts the value. |
188 | fn checked_cast(self) -> Option<Dst>; |
189 | } |
190 | |
191 | /** |
192 | Used to cast into the destination type, saturating if the value does not fit. |
193 | |
194 | It is normally easier to use the [`SaturatingAs`] trait instead of this trait. |
195 | |
196 | # Panics |
197 | |
198 | This trait’s method panics if the value does not fit and saturation |
199 | does not make sense, for example when trying to cast floating-point |
200 | NaN into an integer type. |
201 | |
202 | # Examples |
203 | |
204 | ```rust |
205 | use az::SaturatingCast; |
206 | let a: u32 = (-1).saturating_cast(); |
207 | assert_eq!(a, 0); |
208 | assert_eq!(SaturatingCast::<u8>::saturating_cast(17.0 + 256.0), 255); |
209 | ``` |
210 | */ |
211 | pub trait SaturatingCast<Dst> { |
212 | /// Casts the value. |
213 | fn saturating_cast(self) -> Dst; |
214 | } |
215 | |
216 | /** |
217 | Wrapping cast. |
218 | |
219 | It is normally easier to use the [`WrappingAs`] trait instead of this trait. |
220 | |
221 | # Panics |
222 | |
223 | This trait’s method panics if the value does not fit and cannot be |
224 | wrapped, for example when trying to cast floating-point ∞ into an |
225 | integer type. |
226 | |
227 | # Examples |
228 | |
229 | ```rust |
230 | use az::WrappingCast; |
231 | let a: u32 = (-1).wrapping_cast(); |
232 | assert_eq!(a, u32::max_value()); |
233 | assert_eq!(WrappingCast::<u8>::wrapping_cast(17.0 + 256.0), 17); |
234 | ``` |
235 | */ |
236 | pub trait WrappingCast<Dst> { |
237 | /// Casts the value. |
238 | fn wrapping_cast(self) -> Dst; |
239 | } |
240 | |
241 | /** |
242 | Used for overflowing casts. |
243 | |
244 | This trait’s method returns a [tuple] of the value and a [`bool`], |
245 | indicating whether an overflow has occurred. On overflow, the wrapped |
246 | value is returned. |
247 | |
248 | It is normally easier to use the [`OverflowingAs`] trait instead of this trait. |
249 | |
250 | # Examples |
251 | |
252 | ```rust |
253 | use az::OverflowingCast; |
254 | let a: (u8, bool) = 17i32.overflowing_cast(); |
255 | assert_eq!(a, (17, false)); |
256 | assert_eq!(OverflowingCast::<u32>::overflowing_cast(-1), (u32::max_value(), true)); |
257 | assert_eq!(OverflowingCast::<u8>::overflowing_cast(17.0 + 256.0), (17, true)); |
258 | ``` |
259 | |
260 | # Panics |
261 | |
262 | This trait’s method panics if the value does not fit and cannot be |
263 | wrapped, for example when trying to cast floating-point ∞ into an |
264 | integer type. |
265 | */ |
266 | pub trait OverflowingCast<Dst> { |
267 | /// Casts the value. |
268 | fn overflowing_cast(self) -> (Dst, bool); |
269 | } |
270 | |
271 | /** |
272 | Used to cast values, panicking if the value does not fit. |
273 | |
274 | It is normally easier to use the [`UnwrappedAs`] trait instead of this trait. |
275 | |
276 | # Panics |
277 | |
278 | This trait’s method panics if the value does not fit in the |
279 | destination, even when debug assertions are not enabled. |
280 | |
281 | # Examples |
282 | |
283 | ```rust |
284 | use az::UnwrappedCast; |
285 | let a: u32 = 5i32.unwrapped_cast(); |
286 | assert_eq!(a, 5); |
287 | assert_eq!(UnwrappedCast::<u8>::unwrapped_cast(17.1f32), 17); |
288 | ``` |
289 | |
290 | The following panics because of overflow. |
291 | |
292 | ```rust,should_panic |
293 | use az::UnwrappedCast; |
294 | let _overflow: u32 = (-5i32).unwrapped_cast(); |
295 | ``` |
296 | */ |
297 | pub trait UnwrappedCast<Dst> { |
298 | /// Casts the value. |
299 | #[cfg_attr (track_caller, track_caller)] |
300 | fn unwrapped_cast(self) -> Dst; |
301 | } |
302 | |
303 | /** |
304 | Used to cast values. |
305 | |
306 | This trait enables trait constraints for casting in the opposite direction to |
307 | [`Cast`]. |
308 | |
309 | # Examples |
310 | |
311 | ```rust |
312 | use az::CastFrom; |
313 | trait Tr { |
314 | type Assoc: CastFrom<u8>; |
315 | fn assoc_from_u8(a: u8) -> Self::Assoc { |
316 | CastFrom::cast_from(a) |
317 | } |
318 | } |
319 | impl Tr for () { |
320 | type Assoc = i8; |
321 | } |
322 | assert_eq!(<() as Tr>::assoc_from_u8(5u8), 5i8); |
323 | ``` |
324 | */ |
325 | pub trait CastFrom<Src> { |
326 | /// Casts the value. |
327 | fn cast_from(src: Src) -> Self; |
328 | } |
329 | |
330 | impl<Src: Cast<Dst>, Dst> CastFrom<Src> for Dst { |
331 | #[inline ] |
332 | #[cfg_attr (track_caller, track_caller)] |
333 | fn cast_from(src: Src) -> Self { |
334 | src.cast() |
335 | } |
336 | } |
337 | |
338 | /** |
339 | Used for checked casts. |
340 | |
341 | This trait enables trait constraints for casting in the opposite direction to |
342 | [`CheckedCast`]. |
343 | |
344 | # Examples |
345 | |
346 | ```rust |
347 | use az::CheckedCastFrom; |
348 | trait Tr { |
349 | type Assoc: CheckedCastFrom<u8>; |
350 | fn checked_assoc_from_u8(a: u8) -> Option<Self::Assoc> { |
351 | CheckedCastFrom::checked_cast_from(a) |
352 | } |
353 | } |
354 | impl Tr for () { |
355 | type Assoc = i8; |
356 | } |
357 | assert_eq!(<() as Tr>::checked_assoc_from_u8(5u8), Some(5i8)); |
358 | assert_eq!(<() as Tr>::checked_assoc_from_u8(255u8), None); |
359 | ``` |
360 | */ |
361 | pub trait CheckedCastFrom<Src>: Sized { |
362 | /// Casts the value. |
363 | fn checked_cast_from(src: Src) -> Option<Self>; |
364 | } |
365 | |
366 | impl<Src: CheckedCast<Dst>, Dst> CheckedCastFrom<Src> for Dst { |
367 | #[inline ] |
368 | #[cfg_attr (track_caller, track_caller)] |
369 | fn checked_cast_from(src: Src) -> Option<Self> { |
370 | src.checked_cast() |
371 | } |
372 | } |
373 | |
374 | /** |
375 | Used to cast, saturating if the value does not fit. |
376 | |
377 | This trait enables trait constraints for casting in the opposite direction to |
378 | [`SaturatingCast`]. |
379 | |
380 | # Examples |
381 | |
382 | ```rust |
383 | use az::SaturatingCastFrom; |
384 | trait Tr { |
385 | type Assoc: SaturatingCastFrom<u8>; |
386 | fn saturating_assoc_from_u8(a: u8) -> Self::Assoc { |
387 | SaturatingCastFrom::saturating_cast_from(a) |
388 | } |
389 | } |
390 | impl Tr for () { |
391 | type Assoc = i8; |
392 | } |
393 | assert_eq!(<() as Tr>::saturating_assoc_from_u8(5u8), 5i8); |
394 | assert_eq!(<() as Tr>::saturating_assoc_from_u8(255u8), 127i8); |
395 | ``` |
396 | */ |
397 | pub trait SaturatingCastFrom<Src> { |
398 | /// Casts the value. |
399 | fn saturating_cast_from(src: Src) -> Self; |
400 | } |
401 | |
402 | impl<Src: SaturatingCast<Dst>, Dst> SaturatingCastFrom<Src> for Dst { |
403 | #[inline ] |
404 | #[cfg_attr (track_caller, track_caller)] |
405 | fn saturating_cast_from(src: Src) -> Self { |
406 | src.saturating_cast() |
407 | } |
408 | } |
409 | |
410 | /** |
411 | Wrapping cast. |
412 | |
413 | This trait enables trait constraints for casting in the opposite direction to |
414 | [`WrappingCast`]. |
415 | |
416 | # Examples |
417 | |
418 | ```rust |
419 | use az::WrappingCastFrom; |
420 | trait Tr { |
421 | type Assoc: WrappingCastFrom<u8>; |
422 | fn wrapping_assoc_from_u8(a: u8) -> Self::Assoc { |
423 | WrappingCastFrom::wrapping_cast_from(a) |
424 | } |
425 | } |
426 | impl Tr for () { |
427 | type Assoc = i8; |
428 | } |
429 | assert_eq!(<() as Tr>::wrapping_assoc_from_u8(5u8), 5i8); |
430 | assert_eq!(<() as Tr>::wrapping_assoc_from_u8(255u8), -1i8); |
431 | ``` |
432 | */ |
433 | pub trait WrappingCastFrom<Src> { |
434 | /// Casts the value. |
435 | fn wrapping_cast_from(src: Src) -> Self; |
436 | } |
437 | |
438 | impl<Src: WrappingCast<Dst>, Dst> WrappingCastFrom<Src> for Dst { |
439 | #[inline ] |
440 | #[cfg_attr (track_caller, track_caller)] |
441 | fn wrapping_cast_from(src: Src) -> Self { |
442 | src.wrapping_cast() |
443 | } |
444 | } |
445 | |
446 | /** |
447 | Used for overflowing casts. |
448 | |
449 | This trait enables trait constraints for casting in the opposite direction to |
450 | [`OverflowingCast`]. |
451 | |
452 | # Examples |
453 | |
454 | ```rust |
455 | use az::OverflowingCastFrom; |
456 | trait Tr { |
457 | type Assoc: OverflowingCastFrom<u8>; |
458 | fn overflowing_assoc_from_u8(a: u8) -> (Self::Assoc, bool) { |
459 | OverflowingCastFrom::overflowing_cast_from(a) |
460 | } |
461 | } |
462 | impl Tr for () { |
463 | type Assoc = i8; |
464 | } |
465 | assert_eq!(<() as Tr>::overflowing_assoc_from_u8(5u8), (5i8, false)); |
466 | assert_eq!(<() as Tr>::overflowing_assoc_from_u8(255u8), (-1i8, true)); |
467 | ``` |
468 | */ |
469 | pub trait OverflowingCastFrom<Src>: Sized { |
470 | /// Casts the value. |
471 | fn overflowing_cast_from(src: Src) -> (Self, bool); |
472 | } |
473 | |
474 | impl<Src: OverflowingCast<Dst>, Dst> OverflowingCastFrom<Src> for Dst { |
475 | #[inline ] |
476 | #[cfg_attr (track_caller, track_caller)] |
477 | fn overflowing_cast_from(src: Src) -> (Self, bool) { |
478 | src.overflowing_cast() |
479 | } |
480 | } |
481 | |
482 | /** |
483 | Used to cast values, panicking if the value does not fit. |
484 | |
485 | This trait enables trait constraints for casting in the opposite direction to |
486 | [`UnwrappedCast`]. |
487 | |
488 | # Examples |
489 | |
490 | ```rust |
491 | use az::UnwrappedCastFrom; |
492 | trait Tr { |
493 | type Assoc: UnwrappedCastFrom<u8>; |
494 | fn unwrapped_assoc_from_u8(a: u8) -> Self::Assoc { |
495 | UnwrappedCastFrom::unwrapped_cast_from(a) |
496 | } |
497 | } |
498 | impl Tr for () { |
499 | type Assoc = i8; |
500 | } |
501 | assert_eq!(<() as Tr>::unwrapped_assoc_from_u8(5u8), 5i8); |
502 | ``` |
503 | |
504 | The following assertion would panic because of overflow. |
505 | |
506 | ```rust, should_panic |
507 | # use az::UnwrappedCastFrom; |
508 | # trait Tr { |
509 | # type Assoc: UnwrappedCastFrom<u8>; |
510 | # fn unwrapped_assoc_from_u8(a: u8) -> Self::Assoc { |
511 | # UnwrappedCastFrom::unwrapped_cast_from(a) |
512 | # } |
513 | # } |
514 | # impl Tr for () { |
515 | # type Assoc = i8; |
516 | # } |
517 | let _overflow = <() as Tr>::unwrapped_assoc_from_u8(255u8); |
518 | ``` |
519 | |
520 | */ |
521 | pub trait UnwrappedCastFrom<Src> { |
522 | /// Casts the value. |
523 | fn unwrapped_cast_from(src: Src) -> Self; |
524 | } |
525 | |
526 | impl<Src: UnwrappedCast<Dst>, Dst> UnwrappedCastFrom<Src> for Dst { |
527 | #[inline ] |
528 | #[cfg_attr (track_caller, track_caller)] |
529 | fn unwrapped_cast_from(src: Src) -> Self { |
530 | src.unwrapped_cast() |
531 | } |
532 | } |
533 | |
534 | /** |
535 | Used to cast values. |
536 | |
537 | This is a convenience trait to enable writing |
538 | <code>src.[az][`Az::az`]::<Dst>()</code>. This would not work with |
539 | the <code>[Cast][`Cast`]::[cast][`Cast::cast`]</code> method because |
540 | the [`Cast`] trait is generic while its [`cast`][`Cast::cast`] method |
541 | is not generic. |
542 | |
543 | This trait’s method is suitable for chaining. |
544 | |
545 | If there is an implementation of |
546 | <code>[Cast][`Cast`]<Dst></code> for `&Src` but not for `Src`, |
547 | and the variable `src` is of type `Src`, then |
548 | <code>src.[az][`Az::az`]::<Dst>()</code> would not work and |
549 | <code>(&src).[az][`Az::az`]::<Dst>()</code> is not easy to use with |
550 | chaining, but |
551 | <code>src.[borrow][`borrow`]().[az][`Az::az`]::<Dst>()</code> works. |
552 | |
553 | # Panics |
554 | |
555 | When debug assertions are enabled, this trait’s method panics if the |
556 | value does not fit in the destination. When debug assertions are *not* |
557 | enabled (usual in release mode), the wrapped value can be returned, |
558 | but it is not considered a breaking change if in the future it panics; |
559 | if wrapping is required use [`WrappingAs`] instead. |
560 | |
561 | This trait’s method also panics with no debug assertions if the value |
562 | does not fit and cannot be wrapped, for example when trying to cast |
563 | floating-point ∞ into an integer type. |
564 | |
565 | # Examples |
566 | |
567 | ```rust |
568 | use az::Az; |
569 | assert_eq!(5i32.az::<u32>(), 5); |
570 | assert_eq!(17.1f32.az::<u8>(), 17); |
571 | ``` |
572 | |
573 | The following example shows how this trait can be used when [`Cast`] |
574 | is implemented for a reference type. |
575 | |
576 | ```rust |
577 | use az::{Az, Cast}; |
578 | use core::borrow::Borrow; |
579 | struct I(i32); |
580 | impl Cast<i64> for &'_ I { |
581 | fn cast(self) -> i64 { self.0.cast() } |
582 | } |
583 | |
584 | let r = &I(-5); |
585 | assert_eq!(r.az::<i64>(), -5); |
586 | let owned = I(12); |
587 | assert_eq!(owned.borrow().az::<i64>(), 12); |
588 | ``` |
589 | |
590 | [`borrow`]: `core::borrow::Borrow::borrow` |
591 | */ |
592 | pub trait Az { |
593 | /// Casts the value. |
594 | fn az<Dst>(self) -> Dst |
595 | where |
596 | Self: Cast<Dst>; |
597 | } |
598 | |
599 | impl<T> Az for T { |
600 | #[inline ] |
601 | #[cfg_attr (track_caller, track_caller)] |
602 | fn az<Dst>(self) -> Dst |
603 | where |
604 | Self: Cast<Dst>, |
605 | { |
606 | self.cast() |
607 | } |
608 | } |
609 | |
610 | /** |
611 | Used for checked casts. |
612 | |
613 | This trait’s method returns [`None`] if the value does not fit. |
614 | |
615 | This is a convenience trait to enable writing |
616 | <code>src.[checked\_as][`CheckedAs::checked_as`]::<Dst>()</code>. This |
617 | would not work with the |
618 | <code>[CheckedCast][`CheckedCast`]::[checked\_cast][`CheckedCast::checked_cast`]</code> |
619 | method because the [`CheckedCast`] trait is generic while its |
620 | [`checked_cast`][`CheckedCast::checked_cast`] method is not generic. |
621 | |
622 | This trait’s method is suitable for chaining. |
623 | |
624 | If there is an implementation of |
625 | <code>[CheckedCast][`CheckedCast`]<Dst></code> for `&Src` but |
626 | not for `Src`, and the variable `src` is of type `Src`, then |
627 | <code>src.[checked\_as][`CheckedAs::checked_as`]::<Dst>()</code> would not |
628 | work and |
629 | <code>(&src).[checked\_as][`CheckedAs::checked_as`]::<Dst>()</code> is not |
630 | easy to use with chaining, but |
631 | <code>src.[borrow][`borrow`]().[checked\_as][`CheckedAs::checked_as`]::<Dst>()</code> |
632 | works. |
633 | |
634 | # Examples |
635 | |
636 | ```rust |
637 | use az::CheckedAs; |
638 | use core::f32; |
639 | |
640 | assert_eq!(5i32.checked_as::<u32>(), Some(5)); |
641 | assert_eq!((-5i32).checked_as::<u32>(), None); |
642 | assert_eq!(17.1f32.checked_as::<u8>(), Some(17)); |
643 | assert_eq!(f32::NAN.checked_as::<u8>(), None); |
644 | ``` |
645 | |
646 | The following example shows how this trait can be used when |
647 | [`CheckedCast`] is implemented for a reference type. |
648 | |
649 | ```rust |
650 | use az::{CheckedAs, CheckedCast}; |
651 | use core::borrow::Borrow; |
652 | struct I(i32); |
653 | impl CheckedCast<u32> for &'_ I { |
654 | fn checked_cast(self) -> Option<u32> { self.0.checked_cast() } |
655 | } |
656 | |
657 | let r = &I(-5); |
658 | assert_eq!(r.checked_as::<u32>(), None); |
659 | let owned = I(12); |
660 | assert_eq!(owned.borrow().checked_as::<u32>(), Some(12)); |
661 | ``` |
662 | |
663 | [`borrow`]: `core::borrow::Borrow::borrow` |
664 | */ |
665 | pub trait CheckedAs { |
666 | /// Casts the value. |
667 | fn checked_as<Dst>(self) -> Option<Dst> |
668 | where |
669 | Self: CheckedCast<Dst>; |
670 | } |
671 | |
672 | impl<T> CheckedAs for T { |
673 | #[inline ] |
674 | #[cfg_attr (track_caller, track_caller)] |
675 | fn checked_as<Dst>(self) -> Option<Dst> |
676 | where |
677 | Self: CheckedCast<Dst>, |
678 | { |
679 | self.checked_cast() |
680 | } |
681 | } |
682 | |
683 | /** |
684 | Used to cast into the destination type, saturating if the value does not fit. |
685 | |
686 | This is a convenience trait to enable writing |
687 | <code>src.[saturating\_as][`SaturatingAs::saturating_as`]::<Dst>()</code>. |
688 | This would not work with the |
689 | <code>[SaturatingCast][`SaturatingCast`]::[saturating\_cast][`SaturatingCast::saturating_cast`]</code> |
690 | method because the [`SaturatingCast`] trait is generic while its |
691 | [`SaturatingCast::saturating_cast`] method is not generic. |
692 | |
693 | This trait’s method is suitable for chaining. |
694 | |
695 | If there is an implementation of |
696 | <code>[SaturatingCast][`SaturatingCast`]<Dst></code> for `&Src` |
697 | but not for `Src`, and the variable `src` is of type `Src`, then |
698 | <code>src.[saturating\_as][`SaturatingAs::saturating_as`]::<Dst>()</code> |
699 | would not work and |
700 | <code>(&src).[saturating\_as][`SaturatingAs::saturating_as`]::<Dst>()</code> |
701 | is not easy to use with chaining, but |
702 | <code>src.[borrow][`borrow`]().[saturating\_as][`SaturatingAs::saturating_as`]::<Dst>()</code> |
703 | works. |
704 | |
705 | # Panics |
706 | |
707 | This trait’s method panics if the value does not fit and saturation |
708 | does not make sense, for example when trying to cast floating-point |
709 | NaN into an integer type. |
710 | |
711 | # Examples |
712 | |
713 | ```rust |
714 | use az::SaturatingAs; |
715 | assert_eq!((-1).saturating_as::<u32>(), 0); |
716 | assert_eq!((17.0 + 256.0).saturating_as::<u8>(), 255); |
717 | ``` |
718 | |
719 | The following example shows how this trait can be used when |
720 | [`SaturatingCast`] is implemented for a reference type. |
721 | |
722 | ```rust |
723 | use az::{SaturatingAs, SaturatingCast}; |
724 | use core::borrow::Borrow; |
725 | struct I(i32); |
726 | impl SaturatingCast<u32> for &'_ I { |
727 | fn saturating_cast(self) -> u32 { self.0.saturating_cast() } |
728 | } |
729 | |
730 | let r = &I(-5); |
731 | assert_eq!(r.saturating_as::<u32>(), 0); |
732 | let owned = I(12); |
733 | assert_eq!(owned.borrow().saturating_as::<u32>(), 12); |
734 | ``` |
735 | |
736 | [`borrow`]: `core::borrow::Borrow::borrow` |
737 | */ |
738 | pub trait SaturatingAs { |
739 | /// Casts the value. |
740 | fn saturating_as<Dst>(self) -> Dst |
741 | where |
742 | Self: SaturatingCast<Dst>; |
743 | } |
744 | |
745 | impl<T> SaturatingAs for T { |
746 | #[inline ] |
747 | #[cfg_attr (track_caller, track_caller)] |
748 | fn saturating_as<Dst>(self) -> Dst |
749 | where |
750 | Self: SaturatingCast<Dst>, |
751 | { |
752 | self.saturating_cast() |
753 | } |
754 | } |
755 | |
756 | /** |
757 | Wrapping cast. |
758 | |
759 | This is a convenience trait to enable writing |
760 | <code>src.[wrapping\_as][`WrappingAs::wrapping_as`]::<Dst>()</code>. This |
761 | would not work with the |
762 | <code>[WrappingCast][`WrappingCast`]::[wrapping\_cast][`WrappingCast::wrapping_cast`]</code> |
763 | method because the [`WrappingCast`] trait is generic while its |
764 | [`WrappingCast::wrapping_cast`] method is not generic. |
765 | |
766 | This trait’s method is suitable for chaining. |
767 | |
768 | If there is an implementation of |
769 | <code>[WrappingCast][`WrappingCast`]<Dst></code> for `&Src` but |
770 | not for `Src`, and the variable `src` is of type `Src`, then |
771 | <code>src.[wrapping\_as][`WrappingAs::wrapping_as`]::<Dst>()</code> would |
772 | not work and |
773 | <code>(&src).[wrapping\_as][`WrappingAs::wrapping_as`]::<Dst>()</code> is |
774 | not easy to use with chaining, but |
775 | <code>src.[borrow][`borrow`]().[wrapping\_as][`WrappingAs::wrapping_as`]::<Dst>()</code> |
776 | works. |
777 | |
778 | # Panics |
779 | |
780 | This trait’s method panics if the value does not fit and cannot be |
781 | wrapped, for example when trying to cast floating-point ∞ into an |
782 | integer type. |
783 | |
784 | # Examples |
785 | |
786 | ```rust |
787 | use az::WrappingAs; |
788 | assert_eq!((-1).wrapping_as::<u32>(), u32::max_value()); |
789 | assert_eq!((17.0 + 256.0).wrapping_as::<u8>(), 17); |
790 | ``` |
791 | |
792 | The following example shows how this trait can be used when |
793 | [`WrappingCast`] is implemented for a reference type. |
794 | |
795 | ```rust |
796 | use az::{WrappingAs, WrappingCast}; |
797 | use core::borrow::Borrow; |
798 | struct I(i32); |
799 | impl WrappingCast<u32> for &'_ I { |
800 | fn wrapping_cast(self) -> u32 { self.0.wrapping_cast() } |
801 | } |
802 | |
803 | let r = &I(-5); |
804 | assert_eq!(r.wrapping_as::<u32>(), 5u32.wrapping_neg()); |
805 | let owned = I(12); |
806 | assert_eq!(owned.borrow().wrapping_as::<u32>(), 12); |
807 | ``` |
808 | |
809 | [`borrow`]: `core::borrow::Borrow::borrow` |
810 | */ |
811 | pub trait WrappingAs { |
812 | /// Casts the value. |
813 | fn wrapping_as<Dst>(self) -> Dst |
814 | where |
815 | Self: WrappingCast<Dst>; |
816 | } |
817 | |
818 | impl<T> WrappingAs for T { |
819 | #[inline ] |
820 | #[cfg_attr (track_caller, track_caller)] |
821 | fn wrapping_as<Dst>(self) -> Dst |
822 | where |
823 | Self: WrappingCast<Dst>, |
824 | { |
825 | self.wrapping_cast() |
826 | } |
827 | } |
828 | |
829 | /** |
830 | Used for overflowing casts. |
831 | |
832 | This trait’s method returns a [tuple] of the value and a [`bool`], |
833 | indicating whether an overflow has occurred. On overflow, the wrapped |
834 | value is returned. |
835 | |
836 | This is a convenience trait to enable writing |
837 | <code>src.[overflowing\_as][`OverflowingAs::overflowing_as`]::<Dst>()</code>. |
838 | This would not work with the |
839 | <code>[OverflowingCast][`OverflowingCast`]::[overflowing\_cast][`OverflowingCast::overflowing_cast`]</code> |
840 | method because the [`OverflowingCast`] trait is generic while its |
841 | [`OverflowingCast::overflowing_cast`] method is not generic. |
842 | |
843 | This trait’s method is suitable for chaining. |
844 | |
845 | If there is an implementation of |
846 | <code>[OverflowingCast][`OverflowingCast`]<Dst></code> for |
847 | `&Src` but not for `Src`, and the variable `src` is of type `Src`, |
848 | then |
849 | <code>src.[overflowing\_as][`OverflowingAs::overflowing_as`]::<Dst>()</code> |
850 | would not work and |
851 | <code>(&src).[overflowing\_as][`OverflowingAs::overflowing_as`]::<Dst>()</code> |
852 | is not easy to use with chaining, but |
853 | <code>src.[borrow][`borrow`]().[overflowing\_as][`OverflowingAs::overflowing_as`]::<Dst>()</code> |
854 | works. |
855 | |
856 | # Panics |
857 | |
858 | This trait’s method panics if the value does not fit and cannot be |
859 | wrapped, for example when trying to cast floating-point ∞ into an |
860 | integer type. |
861 | |
862 | # Examples |
863 | |
864 | ```rust |
865 | use az::OverflowingAs; |
866 | assert_eq!(17i32.overflowing_as::<u8>(), (17, false)); |
867 | assert_eq!((-1).overflowing_as::<u32>(), (u32::max_value(), true)); |
868 | assert_eq!((17.0 + 256.0).overflowing_as::<u8>(), (17, true)); |
869 | ``` |
870 | |
871 | The following example shows how this trait can be used when |
872 | [`OverflowingCast`] is implemented for a reference type. |
873 | |
874 | ```rust |
875 | use az::{OverflowingAs, OverflowingCast}; |
876 | use core::borrow::Borrow; |
877 | struct I(i32); |
878 | impl OverflowingCast<u32> for &'_ I { |
879 | fn overflowing_cast(self) -> (u32, bool) { self.0.overflowing_cast() } |
880 | } |
881 | |
882 | let r = &I(-5); |
883 | assert_eq!(r.overflowing_as::<u32>(), (5u32.wrapping_neg(), true)); |
884 | let owned = I(12); |
885 | assert_eq!(owned.borrow().overflowing_as::<u32>(), (12, false)); |
886 | ``` |
887 | |
888 | [`borrow`]: `core::borrow::Borrow::borrow` |
889 | */ |
890 | pub trait OverflowingAs { |
891 | /// Casts the value. |
892 | fn overflowing_as<Dst>(self) -> (Dst, bool) |
893 | where |
894 | Self: OverflowingCast<Dst>; |
895 | } |
896 | |
897 | impl<T> OverflowingAs for T { |
898 | #[inline ] |
899 | #[cfg_attr (track_caller, track_caller)] |
900 | fn overflowing_as<Dst>(self) -> (Dst, bool) |
901 | where |
902 | Self: OverflowingCast<Dst>, |
903 | { |
904 | self.overflowing_cast() |
905 | } |
906 | } |
907 | |
908 | /** |
909 | Used to cast values, panicking if the value does not fit. |
910 | |
911 | This is a convenience trait to enable writing |
912 | <code>src.[unwrapped\_as][`UnwrappedAs::unwrapped_as`]::<Dst>()</code>. |
913 | This would not work with the |
914 | <code>[UnwrappedCast][`UnwrappedCast`]::[unwrapped\_cast][`UnwrappedCast::unwrapped_cast`]</code> |
915 | method because the [`UnwrappedCast`] trait is generic while its |
916 | [`UnwrappedCast::unwrapped_cast`] method is not generic. |
917 | |
918 | This trait’s method is suitable for chaining. |
919 | |
920 | If there is an implementation of |
921 | <code>[UnwrappedCast][`UnwrappedCast`]<Dst></code> for `&Src` |
922 | but not for `Src`, and the variable `src` is of type `Src`, then |
923 | <code>src.[unwrapped\_as][`UnwrappedAs::unwrapped_as`]::<Dst>()</code> |
924 | would not work and |
925 | <code>(&src).[unwrapped\_as][`UnwrappedAs::unwrapped_as`]::<Dst>()</code> |
926 | is not easy to use with chaining, but |
927 | <code>src.[borrow][`borrow`]().[unwrapped\_as][`UnwrappedAs::unwrapped_as`]::<Dst>()</code> |
928 | works. |
929 | |
930 | # Panics |
931 | |
932 | This trait’s method panics if the value does not fit in the |
933 | destination, even when debug assertions are not enabled. |
934 | |
935 | # Examples |
936 | |
937 | ```rust |
938 | use az::UnwrappedAs; |
939 | assert_eq!(5i32.unwrapped_as::<u32>(), 5); |
940 | assert_eq!(17.1f32.unwrapped_as::<u8>(), 17); |
941 | ``` |
942 | |
943 | The following panics because of overflow. |
944 | |
945 | ```rust,should_panic |
946 | use az::UnwrappedAs; |
947 | let _overflow = (-5i32).unwrapped_as::<u32>(); |
948 | ``` |
949 | |
950 | The following example shows how this trait can be used when |
951 | [`UnwrappedCast`] is implemented for a reference type. |
952 | |
953 | ```rust |
954 | use az::{UnwrappedAs, UnwrappedCast}; |
955 | use core::borrow::Borrow; |
956 | struct I(i32); |
957 | impl UnwrappedCast<i64> for &'_ I { |
958 | fn unwrapped_cast(self) -> i64 { self.0.unwrapped_cast() } |
959 | } |
960 | |
961 | let r = &I(-5); |
962 | assert_eq!(r.unwrapped_as::<i64>(), -5); |
963 | let owned = I(12); |
964 | assert_eq!(owned.borrow().unwrapped_as::<i64>(), 12); |
965 | ``` |
966 | |
967 | [`borrow`]: `core::borrow::Borrow::borrow` |
968 | */ |
969 | pub trait UnwrappedAs { |
970 | /// Casts the value. |
971 | #[cfg_attr (track_caller, track_caller)] |
972 | fn unwrapped_as<Dst>(self) -> Dst |
973 | where |
974 | Self: UnwrappedCast<Dst>; |
975 | } |
976 | |
977 | impl<T> UnwrappedAs for T { |
978 | #[inline ] |
979 | fn unwrapped_as<Dst>(self) -> Dst |
980 | where |
981 | Self: UnwrappedCast<Dst>, |
982 | { |
983 | self.unwrapped_cast() |
984 | } |
985 | } |
986 | |
987 | /// Casts the value. |
988 | /// |
989 | /// # Panics |
990 | /// |
991 | /// When debug assertions are enabled, panics if the value does not |
992 | /// fit in the destination. When debug assertions are *not* enabled |
993 | /// (usual in release mode), the wrapped value can be returned, but it |
994 | /// is not considered a breaking change if in the future it panics; if |
995 | /// wrapping is required use [`wrapping_cast`] instead. |
996 | /// |
997 | /// This function also panics with no debug assertions if the value |
998 | /// does not fit and cannot be wrapped, for example when trying to |
999 | /// cast floating-point ∞ into an integer type. |
1000 | /// |
1001 | /// # Examples |
1002 | /// |
1003 | /// ```rust |
1004 | /// assert_eq!(az::cast::<i32, u32>(5), 5); |
1005 | /// assert_eq!(az::cast::<f32, u8>(17.1), 17); |
1006 | /// ``` |
1007 | #[inline ] |
1008 | #[cfg_attr (track_caller, track_caller)] |
1009 | pub fn cast<Src: Cast<Dst>, Dst>(src: Src) -> Dst { |
1010 | src.cast() |
1011 | } |
1012 | |
1013 | /// Casts the value, returning [`None`] if the value does not fit. |
1014 | /// |
1015 | /// # Examples |
1016 | /// |
1017 | /// ```rust |
1018 | /// use core::f32; |
1019 | /// |
1020 | /// assert_eq!(az::checked_cast::<i32, u32>(5), Some(5)); |
1021 | /// assert_eq!(az::checked_cast::<i32, u32>(-5), None); |
1022 | /// assert_eq!(az::checked_cast::<f32, u8>(17.1), Some(17)); |
1023 | /// assert_eq!(az::checked_cast::<f32, u8>(f32::NAN), None); |
1024 | /// ``` |
1025 | #[inline ] |
1026 | #[cfg_attr (track_caller, track_caller)] |
1027 | pub fn checked_cast<Src: CheckedCast<Dst>, Dst>(src: Src) -> Option<Dst> { |
1028 | src.checked_cast() |
1029 | } |
1030 | |
1031 | /// Casts the value, saturating if the value does not fit. |
1032 | /// |
1033 | /// # Panics |
1034 | /// |
1035 | /// Panics if the value does not fit and saturation does not make |
1036 | /// sense, for example when trying to cast floating-point NaN into an |
1037 | /// integer type. |
1038 | /// |
1039 | /// # Examples |
1040 | /// |
1041 | /// ```rust |
1042 | /// assert_eq!(az::saturating_cast::<i32, u32>(-1), 0); |
1043 | /// assert_eq!(az::saturating_cast::<f32, u8>(17.0 + 256.0), 255); |
1044 | /// ``` |
1045 | #[inline ] |
1046 | #[cfg_attr (track_caller, track_caller)] |
1047 | pub fn saturating_cast<Src: SaturatingCast<Dst>, Dst>(src: Src) -> Dst { |
1048 | src.saturating_cast() |
1049 | } |
1050 | |
1051 | /// Casts the value, wrapping on overflow. |
1052 | /// |
1053 | /// # Panics |
1054 | /// |
1055 | /// Panics if the value does not fit and cannot be wrapped, for |
1056 | /// example when trying to cast floating-point ∞ into an integer type. |
1057 | /// |
1058 | /// # Examples |
1059 | /// |
1060 | /// ```rust |
1061 | /// assert_eq!(az::wrapping_cast::<i32, u32>(-1), u32::max_value()); |
1062 | /// assert_eq!(az::wrapping_cast::<f32, u8>(17.0 + 256.0), 17); |
1063 | /// ``` |
1064 | #[inline ] |
1065 | #[cfg_attr (track_caller, track_caller)] |
1066 | pub fn wrapping_cast<Src: WrappingCast<Dst>, Dst>(src: Src) -> Dst { |
1067 | src.wrapping_cast() |
1068 | } |
1069 | |
1070 | /// Overflowing cast. |
1071 | /// |
1072 | /// Returns a [tuple] of the value and a [`bool`], indicating whether |
1073 | /// an overflow has occurred. On overflow, the wrapped value is |
1074 | /// returned. |
1075 | /// |
1076 | /// # Panics |
1077 | /// |
1078 | /// Panics if the value does not fit and cannot be wrapped, for |
1079 | /// example when trying to cast floating-point ∞ into an integer type. |
1080 | /// |
1081 | /// # Examples |
1082 | /// |
1083 | /// ```rust |
1084 | /// assert_eq!(az::overflowing_cast::<i32, u32>(-1), (u32::max_value(), true)); |
1085 | /// assert_eq!(az::overflowing_cast::<f32, u8>(17.0 + 256.0), (17, true)); |
1086 | /// ``` |
1087 | #[inline ] |
1088 | #[cfg_attr (track_caller, track_caller)] |
1089 | pub fn overflowing_cast<Src: OverflowingCast<Dst>, Dst>(src: Src) -> (Dst, bool) { |
1090 | src.overflowing_cast() |
1091 | } |
1092 | |
1093 | /// Casts the value, panicking if the value does not fit. |
1094 | /// |
1095 | /// # Panics |
1096 | /// |
1097 | /// Panics if the value does not fit in the destination, even when |
1098 | /// debug assertions are not enabled. |
1099 | /// |
1100 | /// # Examples |
1101 | /// |
1102 | /// ```rust |
1103 | /// assert_eq!(az::unwrapped_cast::<i32, u32>(5), 5); |
1104 | /// assert_eq!(az::unwrapped_cast::<f32, u8>(17.1), 17); |
1105 | /// ``` |
1106 | /// |
1107 | /// The following panics because of overflow. |
1108 | /// |
1109 | /// ```rust,should_panic |
1110 | /// let _overflow = az::unwrapped_cast::<i32, u32>(-5); |
1111 | /// ``` |
1112 | #[inline ] |
1113 | #[cfg_attr (track_caller, track_caller)] |
1114 | pub fn unwrapped_cast<Src: UnwrappedCast<Dst>, Dst>(src: Src) -> Dst { |
1115 | src.unwrapped_cast() |
1116 | } |
1117 | |
1118 | /// Used to convert floating-point numbers to integers with rounding |
1119 | /// to the nearest, with ties rounded to even. |
1120 | /// |
1121 | /// The underlying value can be retrieved through the `.0` index. |
1122 | /// |
1123 | /// # Examples |
1124 | /// |
1125 | /// ```rust |
1126 | /// use az::Round; |
1127 | /// assert_eq!(az::cast::<_, i32>(Round(0.4)), 0); |
1128 | /// assert_eq!(az::cast::<_, i32>(Round(0.6)), 1); |
1129 | /// // ties rounded to even |
1130 | /// assert_eq!(az::cast::<_, i32>(Round(-0.5)), 0); |
1131 | /// assert_eq!(az::cast::<_, i32>(Round(-1.5)), -2); |
1132 | /// ``` |
1133 | #[repr (transparent)] |
1134 | #[derive (Clone, Copy, Default, Eq, PartialEq, PartialOrd, Ord)] |
1135 | pub struct Round<T>(pub T); |
1136 | |