-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
cast
function to primitive integers
This commit is a result of the libs team's discussion of #33417 and how it affects integral types. The conclusion was that the motivation for converting integral types, working in a cross-platform code that uses platform-specific integer types, was different enough from the intent of `TryFrom` that it doesn't make sense to unify the paths. As a result this is a proposal for the alternative version of the API which purely works with integral types. An unstable `Cast` trait is added as the implementation detail of this API, and otherwise with this you should be able to call `i32::cast(0u8)` at will. The intention is then to call this in platform-specific contexts like: // Convert from C to Rust let a: c_int = ...; let b: u32 = u32::cast(a)?; // Convert from Rust to C let a: u32 = ...; let b: c_int = <c_int>::cast(a)?; Everything here is unstable for now, but the intention is that this will stabilize sooner than `TryFrom`.
- Loading branch information
1 parent
4450779
commit a6b0068
Showing
9 changed files
with
247 additions
and
90 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# `num_cast` | ||
|
||
The tracking issue for this feature is: [#FIXME] | ||
|
||
[#FIXME]: https://github.com/rust-lang/rust/issues/FIXME | ||
|
||
------------------------ | ||
|
8 changes: 8 additions & 0 deletions
8
src/doc/unstable-book/src/library-features/num_cast_internals.md
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# `num_cast_internals` | ||
|
||
The tracking issue for this feature is: [#FIXME] | ||
|
||
[#FIXME]: https://github.com/rust-lang/rust/issues/FIXME | ||
|
||
------------------------ | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
use fmt; | ||
|
||
/// Internal trait for APIs like `i32::cast`. | ||
#[unstable(feature = "num_cast_internals", issue = "0")] | ||
pub trait Cast<T>: Sized { | ||
/// Internal implementation detail of this trait. | ||
fn cast(t: T) -> Result<Self, CastError>; | ||
} | ||
|
||
/// Error type returned from APIs like `i32::cast`, indicates that a cast could | ||
/// not be performed losslessly. | ||
#[unstable(feature = "num_cast", issue = "0")] | ||
#[derive(Debug)] | ||
pub struct CastError(()); | ||
|
||
#[unstable(feature = "num_cast", issue = "0")] | ||
impl fmt::Display for CastError { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
"failed to losslessly cast integral types".fmt(f) | ||
} | ||
} | ||
|
||
macro_rules! same_sign_cast_int_impl { | ||
($storage:ty, $target:ty, $($source:ty),*) => {$( | ||
#[unstable(feature = "num_cast", issue = "0")] | ||
impl Cast<$source> for $target { | ||
#[inline] | ||
fn cast(u: $source) -> Result<$target, CastError> { | ||
let min = <$target>::min_value() as $storage; | ||
let max = <$target>::max_value() as $storage; | ||
if u as $storage < min || u as $storage > max { | ||
Err(CastError(())) | ||
} else { | ||
Ok(u as $target) | ||
} | ||
} | ||
} | ||
)*} | ||
} | ||
|
||
same_sign_cast_int_impl!(u128, u8, u8, u16, u32, u64, u128, usize); | ||
same_sign_cast_int_impl!(i128, i8, i8, i16, i32, i64, i128, isize); | ||
same_sign_cast_int_impl!(u128, u16, u8, u16, u32, u64, u128, usize); | ||
same_sign_cast_int_impl!(i128, i16, i8, i16, i32, i64, i128, isize); | ||
same_sign_cast_int_impl!(u128, u32, u8, u16, u32, u64, u128, usize); | ||
same_sign_cast_int_impl!(i128, i32, i8, i16, i32, i64, i128, isize); | ||
same_sign_cast_int_impl!(u128, u64, u8, u16, u32, u64, u128, usize); | ||
same_sign_cast_int_impl!(i128, i64, i8, i16, i32, i64, i128, isize); | ||
same_sign_cast_int_impl!(u128, u128, u8, u16, u32, u64, u128, usize); | ||
same_sign_cast_int_impl!(i128, i128, i8, i16, i32, i64, i128, isize); | ||
same_sign_cast_int_impl!(u128, usize, u8, u16, u32, u64, u128, usize); | ||
same_sign_cast_int_impl!(i128, isize, i8, i16, i32, i64, i128, isize); | ||
|
||
macro_rules! cross_sign_cast_int_impl { | ||
($unsigned:ty, $($signed:ty),*) => {$( | ||
#[unstable(feature = "num_cast", issue = "0")] | ||
impl Cast<$unsigned> for $signed { | ||
#[inline] | ||
fn cast(u: $unsigned) -> Result<$signed, CastError> { | ||
let max = <$signed>::max_value() as u128; | ||
if u as u128 > max { | ||
Err(CastError(())) | ||
} else { | ||
Ok(u as $signed) | ||
} | ||
} | ||
} | ||
|
||
#[unstable(feature = "num_cast", issue = "0")] | ||
impl Cast<$signed> for $unsigned { | ||
#[inline] | ||
fn cast(u: $signed) -> Result<$unsigned, CastError> { | ||
let max = <$unsigned>::max_value() as u128; | ||
if u < 0 || u as u128 > max { | ||
Err(CastError(())) | ||
} else { | ||
Ok(u as $unsigned) | ||
} | ||
} | ||
} | ||
)*} | ||
} | ||
|
||
cross_sign_cast_int_impl!(u8, i8, i16, i32, i64, i128, isize); | ||
cross_sign_cast_int_impl!(u16, i8, i16, i32, i64, i128, isize); | ||
cross_sign_cast_int_impl!(u32, i8, i16, i32, i64, i128, isize); | ||
cross_sign_cast_int_impl!(u64, i8, i16, i32, i64, i128, isize); | ||
cross_sign_cast_int_impl!(u128, i8, i16, i32, i64, i128, isize); | ||
cross_sign_cast_int_impl!(usize, i8, i16, i32, i64, i128, isize); |
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
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
Oops, something went wrong.