az/lib.rs
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
19This crate provides casts and checked casts.
20
21## Quick examples
22
23```rust
24use az::{Az, OverflowingAs, WrappingAs};
25use core::num::Wrapping;
26
27// Panics on overflow with `debug_assertions`, otherwise wraps
28assert_eq!(12i32.az::<u32>(), 12u32);
29
30// Always wraps
31let wrapped = 1u32.wrapping_neg();
32assert_eq!((-1).wrapping_as::<u32>(), wrapped);
33assert_eq!((-1).overflowing_as::<u32>(), (wrapped, true));
34
35// Wrapping can also be obtained using `Wrapping`
36assert_eq!((-1).az::<Wrapping<u32>>().0, wrapped);
37```
38
39Conversions from floating-point to integers are also supported.
40Numbers are rounded towards zero, but the [`Round`] wrapper can be
41used to convert floating-point numbers to integers with rounding to
42the nearest, with ties rounded to even.
43
44```rust
45use az::{Az, CheckedAs, Round, SaturatingAs};
46use core::f32;
47
48assert_eq!(15.7.az::<i32>(), 15);
49assert_eq!(Round(15.5).az::<i32>(), 16);
50assert_eq!(1.5e20.saturating_as::<i32>(), i32::max_value());
51assert_eq!(f32::NAN.checked_as::<i32>(), None);
52```
53
54## Implementing casts for other types
55
56To provide casts for another type, you should implement the [`Cast`]
57trait and if necessary the [`CheckedCast`], [`SaturatingCast`],
58[`WrappingCast`], [`OverflowingCast`] and [`UnwrappedCast`] traits.
59The [`Az`], [`CheckedAs`], [`SaturatingAs`], [`WrappingAs`],
60[`OverflowingAs`] and [`UnwrappedAs`] traits are already implemented
61for all types using blanket implementations that make use of the
62former traits.
63
64The cast traits can also be implemented for references. This can be
65useful for expensive types that are not [`Copy`]. For example if you
66have your own integer type that does not implement [`Copy`], you could
67implement casts like in the following example. (The type `I` could be
68an expensive type, for example a bignum integer, but for the example
69it is only a wrapped [`i32`].)
70
71```rust
72use az::{Az, Cast};
73use core::borrow::Borrow;
74
75struct I(i32);
76impl Cast<i64> for &'_ I {
77 fn cast(self) -> i64 { self.0.cast() }
78}
79
80let owned = I(12);
81assert_eq!((&owned).az::<i64>(), 12);
82// borrow can be used if chaining is required
83assert_eq!(owned.borrow().az::<i64>(), 12);
84```
85
86## Using the *az* crate
87
88The *az* crate is available on [crates.io][*az* crate]. To use it in
89your crate, add it as a dependency inside [*Cargo.toml*]:
90
91```toml
92[dependencies]
93az = "1.2"
94```
95
96The crate requires rustc version 1.31.0 or later.
97
98## License
99
100This crate is free software: you can redistribute it and/or modify it
101under the terms of either
102
103 * the [Apache License, Version 2.0][LICENSE-APACHE] or
104 * the [MIT License][LICENSE-MIT]
105
106at your option.
107
108### Contribution
109
110Unless you explicitly state otherwise, any contribution intentionally
111submitted for inclusion in the work by you, as defined in the Apache
112License, Version 2.0, shall be dual licensed as above, without any
113additional 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)]
127extern crate std;
128
129mod float;
130mod int;
131#[cfg(test)]
132mod tests;
133
134/**
135Used to cast values.
136
137It is normally easier to use the [`Az`] trait instead of this trait.
138
139# Panics
140
141When debug assertions are enabled, this trait’s method panics if the
142value does not fit in the destination. When debug assertions are *not*
143enabled (usual in release mode), the wrapped value can be returned,
144but it is not considered a breaking change if in the future it panics;
145if wrapping is required use [`WrappingCast`] instead.
146
147This trait’s method also panics with no debug assertions if the value
148does not fit and cannot be wrapped, for example when trying to cast
149floating-point ∞ into an integer type.
150
151# Examples
152
153```rust
154use az::Cast;
155let a: u32 = 5i32.cast();
156assert_eq!(a, 5);
157assert_eq!(Cast::<u8>::cast(17.1f32), 17);
158```
159*/
160pub trait Cast<Dst> {
161 /// Casts the value.
162 fn cast(self) -> Dst;
163}
164
165/**
166Used for checked casts.
167
168This trait’s method returns [`None`] if the value does not fit.
169
170It is normally easier to use the [`CheckedAs`] trait instead of this trait.
171
172# Examples
173
174```rust
175use az::CheckedCast;
176use core::f32;
177
178let a: Option<u32> = 5i32.checked_cast();
179assert_eq!(a, Some(5));
180assert_eq!(CheckedCast::<u32>::checked_cast(-5i32), None);
181assert_eq!(CheckedCast::<u8>::checked_cast(17.1f32), Some(17));
182let b: Option<u8> = f32::NAN.checked_cast();
183assert_eq!(b, None);
184```
185*/
186pub trait CheckedCast<Dst> {
187 /// Casts the value.
188 fn checked_cast(self) -> Option<Dst>;
189}
190
191/**
192Used to cast into the destination type, saturating if the value does not fit.
193
194It is normally easier to use the [`SaturatingAs`] trait instead of this trait.
195
196# Panics
197
198This trait’s method panics if the value does not fit and saturation
199does not make sense, for example when trying to cast floating-point
200NaN into an integer type.
201
202# Examples
203
204```rust
205use az::SaturatingCast;
206let a: u32 = (-1).saturating_cast();
207assert_eq!(a, 0);
208assert_eq!(SaturatingCast::<u8>::saturating_cast(17.0 + 256.0), 255);
209```
210*/
211pub trait SaturatingCast<Dst> {
212 /// Casts the value.
213 fn saturating_cast(self) -> Dst;
214}
215
216/**
217Wrapping cast.
218
219It is normally easier to use the [`WrappingAs`] trait instead of this trait.
220
221# Panics
222
223This trait’s method panics if the value does not fit and cannot be
224wrapped, for example when trying to cast floating-point ∞ into an
225integer type.
226
227# Examples
228
229```rust
230use az::WrappingCast;
231let a: u32 = (-1).wrapping_cast();
232assert_eq!(a, u32::max_value());
233assert_eq!(WrappingCast::<u8>::wrapping_cast(17.0 + 256.0), 17);
234```
235*/
236pub trait WrappingCast<Dst> {
237 /// Casts the value.
238 fn wrapping_cast(self) -> Dst;
239}
240
241/**
242Used for overflowing casts.
243
244This trait’s method returns a [tuple] of the value and a [`bool`],
245indicating whether an overflow has occurred. On overflow, the wrapped
246value is returned.
247
248It is normally easier to use the [`OverflowingAs`] trait instead of this trait.
249
250# Examples
251
252```rust
253use az::OverflowingCast;
254let a: (u8, bool) = 17i32.overflowing_cast();
255assert_eq!(a, (17, false));
256assert_eq!(OverflowingCast::<u32>::overflowing_cast(-1), (u32::max_value(), true));
257assert_eq!(OverflowingCast::<u8>::overflowing_cast(17.0 + 256.0), (17, true));
258```
259
260# Panics
261
262This trait’s method panics if the value does not fit and cannot be
263wrapped, for example when trying to cast floating-point ∞ into an
264integer type.
265*/
266pub trait OverflowingCast<Dst> {
267 /// Casts the value.
268 fn overflowing_cast(self) -> (Dst, bool);
269}
270
271/**
272Used to cast values, panicking if the value does not fit.
273
274It is normally easier to use the [`UnwrappedAs`] trait instead of this trait.
275
276# Panics
277
278This trait’s method panics if the value does not fit in the
279destination, even when debug assertions are not enabled.
280
281# Examples
282
283```rust
284use az::UnwrappedCast;
285let a: u32 = 5i32.unwrapped_cast();
286assert_eq!(a, 5);
287assert_eq!(UnwrappedCast::<u8>::unwrapped_cast(17.1f32), 17);
288```
289
290The following panics because of overflow.
291
292```rust,should_panic
293use az::UnwrappedCast;
294let _overflow: u32 = (-5i32).unwrapped_cast();
295```
296*/
297pub trait UnwrappedCast<Dst> {
298 /// Casts the value.
299 #[cfg_attr(track_caller, track_caller)]
300 fn unwrapped_cast(self) -> Dst;
301}
302
303/**
304Used to cast values.
305
306This trait enables trait constraints for casting in the opposite direction to
307[`Cast`].
308
309# Examples
310
311```rust
312use az::CastFrom;
313trait Tr {
314 type Assoc: CastFrom<u8>;
315 fn assoc_from_u8(a: u8) -> Self::Assoc {
316 CastFrom::cast_from(a)
317 }
318}
319impl Tr for () {
320 type Assoc = i8;
321}
322assert_eq!(<() as Tr>::assoc_from_u8(5u8), 5i8);
323```
324*/
325pub trait CastFrom<Src> {
326 /// Casts the value.
327 fn cast_from(src: Src) -> Self;
328}
329
330impl<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/**
339Used for checked casts.
340
341This trait enables trait constraints for casting in the opposite direction to
342[`CheckedCast`].
343
344# Examples
345
346```rust
347use az::CheckedCastFrom;
348trait 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}
354impl Tr for () {
355 type Assoc = i8;
356}
357assert_eq!(<() as Tr>::checked_assoc_from_u8(5u8), Some(5i8));
358assert_eq!(<() as Tr>::checked_assoc_from_u8(255u8), None);
359```
360*/
361pub trait CheckedCastFrom<Src>: Sized {
362 /// Casts the value.
363 fn checked_cast_from(src: Src) -> Option<Self>;
364}
365
366impl<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/**
375Used to cast, saturating if the value does not fit.
376
377This trait enables trait constraints for casting in the opposite direction to
378[`SaturatingCast`].
379
380# Examples
381
382```rust
383use az::SaturatingCastFrom;
384trait Tr {
385 type Assoc: SaturatingCastFrom<u8>;
386 fn saturating_assoc_from_u8(a: u8) -> Self::Assoc {
387 SaturatingCastFrom::saturating_cast_from(a)
388 }
389}
390impl Tr for () {
391 type Assoc = i8;
392}
393assert_eq!(<() as Tr>::saturating_assoc_from_u8(5u8), 5i8);
394assert_eq!(<() as Tr>::saturating_assoc_from_u8(255u8), 127i8);
395```
396*/
397pub trait SaturatingCastFrom<Src> {
398 /// Casts the value.
399 fn saturating_cast_from(src: Src) -> Self;
400}
401
402impl<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/**
411Wrapping cast.
412
413This trait enables trait constraints for casting in the opposite direction to
414[`WrappingCast`].
415
416# Examples
417
418```rust
419use az::WrappingCastFrom;
420trait Tr {
421 type Assoc: WrappingCastFrom<u8>;
422 fn wrapping_assoc_from_u8(a: u8) -> Self::Assoc {
423 WrappingCastFrom::wrapping_cast_from(a)
424 }
425}
426impl Tr for () {
427 type Assoc = i8;
428}
429assert_eq!(<() as Tr>::wrapping_assoc_from_u8(5u8), 5i8);
430assert_eq!(<() as Tr>::wrapping_assoc_from_u8(255u8), -1i8);
431```
432*/
433pub trait WrappingCastFrom<Src> {
434 /// Casts the value.
435 fn wrapping_cast_from(src: Src) -> Self;
436}
437
438impl<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/**
447Used for overflowing casts.
448
449This trait enables trait constraints for casting in the opposite direction to
450[`OverflowingCast`].
451
452# Examples
453
454```rust
455use az::OverflowingCastFrom;
456trait 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}
462impl Tr for () {
463 type Assoc = i8;
464}
465assert_eq!(<() as Tr>::overflowing_assoc_from_u8(5u8), (5i8, false));
466assert_eq!(<() as Tr>::overflowing_assoc_from_u8(255u8), (-1i8, true));
467```
468*/
469pub trait OverflowingCastFrom<Src>: Sized {
470 /// Casts the value.
471 fn overflowing_cast_from(src: Src) -> (Self, bool);
472}
473
474impl<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/**
483Used to cast values, panicking if the value does not fit.
484
485This trait enables trait constraints for casting in the opposite direction to
486[`UnwrappedCast`].
487
488# Examples
489
490```rust
491use az::UnwrappedCastFrom;
492trait Tr {
493 type Assoc: UnwrappedCastFrom<u8>;
494 fn unwrapped_assoc_from_u8(a: u8) -> Self::Assoc {
495 UnwrappedCastFrom::unwrapped_cast_from(a)
496 }
497}
498impl Tr for () {
499 type Assoc = i8;
500}
501assert_eq!(<() as Tr>::unwrapped_assoc_from_u8(5u8), 5i8);
502```
503
504The 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# }
517let _overflow = <() as Tr>::unwrapped_assoc_from_u8(255u8);
518```
519
520*/
521pub trait UnwrappedCastFrom<Src> {
522 /// Casts the value.
523 fn unwrapped_cast_from(src: Src) -> Self;
524}
525
526impl<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/**
535Used to cast values.
536
537This is a convenience trait to enable writing
538<code>src.[az][`Az::az`]::<Dst>()</code>. This would not work with
539the <code>[Cast][`Cast`]::[cast][`Cast::cast`]</code> method because
540the [`Cast`] trait is generic while its [`cast`][`Cast::cast`] method
541is not generic.
542
543This trait’s method is suitable for chaining.
544
545If there is an implementation of
546<code>[Cast][`Cast`]<Dst></code> for `&Src` but not for `Src`,
547and 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
550chaining, but
551<code>src.[borrow][`borrow`]().[az][`Az::az`]::<Dst>()</code> works.
552
553# Panics
554
555When debug assertions are enabled, this trait’s method panics if the
556value does not fit in the destination. When debug assertions are *not*
557enabled (usual in release mode), the wrapped value can be returned,
558but it is not considered a breaking change if in the future it panics;
559if wrapping is required use [`WrappingAs`] instead.
560
561This trait’s method also panics with no debug assertions if the value
562does not fit and cannot be wrapped, for example when trying to cast
563floating-point ∞ into an integer type.
564
565# Examples
566
567```rust
568use az::Az;
569assert_eq!(5i32.az::<u32>(), 5);
570assert_eq!(17.1f32.az::<u8>(), 17);
571```
572
573The following example shows how this trait can be used when [`Cast`]
574is implemented for a reference type.
575
576```rust
577use az::{Az, Cast};
578use core::borrow::Borrow;
579struct I(i32);
580impl Cast<i64> for &'_ I {
581 fn cast(self) -> i64 { self.0.cast() }
582}
583
584let r = &I(-5);
585assert_eq!(r.az::<i64>(), -5);
586let owned = I(12);
587assert_eq!(owned.borrow().az::<i64>(), 12);
588```
589
590[`borrow`]: `core::borrow::Borrow::borrow`
591*/
592pub trait Az {
593 /// Casts the value.
594 fn az<Dst>(self) -> Dst
595 where
596 Self: Cast<Dst>;
597}
598
599impl<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/**
611Used for checked casts.
612
613This trait’s method returns [`None`] if the value does not fit.
614
615This is a convenience trait to enable writing
616<code>src.[checked\_as][`CheckedAs::checked_as`]::<Dst>()</code>. This
617would not work with the
618<code>[CheckedCast][`CheckedCast`]::[checked\_cast][`CheckedCast::checked_cast`]</code>
619method because the [`CheckedCast`] trait is generic while its
620[`checked_cast`][`CheckedCast::checked_cast`] method is not generic.
621
622This trait’s method is suitable for chaining.
623
624If there is an implementation of
625<code>[CheckedCast][`CheckedCast`]<Dst></code> for `&Src` but
626not for `Src`, and the variable `src` is of type `Src`, then
627<code>src.[checked\_as][`CheckedAs::checked_as`]::<Dst>()</code> would not
628work and
629<code>(&src).[checked\_as][`CheckedAs::checked_as`]::<Dst>()</code> is not
630easy to use with chaining, but
631<code>src.[borrow][`borrow`]().[checked\_as][`CheckedAs::checked_as`]::<Dst>()</code>
632works.
633
634# Examples
635
636```rust
637use az::CheckedAs;
638use core::f32;
639
640assert_eq!(5i32.checked_as::<u32>(), Some(5));
641assert_eq!((-5i32).checked_as::<u32>(), None);
642assert_eq!(17.1f32.checked_as::<u8>(), Some(17));
643assert_eq!(f32::NAN.checked_as::<u8>(), None);
644```
645
646The following example shows how this trait can be used when
647[`CheckedCast`] is implemented for a reference type.
648
649```rust
650use az::{CheckedAs, CheckedCast};
651use core::borrow::Borrow;
652struct I(i32);
653impl CheckedCast<u32> for &'_ I {
654 fn checked_cast(self) -> Option<u32> { self.0.checked_cast() }
655}
656
657let r = &I(-5);
658assert_eq!(r.checked_as::<u32>(), None);
659let owned = I(12);
660assert_eq!(owned.borrow().checked_as::<u32>(), Some(12));
661```
662
663[`borrow`]: `core::borrow::Borrow::borrow`
664*/
665pub trait CheckedAs {
666 /// Casts the value.
667 fn checked_as<Dst>(self) -> Option<Dst>
668 where
669 Self: CheckedCast<Dst>;
670}
671
672impl<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/**
684Used to cast into the destination type, saturating if the value does not fit.
685
686This is a convenience trait to enable writing
687<code>src.[saturating\_as][`SaturatingAs::saturating_as`]::<Dst>()</code>.
688This would not work with the
689<code>[SaturatingCast][`SaturatingCast`]::[saturating\_cast][`SaturatingCast::saturating_cast`]</code>
690method because the [`SaturatingCast`] trait is generic while its
691[`SaturatingCast::saturating_cast`] method is not generic.
692
693This trait’s method is suitable for chaining.
694
695If there is an implementation of
696<code>[SaturatingCast][`SaturatingCast`]<Dst></code> for `&Src`
697but not for `Src`, and the variable `src` is of type `Src`, then
698<code>src.[saturating\_as][`SaturatingAs::saturating_as`]::<Dst>()</code>
699would not work and
700<code>(&src).[saturating\_as][`SaturatingAs::saturating_as`]::<Dst>()</code>
701is not easy to use with chaining, but
702<code>src.[borrow][`borrow`]().[saturating\_as][`SaturatingAs::saturating_as`]::<Dst>()</code>
703works.
704
705# Panics
706
707This trait’s method panics if the value does not fit and saturation
708does not make sense, for example when trying to cast floating-point
709NaN into an integer type.
710
711# Examples
712
713```rust
714use az::SaturatingAs;
715assert_eq!((-1).saturating_as::<u32>(), 0);
716assert_eq!((17.0 + 256.0).saturating_as::<u8>(), 255);
717```
718
719The following example shows how this trait can be used when
720[`SaturatingCast`] is implemented for a reference type.
721
722```rust
723use az::{SaturatingAs, SaturatingCast};
724use core::borrow::Borrow;
725struct I(i32);
726impl SaturatingCast<u32> for &'_ I {
727 fn saturating_cast(self) -> u32 { self.0.saturating_cast() }
728}
729
730let r = &I(-5);
731assert_eq!(r.saturating_as::<u32>(), 0);
732let owned = I(12);
733assert_eq!(owned.borrow().saturating_as::<u32>(), 12);
734```
735
736[`borrow`]: `core::borrow::Borrow::borrow`
737*/
738pub trait SaturatingAs {
739 /// Casts the value.
740 fn saturating_as<Dst>(self) -> Dst
741 where
742 Self: SaturatingCast<Dst>;
743}
744
745impl<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/**
757Wrapping cast.
758
759This is a convenience trait to enable writing
760<code>src.[wrapping\_as][`WrappingAs::wrapping_as`]::<Dst>()</code>. This
761would not work with the
762<code>[WrappingCast][`WrappingCast`]::[wrapping\_cast][`WrappingCast::wrapping_cast`]</code>
763method because the [`WrappingCast`] trait is generic while its
764[`WrappingCast::wrapping_cast`] method is not generic.
765
766This trait’s method is suitable for chaining.
767
768If there is an implementation of
769<code>[WrappingCast][`WrappingCast`]<Dst></code> for `&Src` but
770not for `Src`, and the variable `src` is of type `Src`, then
771<code>src.[wrapping\_as][`WrappingAs::wrapping_as`]::<Dst>()</code> would
772not work and
773<code>(&src).[wrapping\_as][`WrappingAs::wrapping_as`]::<Dst>()</code> is
774not easy to use with chaining, but
775<code>src.[borrow][`borrow`]().[wrapping\_as][`WrappingAs::wrapping_as`]::<Dst>()</code>
776works.
777
778# Panics
779
780This trait’s method panics if the value does not fit and cannot be
781wrapped, for example when trying to cast floating-point ∞ into an
782integer type.
783
784# Examples
785
786```rust
787use az::WrappingAs;
788assert_eq!((-1).wrapping_as::<u32>(), u32::max_value());
789assert_eq!((17.0 + 256.0).wrapping_as::<u8>(), 17);
790```
791
792The following example shows how this trait can be used when
793[`WrappingCast`] is implemented for a reference type.
794
795```rust
796use az::{WrappingAs, WrappingCast};
797use core::borrow::Borrow;
798struct I(i32);
799impl WrappingCast<u32> for &'_ I {
800 fn wrapping_cast(self) -> u32 { self.0.wrapping_cast() }
801}
802
803let r = &I(-5);
804assert_eq!(r.wrapping_as::<u32>(), 5u32.wrapping_neg());
805let owned = I(12);
806assert_eq!(owned.borrow().wrapping_as::<u32>(), 12);
807```
808
809[`borrow`]: `core::borrow::Borrow::borrow`
810*/
811pub trait WrappingAs {
812 /// Casts the value.
813 fn wrapping_as<Dst>(self) -> Dst
814 where
815 Self: WrappingCast<Dst>;
816}
817
818impl<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/**
830Used for overflowing casts.
831
832This trait’s method returns a [tuple] of the value and a [`bool`],
833indicating whether an overflow has occurred. On overflow, the wrapped
834value is returned.
835
836This is a convenience trait to enable writing
837<code>src.[overflowing\_as][`OverflowingAs::overflowing_as`]::<Dst>()</code>.
838This would not work with the
839<code>[OverflowingCast][`OverflowingCast`]::[overflowing\_cast][`OverflowingCast::overflowing_cast`]</code>
840method because the [`OverflowingCast`] trait is generic while its
841[`OverflowingCast::overflowing_cast`] method is not generic.
842
843This trait’s method is suitable for chaining.
844
845If 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`,
848then
849<code>src.[overflowing\_as][`OverflowingAs::overflowing_as`]::<Dst>()</code>
850would not work and
851<code>(&src).[overflowing\_as][`OverflowingAs::overflowing_as`]::<Dst>()</code>
852is not easy to use with chaining, but
853<code>src.[borrow][`borrow`]().[overflowing\_as][`OverflowingAs::overflowing_as`]::<Dst>()</code>
854works.
855
856# Panics
857
858This trait’s method panics if the value does not fit and cannot be
859wrapped, for example when trying to cast floating-point ∞ into an
860integer type.
861
862# Examples
863
864```rust
865use az::OverflowingAs;
866assert_eq!(17i32.overflowing_as::<u8>(), (17, false));
867assert_eq!((-1).overflowing_as::<u32>(), (u32::max_value(), true));
868assert_eq!((17.0 + 256.0).overflowing_as::<u8>(), (17, true));
869```
870
871The following example shows how this trait can be used when
872[`OverflowingCast`] is implemented for a reference type.
873
874```rust
875use az::{OverflowingAs, OverflowingCast};
876use core::borrow::Borrow;
877struct I(i32);
878impl OverflowingCast<u32> for &'_ I {
879 fn overflowing_cast(self) -> (u32, bool) { self.0.overflowing_cast() }
880}
881
882let r = &I(-5);
883assert_eq!(r.overflowing_as::<u32>(), (5u32.wrapping_neg(), true));
884let owned = I(12);
885assert_eq!(owned.borrow().overflowing_as::<u32>(), (12, false));
886```
887
888[`borrow`]: `core::borrow::Borrow::borrow`
889*/
890pub trait OverflowingAs {
891 /// Casts the value.
892 fn overflowing_as<Dst>(self) -> (Dst, bool)
893 where
894 Self: OverflowingCast<Dst>;
895}
896
897impl<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/**
909Used to cast values, panicking if the value does not fit.
910
911This is a convenience trait to enable writing
912<code>src.[unwrapped\_as][`UnwrappedAs::unwrapped_as`]::<Dst>()</code>.
913This would not work with the
914<code>[UnwrappedCast][`UnwrappedCast`]::[unwrapped\_cast][`UnwrappedCast::unwrapped_cast`]</code>
915method because the [`UnwrappedCast`] trait is generic while its
916[`UnwrappedCast::unwrapped_cast`] method is not generic.
917
918This trait’s method is suitable for chaining.
919
920If there is an implementation of
921<code>[UnwrappedCast][`UnwrappedCast`]<Dst></code> for `&Src`
922but not for `Src`, and the variable `src` is of type `Src`, then
923<code>src.[unwrapped\_as][`UnwrappedAs::unwrapped_as`]::<Dst>()</code>
924would not work and
925<code>(&src).[unwrapped\_as][`UnwrappedAs::unwrapped_as`]::<Dst>()</code>
926is not easy to use with chaining, but
927<code>src.[borrow][`borrow`]().[unwrapped\_as][`UnwrappedAs::unwrapped_as`]::<Dst>()</code>
928works.
929
930# Panics
931
932This trait’s method panics if the value does not fit in the
933destination, even when debug assertions are not enabled.
934
935# Examples
936
937```rust
938use az::UnwrappedAs;
939assert_eq!(5i32.unwrapped_as::<u32>(), 5);
940assert_eq!(17.1f32.unwrapped_as::<u8>(), 17);
941```
942
943The following panics because of overflow.
944
945```rust,should_panic
946use az::UnwrappedAs;
947let _overflow = (-5i32).unwrapped_as::<u32>();
948```
949
950The following example shows how this trait can be used when
951[`UnwrappedCast`] is implemented for a reference type.
952
953```rust
954use az::{UnwrappedAs, UnwrappedCast};
955use core::borrow::Borrow;
956struct I(i32);
957impl UnwrappedCast<i64> for &'_ I {
958 fn unwrapped_cast(self) -> i64 { self.0.unwrapped_cast() }
959}
960
961let r = &I(-5);
962assert_eq!(r.unwrapped_as::<i64>(), -5);
963let owned = I(12);
964assert_eq!(owned.borrow().unwrapped_as::<i64>(), 12);
965```
966
967[`borrow`]: `core::borrow::Borrow::borrow`
968*/
969pub 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
977impl<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)]
1009pub 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)]
1027pub 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)]
1047pub 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)]
1066pub 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)]
1089pub 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)]
1114pub 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)]
1135pub struct Round<T>(pub T);