// Copyright © 2019–2021 Trevor Spiteri // This library is free software: you can redistribute it and/or // modify it under the terms of either // // * the Apache License, Version 2.0 or // * the MIT License // // at your option. // // You should have recieved copies of the Apache License and the MIT // License along with the library. If not, see // and // . /*! # Numeric casts This crate provides casts and checked casts. ## Quick examples ```rust use az::{Az, OverflowingAs, WrappingAs}; use core::num::Wrapping; // Panics on overflow with `debug_assertions`, otherwise wraps assert_eq!(12i32.az::(), 12u32); // Always wraps let wrapped = 1u32.wrapping_neg(); assert_eq!((-1).wrapping_as::(), wrapped); assert_eq!((-1).overflowing_as::(), (wrapped, true)); // Wrapping can also be obtained using `Wrapping` assert_eq!((-1).az::>().0, wrapped); ``` Conversions from floating-point to integers are also supported. Numbers are rounded towards zero, but the [`Round`] wrapper can be used to convert floating-point numbers to integers with rounding to the nearest, with ties rounded to even. ```rust use az::{Az, CheckedAs, Round, SaturatingAs}; use core::f32; assert_eq!(15.7.az::(), 15); assert_eq!(Round(15.5).az::(), 16); assert_eq!(1.5e20.saturating_as::(), i32::max_value()); assert_eq!(f32::NAN.checked_as::(), None); ``` ## Implementing casts for other types To provide casts for another type, you should implement the [`Cast`] trait and if necessary the [`CheckedCast`], [`SaturatingCast`], [`WrappingCast`], [`OverflowingCast`] and [`UnwrappedCast`] traits. The [`Az`], [`CheckedAs`], [`SaturatingAs`], [`WrappingAs`], [`OverflowingAs`] and [`UnwrappedAs`] traits are already implemented for all types using blanket implementations that make use of the former traits. The cast traits can also be implemented for references. This can be useful for expensive types that are not [`Copy`]. For example if you have your own integer type that does not implement [`Copy`], you could implement casts like in the following example. (The type `I` could be an expensive type, for example a bignum integer, but for the example it is only a wrapped [`i32`].) ```rust use az::{Az, Cast}; use core::borrow::Borrow; struct I(i32); impl Cast for &'_ I { fn cast(self) -> i64 { self.0.cast() } } let owned = I(12); assert_eq!((&owned).az::(), 12); // borrow can be used if chaining is required assert_eq!(owned.borrow().az::(), 12); ``` ## Using the *az* crate The *az* crate is available on [crates.io][*az* crate]. To use it in your crate, add it as a dependency inside [*Cargo.toml*]: ```toml [dependencies] az = "1.2" ``` The crate requires rustc version 1.31.0 or later. ## License This crate is free software: you can redistribute it and/or modify it under the terms of either * the [Apache License, Version 2.0][LICENSE-APACHE] or * the [MIT License][LICENSE-MIT] at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache License, Version 2.0, shall be dual licensed as above, without any additional terms or conditions. [*Cargo.toml*]: https://doc.rust-lang.org/cargo/guide/dependencies.html [*az* crate]: https://crates.io/crates/az [LICENSE-APACHE]: https://www.apache.org/licenses/LICENSE-2.0 [LICENSE-MIT]: https://opensource.org/licenses/MIT */ #![no_std] #![warn(missing_docs)] #![doc(html_root_url = "https://docs.rs/az/~1.2")] #![doc(test(attr(deny(warnings))))] #![cfg_attr(feature = "fail-on-warnings", deny(warnings))] #[cfg(test)] extern crate std; mod float; mod int; #[cfg(test)] mod tests; /** Used to cast values. It is normally easier to use the [`Az`] trait instead of this trait. # Panics When debug assertions are enabled, this trait’s method panics if the value does not fit in the destination. When debug assertions are *not* enabled (usual in release mode), the wrapped value can be returned, but it is not considered a breaking change if in the future it panics; if wrapping is required use [`WrappingCast`] instead. This trait’s method also panics with no debug assertions if the value does not fit and cannot be wrapped, for example when trying to cast floating-point ∞ into an integer type. # Examples ```rust use az::Cast; let a: u32 = 5i32.cast(); assert_eq!(a, 5); assert_eq!(Cast::::cast(17.1f32), 17); ``` */ pub trait Cast { /// Casts the value. fn cast(self) -> Dst; } /** Used for checked casts. This trait’s method returns [`None`] if the value does not fit. It is normally easier to use the [`CheckedAs`] trait instead of this trait. # Examples ```rust use az::CheckedCast; use core::f32; let a: Option = 5i32.checked_cast(); assert_eq!(a, Some(5)); assert_eq!(CheckedCast::::checked_cast(-5i32), None); assert_eq!(CheckedCast::::checked_cast(17.1f32), Some(17)); let b: Option = f32::NAN.checked_cast(); assert_eq!(b, None); ``` */ pub trait CheckedCast { /// Casts the value. fn checked_cast(self) -> Option; } /** Used to cast into the destination type, saturating if the value does not fit. It is normally easier to use the [`SaturatingAs`] trait instead of this trait. # Panics This trait’s method panics if the value does not fit and saturation does not make sense, for example when trying to cast floating-point NaN into an integer type. # Examples ```rust use az::SaturatingCast; let a: u32 = (-1).saturating_cast(); assert_eq!(a, 0); assert_eq!(SaturatingCast::::saturating_cast(17.0 + 256.0), 255); ``` */ pub trait SaturatingCast { /// Casts the value. fn saturating_cast(self) -> Dst; } /** Wrapping cast. It is normally easier to use the [`WrappingAs`] trait instead of this trait. # Panics This trait’s method panics if the value does not fit and cannot be wrapped, for example when trying to cast floating-point ∞ into an integer type. # Examples ```rust use az::WrappingCast; let a: u32 = (-1).wrapping_cast(); assert_eq!(a, u32::max_value()); assert_eq!(WrappingCast::::wrapping_cast(17.0 + 256.0), 17); ``` */ pub trait WrappingCast { /// Casts the value. fn wrapping_cast(self) -> Dst; } /** Used for overflowing casts. This trait’s method returns a [tuple] of the value and a [`bool`], indicating whether an overflow has occurred. On overflow, the wrapped value is returned. It is normally easier to use the [`OverflowingAs`] trait instead of this trait. # Examples ```rust use az::OverflowingCast; let a: (u8, bool) = 17i32.overflowing_cast(); assert_eq!(a, (17, false)); assert_eq!(OverflowingCast::::overflowing_cast(-1), (u32::max_value(), true)); assert_eq!(OverflowingCast::::overflowing_cast(17.0 + 256.0), (17, true)); ``` # Panics This trait’s method panics if the value does not fit and cannot be wrapped, for example when trying to cast floating-point ∞ into an integer type. */ pub trait OverflowingCast { /// Casts the value. fn overflowing_cast(self) -> (Dst, bool); } /** Used to cast values, panicking if the value does not fit. It is normally easier to use the [`UnwrappedAs`] trait instead of this trait. # Panics This trait’s method panics if the value does not fit in the destination, even when debug assertions are not enabled. # Examples ```rust use az::UnwrappedCast; let a: u32 = 5i32.unwrapped_cast(); assert_eq!(a, 5); assert_eq!(UnwrappedCast::::unwrapped_cast(17.1f32), 17); ``` The following panics because of overflow. ```rust,should_panic use az::UnwrappedCast; let _overflow: u32 = (-5i32).unwrapped_cast(); ``` */ pub trait UnwrappedCast { /// Casts the value. #[cfg_attr(track_caller, track_caller)] fn unwrapped_cast(self) -> Dst; } /** Used to cast values. This trait enables trait constraints for casting in the opposite direction to [`Cast`]. # Examples ```rust use az::CastFrom; trait Tr { type Assoc: CastFrom; fn assoc_from_u8(a: u8) -> Self::Assoc { CastFrom::cast_from(a) } } impl Tr for () { type Assoc = i8; } assert_eq!(<() as Tr>::assoc_from_u8(5u8), 5i8); ``` */ pub trait CastFrom { /// Casts the value. fn cast_from(src: Src) -> Self; } impl, Dst> CastFrom for Dst { #[inline] #[cfg_attr(track_caller, track_caller)] fn cast_from(src: Src) -> Self { src.cast() } } /** Used for checked casts. This trait enables trait constraints for casting in the opposite direction to [`CheckedCast`]. # Examples ```rust use az::CheckedCastFrom; trait Tr { type Assoc: CheckedCastFrom; fn checked_assoc_from_u8(a: u8) -> Option { CheckedCastFrom::checked_cast_from(a) } } impl Tr for () { type Assoc = i8; } assert_eq!(<() as Tr>::checked_assoc_from_u8(5u8), Some(5i8)); assert_eq!(<() as Tr>::checked_assoc_from_u8(255u8), None); ``` */ pub trait CheckedCastFrom: Sized { /// Casts the value. fn checked_cast_from(src: Src) -> Option; } impl, Dst> CheckedCastFrom for Dst { #[inline] #[cfg_attr(track_caller, track_caller)] fn checked_cast_from(src: Src) -> Option { src.checked_cast() } } /** Used to cast, saturating if the value does not fit. This trait enables trait constraints for casting in the opposite direction to [`SaturatingCast`]. # Examples ```rust use az::SaturatingCastFrom; trait Tr { type Assoc: SaturatingCastFrom; fn saturating_assoc_from_u8(a: u8) -> Self::Assoc { SaturatingCastFrom::saturating_cast_from(a) } } impl Tr for () { type Assoc = i8; } assert_eq!(<() as Tr>::saturating_assoc_from_u8(5u8), 5i8); assert_eq!(<() as Tr>::saturating_assoc_from_u8(255u8), 127i8); ``` */ pub trait SaturatingCastFrom { /// Casts the value. fn saturating_cast_from(src: Src) -> Self; } impl, Dst> SaturatingCastFrom for Dst { #[inline] #[cfg_attr(track_caller, track_caller)] fn saturating_cast_from(src: Src) -> Self { src.saturating_cast() } } /** Wrapping cast. This trait enables trait constraints for casting in the opposite direction to [`WrappingCast`]. # Examples ```rust use az::WrappingCastFrom; trait Tr { type Assoc: WrappingCastFrom; fn wrapping_assoc_from_u8(a: u8) -> Self::Assoc { WrappingCastFrom::wrapping_cast_from(a) } } impl Tr for () { type Assoc = i8; } assert_eq!(<() as Tr>::wrapping_assoc_from_u8(5u8), 5i8); assert_eq!(<() as Tr>::wrapping_assoc_from_u8(255u8), -1i8); ``` */ pub trait WrappingCastFrom { /// Casts the value. fn wrapping_cast_from(src: Src) -> Self; } impl, Dst> WrappingCastFrom for Dst { #[inline] #[cfg_attr(track_caller, track_caller)] fn wrapping_cast_from(src: Src) -> Self { src.wrapping_cast() } } /** Used for overflowing casts. This trait enables trait constraints for casting in the opposite direction to [`OverflowingCast`]. # Examples ```rust use az::OverflowingCastFrom; trait Tr { type Assoc: OverflowingCastFrom; fn overflowing_assoc_from_u8(a: u8) -> (Self::Assoc, bool) { OverflowingCastFrom::overflowing_cast_from(a) } } impl Tr for () { type Assoc = i8; } assert_eq!(<() as Tr>::overflowing_assoc_from_u8(5u8), (5i8, false)); assert_eq!(<() as Tr>::overflowing_assoc_from_u8(255u8), (-1i8, true)); ``` */ pub trait OverflowingCastFrom: Sized { /// Casts the value. fn overflowing_cast_from(src: Src) -> (Self, bool); } impl, Dst> OverflowingCastFrom for Dst { #[inline] #[cfg_attr(track_caller, track_caller)] fn overflowing_cast_from(src: Src) -> (Self, bool) { src.overflowing_cast() } } /** Used to cast values, panicking if the value does not fit. This trait enables trait constraints for casting in the opposite direction to [`UnwrappedCast`]. # Examples ```rust use az::UnwrappedCastFrom; trait Tr { type Assoc: UnwrappedCastFrom; fn unwrapped_assoc_from_u8(a: u8) -> Self::Assoc { UnwrappedCastFrom::unwrapped_cast_from(a) } } impl Tr for () { type Assoc = i8; } assert_eq!(<() as Tr>::unwrapped_assoc_from_u8(5u8), 5i8); ``` The following assertion would panic because of overflow. ```rust, should_panic # use az::UnwrappedCastFrom; # trait Tr { # type Assoc: UnwrappedCastFrom; # fn unwrapped_assoc_from_u8(a: u8) -> Self::Assoc { # UnwrappedCastFrom::unwrapped_cast_from(a) # } # } # impl Tr for () { # type Assoc = i8; # } let _overflow = <() as Tr>::unwrapped_assoc_from_u8(255u8); ``` */ pub trait UnwrappedCastFrom { /// Casts the value. fn unwrapped_cast_from(src: Src) -> Self; } impl, Dst> UnwrappedCastFrom for Dst { #[inline] #[cfg_attr(track_caller, track_caller)] fn unwrapped_cast_from(src: Src) -> Self { src.unwrapped_cast() } } /** Used to cast values. This is a convenience trait to enable writing src.[az][`Az::az`]::<Dst>(). This would not work with the [Cast][`Cast`]::[cast][`Cast::cast`] method because the [`Cast`] trait is generic while its [`cast`][`Cast::cast`] method is not generic. This trait’s method is suitable for chaining. If there is an implementation of [Cast][`Cast`]<Dst> for `&Src` but not for `Src`, and the variable `src` is of type `Src`, then src.[az][`Az::az`]::<Dst>() would not work and (&src).[az][`Az::az`]::<Dst>() is not easy to use with chaining, but src.[borrow][`borrow`]().[az][`Az::az`]::<Dst>() works. # Panics When debug assertions are enabled, this trait’s method panics if the value does not fit in the destination. When debug assertions are *not* enabled (usual in release mode), the wrapped value can be returned, but it is not considered a breaking change if in the future it panics; if wrapping is required use [`WrappingAs`] instead. This trait’s method also panics with no debug assertions if the value does not fit and cannot be wrapped, for example when trying to cast floating-point ∞ into an integer type. # Examples ```rust use az::Az; assert_eq!(5i32.az::(), 5); assert_eq!(17.1f32.az::(), 17); ``` The following example shows how this trait can be used when [`Cast`] is implemented for a reference type. ```rust use az::{Az, Cast}; use core::borrow::Borrow; struct I(i32); impl Cast for &'_ I { fn cast(self) -> i64 { self.0.cast() } } let r = &I(-5); assert_eq!(r.az::(), -5); let owned = I(12); assert_eq!(owned.borrow().az::(), 12); ``` [`borrow`]: `core::borrow::Borrow::borrow` */ pub trait Az { /// Casts the value. fn az(self) -> Dst where Self: Cast; } impl Az for T { #[inline] #[cfg_attr(track_caller, track_caller)] fn az(self) -> Dst where Self: Cast, { self.cast() } } /** Used for checked casts. This trait’s method returns [`None`] if the value does not fit. This is a convenience trait to enable writing src.[checked\_as][`CheckedAs::checked_as`]::<Dst>(). This would not work with the [CheckedCast][`CheckedCast`]::[checked\_cast][`CheckedCast::checked_cast`] method because the [`CheckedCast`] trait is generic while its [`checked_cast`][`CheckedCast::checked_cast`] method is not generic. This trait’s method is suitable for chaining. If there is an implementation of [CheckedCast][`CheckedCast`]<Dst> for `&Src` but not for `Src`, and the variable `src` is of type `Src`, then src.[checked\_as][`CheckedAs::checked_as`]::<Dst>() would not work and (&src).[checked\_as][`CheckedAs::checked_as`]::<Dst>() is not easy to use with chaining, but src.[borrow][`borrow`]().[checked\_as][`CheckedAs::checked_as`]::<Dst>() works. # Examples ```rust use az::CheckedAs; use core::f32; assert_eq!(5i32.checked_as::(), Some(5)); assert_eq!((-5i32).checked_as::(), None); assert_eq!(17.1f32.checked_as::(), Some(17)); assert_eq!(f32::NAN.checked_as::(), None); ``` The following example shows how this trait can be used when [`CheckedCast`] is implemented for a reference type. ```rust use az::{CheckedAs, CheckedCast}; use core::borrow::Borrow; struct I(i32); impl CheckedCast for &'_ I { fn checked_cast(self) -> Option { self.0.checked_cast() } } let r = &I(-5); assert_eq!(r.checked_as::(), None); let owned = I(12); assert_eq!(owned.borrow().checked_as::(), Some(12)); ``` [`borrow`]: `core::borrow::Borrow::borrow` */ pub trait CheckedAs { /// Casts the value. fn checked_as(self) -> Option where Self: CheckedCast; } impl CheckedAs for T { #[inline] #[cfg_attr(track_caller, track_caller)] fn checked_as(self) -> Option where Self: CheckedCast, { self.checked_cast() } } /** Used to cast into the destination type, saturating if the value does not fit. This is a convenience trait to enable writing src.[saturating\_as][`SaturatingAs::saturating_as`]::<Dst>(). This would not work with the [SaturatingCast][`SaturatingCast`]::[saturating\_cast][`SaturatingCast::saturating_cast`] method because the [`SaturatingCast`] trait is generic while its [`SaturatingCast::saturating_cast`] method is not generic. This trait’s method is suitable for chaining. If there is an implementation of [SaturatingCast][`SaturatingCast`]<Dst> for `&Src` but not for `Src`, and the variable `src` is of type `Src`, then src.[saturating\_as][`SaturatingAs::saturating_as`]::<Dst>() would not work and (&src).[saturating\_as][`SaturatingAs::saturating_as`]::<Dst>() is not easy to use with chaining, but src.[borrow][`borrow`]().[saturating\_as][`SaturatingAs::saturating_as`]::<Dst>() works. # Panics This trait’s method panics if the value does not fit and saturation does not make sense, for example when trying to cast floating-point NaN into an integer type. # Examples ```rust use az::SaturatingAs; assert_eq!((-1).saturating_as::(), 0); assert_eq!((17.0 + 256.0).saturating_as::(), 255); ``` The following example shows how this trait can be used when [`SaturatingCast`] is implemented for a reference type. ```rust use az::{SaturatingAs, SaturatingCast}; use core::borrow::Borrow; struct I(i32); impl SaturatingCast for &'_ I { fn saturating_cast(self) -> u32 { self.0.saturating_cast() } } let r = &I(-5); assert_eq!(r.saturating_as::(), 0); let owned = I(12); assert_eq!(owned.borrow().saturating_as::(), 12); ``` [`borrow`]: `core::borrow::Borrow::borrow` */ pub trait SaturatingAs { /// Casts the value. fn saturating_as(self) -> Dst where Self: SaturatingCast; } impl SaturatingAs for T { #[inline] #[cfg_attr(track_caller, track_caller)] fn saturating_as(self) -> Dst where Self: SaturatingCast, { self.saturating_cast() } } /** Wrapping cast. This is a convenience trait to enable writing src.[wrapping\_as][`WrappingAs::wrapping_as`]::<Dst>(). This would not work with the [WrappingCast][`WrappingCast`]::[wrapping\_cast][`WrappingCast::wrapping_cast`] method because the [`WrappingCast`] trait is generic while its [`WrappingCast::wrapping_cast`] method is not generic. This trait’s method is suitable for chaining. If there is an implementation of [WrappingCast][`WrappingCast`]<Dst> for `&Src` but not for `Src`, and the variable `src` is of type `Src`, then src.[wrapping\_as][`WrappingAs::wrapping_as`]::<Dst>() would not work and (&src).[wrapping\_as][`WrappingAs::wrapping_as`]::<Dst>() is not easy to use with chaining, but src.[borrow][`borrow`]().[wrapping\_as][`WrappingAs::wrapping_as`]::<Dst>() works. # Panics This trait’s method panics if the value does not fit and cannot be wrapped, for example when trying to cast floating-point ∞ into an integer type. # Examples ```rust use az::WrappingAs; assert_eq!((-1).wrapping_as::(), u32::max_value()); assert_eq!((17.0 + 256.0).wrapping_as::(), 17); ``` The following example shows how this trait can be used when [`WrappingCast`] is implemented for a reference type. ```rust use az::{WrappingAs, WrappingCast}; use core::borrow::Borrow; struct I(i32); impl WrappingCast for &'_ I { fn wrapping_cast(self) -> u32 { self.0.wrapping_cast() } } let r = &I(-5); assert_eq!(r.wrapping_as::(), 5u32.wrapping_neg()); let owned = I(12); assert_eq!(owned.borrow().wrapping_as::(), 12); ``` [`borrow`]: `core::borrow::Borrow::borrow` */ pub trait WrappingAs { /// Casts the value. fn wrapping_as(self) -> Dst where Self: WrappingCast; } impl WrappingAs for T { #[inline] #[cfg_attr(track_caller, track_caller)] fn wrapping_as(self) -> Dst where Self: WrappingCast, { self.wrapping_cast() } } /** Used for overflowing casts. This trait’s method returns a [tuple] of the value and a [`bool`], indicating whether an overflow has occurred. On overflow, the wrapped value is returned. This is a convenience trait to enable writing src.[overflowing\_as][`OverflowingAs::overflowing_as`]::<Dst>(). This would not work with the [OverflowingCast][`OverflowingCast`]::[overflowing\_cast][`OverflowingCast::overflowing_cast`] method because the [`OverflowingCast`] trait is generic while its [`OverflowingCast::overflowing_cast`] method is not generic. This trait’s method is suitable for chaining. If there is an implementation of [OverflowingCast][`OverflowingCast`]<Dst> for `&Src` but not for `Src`, and the variable `src` is of type `Src`, then src.[overflowing\_as][`OverflowingAs::overflowing_as`]::<Dst>() would not work and (&src).[overflowing\_as][`OverflowingAs::overflowing_as`]::<Dst>() is not easy to use with chaining, but src.[borrow][`borrow`]().[overflowing\_as][`OverflowingAs::overflowing_as`]::<Dst>() works. # Panics This trait’s method panics if the value does not fit and cannot be wrapped, for example when trying to cast floating-point ∞ into an integer type. # Examples ```rust use az::OverflowingAs; assert_eq!(17i32.overflowing_as::(), (17, false)); assert_eq!((-1).overflowing_as::(), (u32::max_value(), true)); assert_eq!((17.0 + 256.0).overflowing_as::(), (17, true)); ``` The following example shows how this trait can be used when [`OverflowingCast`] is implemented for a reference type. ```rust use az::{OverflowingAs, OverflowingCast}; use core::borrow::Borrow; struct I(i32); impl OverflowingCast for &'_ I { fn overflowing_cast(self) -> (u32, bool) { self.0.overflowing_cast() } } let r = &I(-5); assert_eq!(r.overflowing_as::(), (5u32.wrapping_neg(), true)); let owned = I(12); assert_eq!(owned.borrow().overflowing_as::(), (12, false)); ``` [`borrow`]: `core::borrow::Borrow::borrow` */ pub trait OverflowingAs { /// Casts the value. fn overflowing_as(self) -> (Dst, bool) where Self: OverflowingCast; } impl OverflowingAs for T { #[inline] #[cfg_attr(track_caller, track_caller)] fn overflowing_as(self) -> (Dst, bool) where Self: OverflowingCast, { self.overflowing_cast() } } /** Used to cast values, panicking if the value does not fit. This is a convenience trait to enable writing src.[unwrapped\_as][`UnwrappedAs::unwrapped_as`]::<Dst>(). This would not work with the [UnwrappedCast][`UnwrappedCast`]::[unwrapped\_cast][`UnwrappedCast::unwrapped_cast`] method because the [`UnwrappedCast`] trait is generic while its [`UnwrappedCast::unwrapped_cast`] method is not generic. This trait’s method is suitable for chaining. If there is an implementation of [UnwrappedCast][`UnwrappedCast`]<Dst> for `&Src` but not for `Src`, and the variable `src` is of type `Src`, then src.[unwrapped\_as][`UnwrappedAs::unwrapped_as`]::<Dst>() would not work and (&src).[unwrapped\_as][`UnwrappedAs::unwrapped_as`]::<Dst>() is not easy to use with chaining, but src.[borrow][`borrow`]().[unwrapped\_as][`UnwrappedAs::unwrapped_as`]::<Dst>() works. # Panics This trait’s method panics if the value does not fit in the destination, even when debug assertions are not enabled. # Examples ```rust use az::UnwrappedAs; assert_eq!(5i32.unwrapped_as::(), 5); assert_eq!(17.1f32.unwrapped_as::(), 17); ``` The following panics because of overflow. ```rust,should_panic use az::UnwrappedAs; let _overflow = (-5i32).unwrapped_as::(); ``` The following example shows how this trait can be used when [`UnwrappedCast`] is implemented for a reference type. ```rust use az::{UnwrappedAs, UnwrappedCast}; use core::borrow::Borrow; struct I(i32); impl UnwrappedCast for &'_ I { fn unwrapped_cast(self) -> i64 { self.0.unwrapped_cast() } } let r = &I(-5); assert_eq!(r.unwrapped_as::(), -5); let owned = I(12); assert_eq!(owned.borrow().unwrapped_as::(), 12); ``` [`borrow`]: `core::borrow::Borrow::borrow` */ pub trait UnwrappedAs { /// Casts the value. #[cfg_attr(track_caller, track_caller)] fn unwrapped_as(self) -> Dst where Self: UnwrappedCast; } impl UnwrappedAs for T { #[inline] fn unwrapped_as(self) -> Dst where Self: UnwrappedCast, { self.unwrapped_cast() } } /// Casts the value. /// /// # Panics /// /// When debug assertions are enabled, panics if the value does not /// fit in the destination. When debug assertions are *not* enabled /// (usual in release mode), the wrapped value can be returned, but it /// is not considered a breaking change if in the future it panics; if /// wrapping is required use [`wrapping_cast`] instead. /// /// This function also panics with no debug assertions if the value /// does not fit and cannot be wrapped, for example when trying to /// cast floating-point ∞ into an integer type. /// /// # Examples /// /// ```rust /// assert_eq!(az::cast::(5), 5); /// assert_eq!(az::cast::(17.1), 17); /// ``` #[inline] #[cfg_attr(track_caller, track_caller)] pub fn cast, Dst>(src: Src) -> Dst { src.cast() } /// Casts the value, returning [`None`] if the value does not fit. /// /// # Examples /// /// ```rust /// use core::f32; /// /// assert_eq!(az::checked_cast::(5), Some(5)); /// assert_eq!(az::checked_cast::(-5), None); /// assert_eq!(az::checked_cast::(17.1), Some(17)); /// assert_eq!(az::checked_cast::(f32::NAN), None); /// ``` #[inline] #[cfg_attr(track_caller, track_caller)] pub fn checked_cast, Dst>(src: Src) -> Option { src.checked_cast() } /// Casts the value, saturating if the value does not fit. /// /// # Panics /// /// Panics if the value does not fit and saturation does not make /// sense, for example when trying to cast floating-point NaN into an /// integer type. /// /// # Examples /// /// ```rust /// assert_eq!(az::saturating_cast::(-1), 0); /// assert_eq!(az::saturating_cast::(17.0 + 256.0), 255); /// ``` #[inline] #[cfg_attr(track_caller, track_caller)] pub fn saturating_cast, Dst>(src: Src) -> Dst { src.saturating_cast() } /// Casts the value, wrapping on overflow. /// /// # Panics /// /// Panics if the value does not fit and cannot be wrapped, for /// example when trying to cast floating-point ∞ into an integer type. /// /// # Examples /// /// ```rust /// assert_eq!(az::wrapping_cast::(-1), u32::max_value()); /// assert_eq!(az::wrapping_cast::(17.0 + 256.0), 17); /// ``` #[inline] #[cfg_attr(track_caller, track_caller)] pub fn wrapping_cast, Dst>(src: Src) -> Dst { src.wrapping_cast() } /// Overflowing cast. /// /// Returns a [tuple] of the value and a [`bool`], indicating whether /// an overflow has occurred. On overflow, the wrapped value is /// returned. /// /// # Panics /// /// Panics if the value does not fit and cannot be wrapped, for /// example when trying to cast floating-point ∞ into an integer type. /// /// # Examples /// /// ```rust /// assert_eq!(az::overflowing_cast::(-1), (u32::max_value(), true)); /// assert_eq!(az::overflowing_cast::(17.0 + 256.0), (17, true)); /// ``` #[inline] #[cfg_attr(track_caller, track_caller)] pub fn overflowing_cast, Dst>(src: Src) -> (Dst, bool) { src.overflowing_cast() } /// Casts the value, panicking if the value does not fit. /// /// # Panics /// /// Panics if the value does not fit in the destination, even when /// debug assertions are not enabled. /// /// # Examples /// /// ```rust /// assert_eq!(az::unwrapped_cast::(5), 5); /// assert_eq!(az::unwrapped_cast::(17.1), 17); /// ``` /// /// The following panics because of overflow. /// /// ```rust,should_panic /// let _overflow = az::unwrapped_cast::(-5); /// ``` #[inline] #[cfg_attr(track_caller, track_caller)] pub fn unwrapped_cast, Dst>(src: Src) -> Dst { src.unwrapped_cast() } /// Used to convert floating-point numbers to integers with rounding /// to the nearest, with ties rounded to even. /// /// The underlying value can be retrieved through the `.0` index. /// /// # Examples /// /// ```rust /// use az::Round; /// assert_eq!(az::cast::<_, i32>(Round(0.4)), 0); /// assert_eq!(az::cast::<_, i32>(Round(0.6)), 1); /// // ties rounded to even /// assert_eq!(az::cast::<_, i32>(Round(-0.5)), 0); /// assert_eq!(az::cast::<_, i32>(Round(-1.5)), -2); /// ``` #[repr(transparent)] #[derive(Clone, Copy, Default, Eq, PartialEq, PartialOrd, Ord)] pub struct Round(pub T);