Last active
October 23, 2019 17:19
-
-
Save kathampy/b988118d555c5ccd0f7e64ae2d3f48db to your computer and use it in GitHub Desktop.
Saturating Casts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
From https://github.com/rust-lang/rust/issues/23596 | |
128-bit support | |
More usize & isize conversions | |
Lossless conversion between usize & isize <-> integers | |
Inlined functions | |
Removed self-casts and primitives with From<T> implementations | |
Note: usize & isize conversions valid on 32-bit & 64-bit word sizes. | |
*/ | |
pub trait PointerCast<T> { | |
fn pointer_cast(self) -> T; | |
} | |
pub trait SaturatingCast<T> { | |
fn saturating_cast(self) -> T; | |
} | |
// Pointer casts that are lossless | |
macro_rules! cast { | |
($src:ty as $($dst:ty),+) => { | |
$(impl PointerCast<$dst> for $src { | |
#[inline] | |
fn pointer_cast(self) -> $dst { | |
self as $dst | |
} | |
})+ | |
} | |
} | |
cast!(i8 as isize); | |
cast!(u8 as isize, usize); | |
cast!(i16 as isize); | |
cast!(u16 as isize, usize); | |
cast!(i32 as isize); | |
#[cfg(target_word_size = "64")] | |
cast!(u32 as isize); | |
cast!(u32 as usize); | |
#[cfg(target_word_size = "64")] | |
cast!(i64 as isize); | |
#[cfg(target_word_size = "64")] | |
cast!(u64 as usize); | |
#[cfg(target_word_size = "32")] | |
cast!(isize as i32); | |
cast!(isize as i64, i128); | |
#[cfg(target_word_size = "32")] | |
cast!(usize as u32, i64); | |
cast!(usize as u64, i128, u128); | |
// Truncation of signed types to unsigned types of larger range | |
macro_rules! trunc_s2u_up { | |
($src:ty as $($dst:ty),+) => { | |
$(impl SaturatingCast<$dst> for $src { | |
#[inline] | |
fn saturating_cast(self) -> $dst { | |
if self >= 0 { | |
self as $dst | |
} else { | |
0 | |
} | |
} | |
})+ | |
} | |
} | |
trunc_s2u_up!(i8 as u8, u16, u32, u64, u128, usize); | |
trunc_s2u_up!(i16 as u16, u32, u64, u128, usize); | |
trunc_s2u_up!(i32 as u32, u64, u128, usize); | |
trunc_s2u_up!(i64 as u64, u128); | |
#[cfg(target_word_size = "64")] | |
trunc_s2u_up!(i64 as usize); | |
trunc_s2u_up!(i128 as u128); | |
#[cfg(target_word_size = "32")] | |
trunc_s2u_up!(isize as u32); | |
trunc_s2u_up!(isize as u64, u128, usize); | |
// Truncation of signed types to types of smaller range | |
macro_rules! trunc_s_down { | |
($src:ty as $($dst:ident),+) => { | |
$(impl SaturatingCast<$dst> for $src { | |
#[inline] | |
fn saturating_cast(self) -> $dst { | |
if self > std::$dst::MAX as $src { | |
std::$dst::MAX | |
} else if self < std::$dst::MIN as $src { | |
std::$dst::MIN | |
} else { | |
self as $dst | |
} | |
} | |
})+ | |
} | |
} | |
trunc_s_down!(i16 as i8, u8); | |
trunc_s_down!(i32 as i8, u8, i16, u16); | |
trunc_s_down!(i64 as i8, u8, i16, u16, i32, u32); | |
#[cfg(target_word_size = "32")] | |
trunc_s_down!(i64 as isize, usize); | |
trunc_s_down!(i128 as i8, u8, i16, u16, i32, u32, i64, u64, isize, usize); | |
trunc_s_down!(isize as i8, u8, i16, u16); | |
#[cfg(target_word_size = "64")] | |
trunc_s_down!(isize as i32, u32); | |
// Truncation of unsigned types to types of smaller range | |
macro_rules! trunc_u_down { | |
($src:ty as $($dst:ident),+) => { | |
$(impl SaturatingCast<$dst> for $src { | |
#[inline] | |
fn saturating_cast(self) -> $dst { | |
if self > std::$dst::MAX as $src { | |
std::$dst::MAX | |
} else { | |
self as $dst | |
} | |
} | |
})+ | |
} | |
} | |
trunc_u_down!(u8 as i8); | |
trunc_u_down!(u16 as i8, u8, i16); | |
trunc_u_down!(u32 as i8, u8, i16, u16, i32); | |
#[cfg(target_word_size = "32")] | |
trunc_u_down!(u32 as isize); | |
trunc_u_down!(u64 as i8, u8, i16, u16, i32, u32, i64, isize); | |
#[cfg(target_word_size = "32")] | |
trunc_u_down!(u64 as usize); | |
trunc_u_down!(u128 as i8, u8, i16, u16, i32, u32, i64, u64, i128, isize, usize); | |
trunc_u_down!(usize as i8, u8, i16, u16, i32, isize); | |
#[cfg(target_word_size = "64")] | |
trunc_u_down!(usize as u32, i64); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment