japaric / cast.rs Goto Github PK
View Code? Open in Web Editor NEWMachine scalar casting that meets your expectations
License: Apache License 2.0
Machine scalar casting that meets your expectations
License: Apache License 2.0
Using 0.2.1 cast::u64(64f64.exp2())
returns Ok(0)
when it should return Err(Overflow)
just like cast::u32(32f64.exp2())
does.
The issue is
Line 293 in f5ccf5f
u64::MAX
can't be stored exactly in a f64
so is rounded up to 264 causing the >
to return false
.
This applies to all float to int conversions where the number of bits in the destination type is larger than the number of bits in the source mantissa.
use cast::u8;
fn main() {
println!("{:?}", u8(255.0)); // yields Overflow
}
It should be Ok(255)
, of course ๐
Using 0.2.1 cast::i64(-0.1f64)
returns Ok(0)
but cast::u64(-0.1f64)
returns Err(Underflow)
. I would expect the latter to also return Ok(0)
as float to int conversions truncate towards 0 and 0 can be represented in a u64
just fine.
See draft PR #38. All these tests fail regularly when quickcheck
is upgraded to 1.0.3:
test::demoting_to::i16::from::f32
test::demoting_to::i16::from::f64
test::demoting_to::i32::from::f32
test::demoting_to::i32::from::f64
test::demoting_to::i64::from::f32
test::demoting_to::i64::from::f64
test::demoting_to::i8::from::f32
test::demoting_to::i8::from::f64
test::demoting_to::isize::from::f32
test::demoting_to::isize::from::f64
test::demoting_to::u16::from::f32
test::demoting_to::u16::from::f64
test::demoting_to::u32::from::f32
test::demoting_to::u32::from::f64
test::demoting_to::u64::from::f32
test::demoting_to::u64::from::f64
test::demoting_to::u8::from::f32
test::demoting_to::u8::from::f64
test::demoting_to::usize::from::f32
test::demoting_to::usize::from::f64
My initial guess is that the cause is the same bug as described in issue #23, and that quickcheck 1.0.3 provides coverage for the buggy cases.
Most of the casts can only fail with overflow or underflow. Sometimes it would be nice to handle those casts using saturation instead of errors.
It would for instance be nice to have functions such as u8_saturate
, with the property that u8_saturate(1234u16) = 255u8
and u8_saturate(-1u8) = 0u8
.
This crate has quite a lot of conditionals, making it easy to miss updating some parts of the code. This is likely the cause of #29
Please consider adding CI, for example Github Actions to build and test on a range of supported systems, with 32-bit and 64-bit pointers etc.
Please stabilize this feature or at least provide an cfg entry for using it in recent compiler versions
Needed by tests for rust-lang/compiler-builtins#161 .
I would like to have an implementation of the trait tests::cast::From<i128>
for f32
, and similar implementations needed to test i128/u128 <-> float conversion functions
Hello! I'm using the cast
library in some production code, and it's great! I like the way that casts only return Result
if they might fail.
I'm also using the error-chain crate, which provides support for converting many different error types into my library's "official" error type. But for this to work, all error types need to implement the Display
and Error
traits. Would you be interested in a pull request adding support for this to your cast
library?
Thank you for considering this!
Hi, I'd like to use cast.rs
but I'd also like to minimize my dependency tree. I noticed that rustc_version
seems to be used primarily to decide whether to support 128-bit types. But, 128-bit types have been in stable Rust for years. I think it would be a better trade-off to break compatibility with the ancient versions of Rust with a new version that eliminates this conditional check. I would be happy to submit a PR that does this if you agree this makes sense.
Compiling cast 0.2.4 on i686-unknown-linux-gnu target fails to compile. 0.2.3 works fine.
Log:
error[E0432]: unresolved import `Error`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:361:10
|
361 | use {Error, From};
| ^^^^^ no external crate `Error`
error[E0437]: type `Output` is not a member of trait `From`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:192:21
|
192 | type Output = $dst;
| ^^^^^^^^^^^^^^^^^^^ not a member of trait `From`
...
364 | / promotion! {
365 | | i8 => f32, f64, i8, i16, i32, isize, i64;
366 | | i16 => f32, f64, i16, i32, isize, i64;
367 | | i32 => f32, f64, i32, isize, i64;
368 | | isize => f32, f64, i32, isize, i64;
369 | | i64 => f32, f64, i64;
370 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0407]: method `cast` is not a member of trait `From`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:195:21
|
195 | / fn cast(src: $src) -> $dst {
196 | | src as $dst
197 | | }
| |_____________________^ not a member of trait `From`
...
364 | / promotion! {
365 | | i8 => f32, f64, i8, i16, i32, isize, i64;
366 | | i16 => f32, f64, i16, i32, isize, i64;
367 | | i32 => f32, f64, i32, isize, i64;
368 | | isize => f32, f64, i32, isize, i64;
369 | | i64 => f32, f64, i64;
370 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0437]: type `Output` is not a member of trait `From`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:210:21
|
210 | type Output = Result<$dst, Error>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `From`
...
372 | / half_promotion! {
373 | | i8 => u8, u16, u32, usize, u64;
374 | | i16 => u16, u32, usize, u64;
375 | | i32 => u32, usize, u64;
376 | | isize => u32, usize, u64;
377 | | i64 => u64;
378 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0407]: method `cast` is not a member of trait `From`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:213:21
|
213 | / fn cast(src: $src) -> Self::Output {
214 | | if src < 0 {
215 | | Err(Error::Underflow)
216 | | } else {
217 | | Ok(src as $dst)
218 | | }
219 | | }
| |_____________________^ not a member of trait `From`
...
372 | / half_promotion! {
373 | | i8 => u8, u16, u32, usize, u64;
374 | | i16 => u16, u32, usize, u64;
375 | | i32 => u32, usize, u64;
376 | | isize => u32, usize, u64;
377 | | i64 => u64;
378 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0437]: type `Output` is not a member of trait `From`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:256:21
|
256 | type Output = Result<$dst, Error>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `From`
...
380 | / from_signed! {
381 | |
382 | | i16 => i8, u8;
383 | | i32 => i8, i16, u8, u16;
384 | | isize => i8, i16, u8, u16;
385 | | i64 => i8, i16, i32, isize, u8, u16, u32, usize;
386 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0407]: method `cast` is not a member of trait `From`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:259:21
|
259 | / fn cast(src: $src) -> Self::Output {
260 | | use core::$dst;
261 | |
262 | | Err(if src < $dst::MIN as $src {
... |
268 | | })
269 | | }
| |_____________________^ not a member of trait `From`
...
380 | / from_signed! {
381 | |
382 | | i16 => i8, u8;
383 | | i32 => i8, i16, u8, u16;
384 | | isize => i8, i16, u8, u16;
385 | | i64 => i8, i16, i32, isize, u8, u16, u32, usize;
386 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0437]: type `Output` is not a member of trait `From`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:192:21
|
192 | type Output = $dst;
| ^^^^^^^^^^^^^^^^^^^ not a member of trait `From`
...
389 | / promotion! {
390 | | u8 => f32, f64, i16, i32, isize, i64, u8, u16, u32, usize, u64;
391 | | u16 => f32, f64, i32, isize, i64, u16, u32, usize, u64;
392 | | u32 => f32, f64, i64, u32, usize, u64;
393 | | usize => f32, f64, i64, u32, usize, u64;
394 | | u64 => f32, f64, u64;
395 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0407]: method `cast` is not a member of trait `From`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:195:21
|
195 | / fn cast(src: $src) -> $dst {
196 | | src as $dst
197 | | }
| |_____________________^ not a member of trait `From`
...
389 | / promotion! {
390 | | u8 => f32, f64, i16, i32, isize, i64, u8, u16, u32, usize, u64;
391 | | u16 => f32, f64, i32, isize, i64, u16, u32, usize, u64;
392 | | u32 => f32, f64, i64, u32, usize, u64;
393 | | usize => f32, f64, i64, u32, usize, u64;
394 | | u64 => f32, f64, u64;
395 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0437]: type `Output` is not a member of trait `From`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:232:21
|
232 | type Output = Result<$dst, Error>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `From`
...
397 | / from_unsigned! {
398 | | u8 => i8;
399 | | u16 => i8, i16, u8;
400 | | u32 => i8, i16, i32, isize, u8, u16;
401 | | usize => i8, i16, i32, isize, u8, u16;
402 | | u64 => i8, i16, i32, isize, i64, u8, u16, u32, usize;
403 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0407]: method `cast` is not a member of trait `From`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:235:21
|
235 | / fn cast(src: $src) -> Self::Output {
236 | | use core::$dst;
237 | |
238 | | if src > $dst::MAX as $src {
... |
242 | | }
243 | | }
| |_____________________^ not a member of trait `From`
...
397 | / from_unsigned! {
398 | | u8 => i8;
399 | | u16 => i8, i16, u8;
400 | | u32 => i8, i16, i32, isize, u8, u16;
401 | | usize => i8, i16, i32, isize, u8, u16;
402 | | u64 => i8, i16, i32, isize, i64, u8, u16, u32, usize;
403 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0437]: type `Output` is not a member of trait `From`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:192:21
|
192 | type Output = $dst;
| ^^^^^^^^^^^^^^^^^^^ not a member of trait `From`
...
406 | / promotion! {
407 | | f32 => f32, f64;
408 | | f64 => f64;
409 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0407]: method `cast` is not a member of trait `From`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:195:21
|
195 | / fn cast(src: $src) -> $dst {
196 | | src as $dst
197 | | }
| |_____________________^ not a member of trait `From`
...
406 | / promotion! {
407 | | f32 => f32, f64;
408 | | f64 => f64;
409 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0437]: type `Output` is not a member of trait `From`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:282:21
|
282 | type Output = Result<$dst, Error>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `From`
...
411 | / from_float! {
412 | | f32, u32 => i8, i16, i32, isize, i64, u8, u16, u32, usize, u64;
413 | | f64, u64 => i8, i16, i32, isize, i64, u8, u16, u32, usize, u64;
414 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0407]: method `cast` is not a member of trait `From`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:285:21
|
285 | / fn cast(src: $src) -> Self::Output {
286 | | use core::{$dst, $src};
287 | |
288 | | Err(if src != src {
... |
317 | | })
318 | | }
| |_____________________^ not a member of trait `From`
...
411 | / from_float! {
412 | | f32, u32 => i8, i16, i32, isize, i64, u8, u16, u32, usize, u64;
413 | | f64, u64 => i8, i16, i32, isize, i64, u8, u16, u32, usize, u64;
414 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0220]: associated type `Output` not found for `Self`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:213:49
|
213 | fn cast(src: $src) -> Self::Output {
| ^^^^^^ associated type `Output` not found
...
372 | / half_promotion! {
373 | | i8 => u8, u16, u32, usize, u64;
374 | | i16 => u16, u32, usize, u64;
375 | | i32 => u32, usize, u64;
376 | | isize => u32, usize, u64;
377 | | i64 => u64;
378 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0220]: associated type `Output` not found for `Self`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:259:49
|
259 | fn cast(src: $src) -> Self::Output {
| ^^^^^^ associated type `Output` not found
...
380 | / from_signed! {
381 | |
382 | | i16 => i8, u8;
383 | | i32 => i8, i16, u8, u16;
384 | | isize => i8, i16, u8, u16;
385 | | i64 => i8, i16, i32, isize, u8, u16, u32, usize;
386 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0220]: associated type `Output` not found for `Self`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:235:49
|
235 | fn cast(src: $src) -> Self::Output {
| ^^^^^^ associated type `Output` not found
...
397 | / from_unsigned! {
398 | | u8 => i8;
399 | | u16 => i8, i16, u8;
400 | | u32 => i8, i16, i32, isize, u8, u16;
401 | | usize => i8, i16, i32, isize, u8, u16;
402 | | u64 => i8, i16, i32, isize, i64, u8, u16, u32, usize;
403 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0220]: associated type `Output` not found for `Self`
--> /home/ubuntu/.cargo/registry/src/github.com-1ecc6299db9ec823/cast-0.2.4/src/lib.rs:285:49
|
285 | fn cast(src: $src) -> Self::Output {
| ^^^^^^ associated type `Output` not found
...
411 | / from_float! {
412 | | f32, u32 => i8, i16, i32, isize, i64, u8, u16, u32, usize, u64;
413 | | f64, u64 => i8, i16, i32, isize, i64, u8, u16, u32, usize, u64;
414 | | }
| |_____- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
The following code compiles on 64-bit targets:
fn main() {
let a: usize = 2;
let b: u32 = cast::u32(a).unwrap();
let c: u64 = cast::u64(a);
let _d: usize = cast::usize(b);
let _e: usize = cast::usize(c);
}
However, it doesn't compile on a 32-bit target:
error[E0599]: no method named `unwrap` found for type `u32` in the current scope
--> src/main.rs:3:31
|
3 | let b: u32 = cast::u32(a).unwrap();
| ^^^^^^
error[E0308]: mismatched types
--> src/main.rs:6:21
|
6 | let _e: usize = cast::usize(c);
| ^^^^^^^^^^^^^^ expected usize, found enum `std::result::Result`
|
= note: expected type `usize`
found type `std::result::Result<usize, cast::Error>`
because the Output
types use Result
or not depending on the target's usize
size.
Is there a way to write code that does checked (when needed) casts between fixed-sized types and usize
that works on both 32-bit and 64-bit platforms?
I might be looking for something returning a Result
on both, relying on inlining and optimization to eliminate the overhead in cases where the conversion turns out to be trivial.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.