Easy-cast library

Overview

Easy-cast

Test Status Docs

Type conversion, success expected

This library is written to make numeric type conversions easy. Such conversions usually fall into one of the following cases:

  • the conversion must preserve values exactly (use From or Into or Conv or Cast)
  • the conversion is expected to preserve values exactly, though this is not ensured by the types in question (use Conv or Cast)
  • the conversion could fail and must be checked at run-time (use TryFrom or TryInto or Conv::try_conv or [Cast::try_cast])
  • the conversion is from floating point values to integers and should round to the "nearest" integer (use ConvFloat or CastFloat)
  • the conversion is from f32 to f64 or vice-versa; in this case use of as f32 / as f64 is likely acceptable since f32 has special representations for non-finite values and conversion to f64 is exact
  • truncating conversion (modular arithmetic) is desired; in this case as probably does exactly what you want
  • saturating conversion is desired (less common; not supported here)

If you are wondering "why not just use as", there are a few reasons:

  • integer conversions may silently truncate
  • integer conversions to/from signed types silently reinterpret
  • prior to Rust 1.45.0 float-to-int conversions were not fully defined; since this version they use saturating conversion (NaN converts to 0)
  • you want some assurance (at least in debug builds) that the conversion will preserve values correctly without having to proof-read code

When should you not use this library?

  • Only numeric conversions are supported
  • Conversions from floats do not provide fine control of rounding modes
  • This library has not been thoroughly tested correctness

Assertions

All type conversions which are potentially fallible assert on failure in debug builds. In release builds assertions may be omitted, thus making incorrect conversions possible.

If the always_assert feature flag is set, assertions will be turned on in all builds. Some additional feature flags are available for finer-grained control (see Cargo.toml).

MSRV and no_std

The Minumum Supported Rust Version is 1.32.0 (first release of Edition 2018).

By default, std support is required. With default features disabled no_std is supported, but the ConvFloat and CastFloat traits are unavailable. Enabling the libm feature will re-enable these traits.

Copyright and Licence

The COPYRIGHT file includes a list of contributors who claim copyright on this project. This list may be incomplete; new contributors may optionally add themselves to this list.

The easy-cast library is published under the terms of the Apache License, Version 2.0. You may obtain a copy of this licence from the LICENSE file or on the following webpage: https://www.apache.org/licenses/LICENSE-2.0

Comments
  • Document MSRV

    Document MSRV

    Is there a minimal supported Rust version for this crate? It seems to require associated constants, which makes it incompatible with older Rust versions.

    opened by vks 9
  • Conversion from `u32` to `f32` via `cast()` can be inexact

    Conversion from `u32` to `f32` via `cast()` can be inexact

    My understanding from the docs is that conversions via cast() should always be exact, but this is not currently the case.

    let x: f32 = (!0u32).cast();
    println!("{}", !0u32); // prints 4294967295
    println!("{}", x); // prints 4294967300
    
    opened by BartMassey 5
  • Add try_conv and try_cast

    Add try_conv and try_cast

    Closes #4. I see two potential uses for these additional conversions (though didn't yet need them myself):

    1. If the conversion is fallible, and failure should be handled at run-time.
    2. If the conversion may be fallible and we want to ensure a check occurs (without using the always_assert feature).

    ~~TODO: float conversions.~~ Code share with conv is minimal and probably that's for the best.

    I'll just leave this here for now. If @BartMassey or @vks or anyone else wishes to comment, please do.

    opened by dhardy 4
  • MSRV: document and support 1.36.0

    MSRV: document and support 1.36.0

    Closes #9.

    @vks I don't see any no_std tests for rand_distr. Maybe we should rectify that. This will still cause problems with average though, which claims to work without std.

    I guess the easiest solution is to feature-gate float conversions in this crate.

    opened by dhardy 4
  • Better error messages for asserts

    Better error messages for asserts

    I got a little fed up with it not being obvious why an assert triggered, hence this PR.

    Examples:

    thread 'int_casts' panicked at 'cast x: i8 to u8: expected x > 0, found x = -3'
    thread 'int_casts' panicked at 'cast x: u16 to i8: expected x <= 127, found x = 256'
    thread 'int_casts' panicked at 'cast x: isize to i8: expected -128 <= x <= 127, found x = 256'
    thread 'float_casts' panicked at 'cast x: u32 to f32: inexact for x = 4294967295'
    thread 'float_casts' panicked at 'cast x: f64 to i8 (nearest): range error for x = 127.5'
    

    My only concern is that the extra formatting machinery may have some cost. Then again, the design of the library allows removing these "fuses" in release builds if this is deemed appropriate.

    @vks thoughts?

    opened by dhardy 2
  • Provide `TryConv` and `TryCast`

    Provide `TryConv` and `TryCast`

    Would be nice to provide a way to handle cast errors.

    This is especially important since std::convert::TryInto() currently doesn't support conversions from integer to floating types for some reason: it would be nice to have conversions that fail if inexact.

    opened by BartMassey 2
  • Remove restrictions on `isize` and `usize`

    Remove restrictions on `isize` and `usize`

    It seems possible to make this crate work for 16-bit and 128-bit isize with a little more work. I can try to throw together a PR if desired.

    I believe that Rust always requires size_of::<isize>() == size_of::<usize>(), and am pretty sure that all implementations assume that anyhow. I don't have chapter and verse on that, though.

    opened by BartMassey 2
  • Provide crate option for leaving checks on always

    Provide crate option for leaving checks on always

    Currently, this crate uses debug_assert_eq!() for its checks. Would be nice to provide an always crate option so that the checks are on in release mode also. I always want these checks.

    opened by BartMassey 2
  • `assert_digits` is not enabled by `always_assert`

    `assert_digits` is not enabled by `always_assert`

    The following tests failed:

    Running .guix-tests/tests
    
    running 11 tests
    test float_casts ... ok
    test float_trunc ... ok
    test int_casts ... ok
    test int_to_float ... ok
    test int_to_float_inexact - should panic ... FAILED
    test signed_to_unsigned ... ok
    test u32_max_f32 - should panic ... FAILED
    test unsigned_to_signed ... ok
    test float_trunc_fail1 - should panic ... ok
    test signed_to_unsigned_n1 - should panic ... ok
    test unsigned_to_signed_large - should panic ... ok
    
    failures:
    
    ---- int_to_float_inexact stdout ----
    note: test did not panic as expected
    ---- u32_max_f32 stdout ----
    note: test did not panic as expected
    
    failures:
        int_to_float_inexact
        u32_max_f32
    

    even though always_assert was enabled. Enabling assert_digits fixed this. I'd think that always_assert should imply assert_digits.

    opened by emixa-d 1
  • Extend to other types: NonZero*, tuples, arrays, ...?

    Extend to other types: NonZero*, tuples, arrays, ...?

    Currently this library is limited to basic numeric types (f*, i*, u*). Should it remain that way?

    1. std::num::NonZeroU32 etc. are essentially numeric types. So should we support those?
    2. What about numeric and vector types for third-party libraries, behind feature flags?
    3. With a few lines of code we can support tuples ((A, B) → (C, D) where A → C, B → D, also for more elements to some limit) and arrays ([A; N] → [B; N] where A → B). It's easy to add, but may impact compile times.

    Concern: casting as an operation is expected to be transitive: if a → b and b → c then a → c. Supporting additional "numeric" types such as NonZero* is therefore a substantial increase in the number of conversions we must support. (We cannot have this automatically since the type of b must be specified.)

    Concern: properly casting between types from multiple third-party libraries could quickly become over-complex.

    Concern: there is significant appeal in a small, minimal-dependency library.


    Given the above, easy-cast will likely remain limited to standard types. Supporting arrays and small tuples may be desirable.

    opened by dhardy 1
  • Fix conv(0) from int to float

    Fix conv(0) from int to float

    In 0.4.0, this panics:

    f32::conv(0);
    

    The reason: x.leading_zeros() + x.trailing_zeros() is counting every bit twice.

    The easiest fix seems to be to use saturating_sub. If there's a more performant option we can switch later.

    opened by dhardy 1
  • Exact casts from float to int?

    Exact casts from float to int?

    ~~Unless I'm missing something, casts from float to int are currently missing. This is too bad, as these are some of the most problematic casts as provides.~~ (Edit: I was missing something. See below.) Suggested semantics are to only convert from floats that are exact integers (only zero bits after the decimal point) that will fit in the target int.

    No prize for guessing what Rust does with (0.0f32 / 0.0) as u32. :slightly_smiling_face:

    opened by BartMassey 5
