#numerics #primitives #traits #pointers

no-std funty

Trait generalization over the primitive types

5 releases (stable)

Uses new Rust 2021

3.0.0-rc1 Nov 16, 2022
2.0.0 Nov 28, 2021
1.2.0 Feb 13, 2021
1.1.0 Dec 23, 2020
1.0.0 Feb 24, 2020

#268 in Rust patterns

Download history 164965/week @ 2022-08-15 161878/week @ 2022-08-22 160777/week @ 2022-08-29 156589/week @ 2022-09-05 165902/week @ 2022-09-12 166370/week @ 2022-09-19 169915/week @ 2022-09-26 163335/week @ 2022-10-03 176357/week @ 2022-10-10 188296/week @ 2022-10-17 182376/week @ 2022-10-24 191965/week @ 2022-10-31 203821/week @ 2022-11-07 190674/week @ 2022-11-14 169561/week @ 2022-11-21 177653/week @ 2022-11-28

753,251 downloads per month
Used in fewer than 40 crates

MIT license

70KB
2K SLoC

funty

Fundamental Type Unification

Latest Version MSRV License

Documentation Crate Downloads

Prior to 1.0, Rust had traits for the numeric primitive types to permit code to generalize over which specific type it accepted. This was never stabilized, and eventually removed.

This library provides a set of traits that abstract over common API surfaces of the primitive types, so that properties such as numeric behavior, register width, or signedness can be represented in the trait system.

Pointer Unification

*const T and *mut T are unified under the Pointer<T, Shared | Unique> type. The Permission trait allows code to be generic over write permissions, and manages propagating, downgrading, and upgrading permissions correctly without risking violations of Rust’s provenance tracking rules.

In particular, Pointer uses the associated-type system to internally wrap either *const T or *mut T according to the Permission type parameter it is given, so user code is never able to (safely) improperly upgrade write permissions on a pointer that is derived from a read-only provenance history.

See the ptr module for more details.

Functionality Traits

All primitive types (bool, char, {i,u}{8,16,32,64,128,size}, and f{32,64}) implement the Fundamental trait. This trait defines the basic concepts available to primitives: they are plain-old-data values, and can be as-casted to each other. Fundamental has no functionality other than providing the basic set of traits and allowing conversion.

The numeric primitives (everything except bool and char) implement the following trait hierarchy:

  • Numeric exports all the trait implementations and methods found on all numeric primitives.
    • Integral exports the trait implementations and methods found on all integers.
      • Signed unifies all signed integers iN.
      • Unsigned unifies all unsigned integers uN.
    • Floating unifies both floating-point numbers.

Width Traits

There are three trait families for type width. For Width values of 8, 16, 32, 64, and 128:

  • IsWidth is implemented by the numbers that are exactly this width.
  • AtLeastWidth is implemented by all numbers that are this width or wider.
  • AtMostWidth is implemented by all numbers that are this width or narrower.

Usage

Type use funty::*;, then declare the traits you need as generic bounds.

Examples

Perform bit arithmetic on some unsigned integer:

use funty::Unsigned;
fn invert_middle_bits<T: Unsigned>(num: T) -> T {
  let mask = (!T::ZERO).wrapping_shl(2).wrapping_shr(4).wrapping_shl(2);
  num ^ mask
}

#![no_std] Compatibility

The floating-point numbers offer many functions which are implemented in the target system’s libm. This library is present only in std-targets. If you are compiling to a #![no_std] target, depend on this library with

[dependencies.funty]
version = "3"
default-features = false

No runtime deps