Releases(0.5.2)
  • 0.5.2(Dec 22, 2022)

  • 0.5.1(Oct 14, 2022)

  • 0.5.0(Aug 19, 2022)

    • Reorganise code (#20)
    • Bump MSRV to 1.53.0 (#21)
    • Add default implementations of conv methods over equivalent try_conv variant to facilitate custom implementations (#21)
    • Add ConvApprox and CastApprox, supporting approximate conversions with unspecified rounding, implemented for f64 → f32 and all type conversions supported by Conv (#21)
    • Support Conv and ConvFloat for arrays and tuples (#21)
    • Remove impl<T> Conv<T> for T (#21)
    • Add easy_cast::Result type alias (#22)
    • Move traits into new easy_cast::traits public module (#23)
    Source code(tar.gz)
    Source code(zip)
Owner
null
A library that creates a terminal-like window with feature-packed drawing of text and easy input handling. MIRROR.

BearLibTerminal provides a pseudoterminal window with a grid of character cells and a simple yet powerful API for flexible textual output and uncompli

Tommy Ettinger 43 Oct 31, 2022
An easy to use library for pretty print tables of Rust structs and enums.

tabled An easy to use library for pretty printing tables of Rust structs and enums. Table of Contents Usage Settings Style Themes ASCII Psql Github Ma

Maxim Zhiburt 1.3k Jan 9, 2023
An easy-to-use SocketCAN library for Python and C++, built in Rust.

JCAN An easy-to-use SocketCAN library for Python and C++, built in Rust, using cxx-rs and pyo3. Warning: I have never used Rust before and I don't kno

Leigh Oliver 4 Feb 9, 2023
💫 Easy to use, robust Rust library for displaying spinners in the terminal

spinoff an easy to use, robust library for displaying spinners in the terminal ?? Install Add as a dependency to your Cargo.toml: [dependencies] spino

ad4m 401 Jun 24, 2023
Rustato: A powerful, thread-safe global state management library for Rust applications, offering type-safe, reactive state handling with an easy-to-use macro-based API.

Rustato State Manager A generical thread-safe global state manager for Rust Introduction • Features • Installation • Usage • Advanced Usage • Api Refe

BiteCraft 8 Sep 16, 2024
Call is an easy-to-use command tools for remote development.

Call is an easy-to-use command tools for remote development. It helps you to build remote development easily and elegant. It can work with makefile and justfile.

null 21 Dec 14, 2022
The dead easy way to use config files in your rust project

Configr The dead easy way to use config files in your project This will load a config.toml file if it exists, otherwise it will create the needed fold

Carsten Kragelund Jørgensen 4 Jul 1, 2022
Bartib is an easy to use time tracking tool for the command line.

Bartib is an easy to use time tracking tool for the command line. It saves a log of all tracked activities as a plaintext file and allows you to create flexible reports.

Nikolas Schmidt-Voigt 346 Jan 2, 2023
Requestty - An easy-to-use collection of interactive cli prompts inspired by Inquirer.js.

Requestty requestty (request-tty) is an easy-to-use collection of interactive cli prompts inspired by Inquirer.js. Easy-to-use - The builder API and m

null 160 Dec 28, 2022
rustcxx: Using C++ from Rust made easy

rustcxx: Using C++ from Rust made easy rustcxx is a tool allowing C++ to be used from a Rust project easily. It works by allowing snippets of C++ to b

Google 500 Jan 3, 2023
zigfi is an open-source stocks, commodities and cryptocurrencies price monitoring CLI app, written fully in Rust, where you can organize assets you're watching easily into watchlists for easy access on your terminal.

zigfi zigfi is an open-source stocks, commodities and cryptocurrencies price monitoring CLI app, written fully in Rust, where you can organize assets

Aldrin Zigmund Cortez Velasco 18 Oct 24, 2022
Easy, Simple, Clean. Making status bars reliable and up-to-date.

Simple Status Easy, Simple, Clean. Making status bars reliable and up-to-date. Installation Compiling simple_status yourself doesn't require much. Ins

James Butcher 5 Aug 1, 2022
procs makes it easy to find and manage system processes

procs procs makes it easy to find and manage system processes. Right now, the main usage is finding processes by the ports it is listening on, but mor

Kurt Wolf 3 Aug 29, 2022
A tiny crate to make it easy to share and apply Git hooks for Rust projects

Shareable git hooks for Rust project. Sloughi is a friend of Husky from North Africa! :algeria:

Walid ZIOUCHE 24 Oct 6, 2022
Workflows make it easy to browse, search, execute and share commands (or a series of commands)--without needing to leave your terminal.

Workflows The repo for all public Workflows that appear within Warp and within commands.dev. To learn how to create local or repository workflows, see

Warp 369 Jan 2, 2023
An easy-to-use TUI crate for Rust, based off of the Elm architecture.

Rustea An easy-to-use TUI crate for Rust, based off of the Elm architecture. This is a re-implementation of Go's Tea, created by TJ Holowaychuk. Featu

Laz 82 Dec 21, 2022
Make data-driven table rendering easy with Dioxus

Dioxus Table Make data-driven table rendering easy with Dioxus Installation Until the next release of Dioxus this requires Dioxus nightly from git. Th

null 9 Oct 9, 2022
🚀 Supercharge your development with easy to setup package scripts

Mist ?? Supercharge your development with easy to setup package scripts. Works with every codebase regardless of the language or framework used! Note:

Shiv 3 May 2, 2022
A robust, customizable, blazingly-fast, efficient and easy-to-use command line application to uwu'ify your text!

uwuifyy A robust, customizable, blazingly-fast, efficient and easy-to-use command line application to uwu'ify your text! Logo Credits: Jade Nelson Tab

Hamothy 43 Dec 12, 2022