Crate multitype

Crate multitype 

Source
Expand description

MultiType is a crate for generalising fundamental types via traits.

MultiType provideds traits such as Uint and Float traits to abstract over a set of equivalent primitive types. These traits are intended to provide one-to-one copies of the interfaces that the primitive types define.

§Overview

The complete list of abstraction traits is:

For the sake of compatibility with {f16, f32, f64, f128}::to_int_unchecked, a FloatToInt trait is also provided.

Any given type may implement at most one of the aforementioned trait groups; thus, for example, any type that implemets Float can be assumed to possibly implement FloatLeast32 but never Uint.

Also note that all traits provided by this crate are sealed and cannot be implemented by third-party crates (at least currently).

§Arithmetic types

MultiType defines different traits for generalising arithmetic types:

Furthermore, StdFloat extends the Float trait with functionality that is typically only available in std’s floating-point types.

§Sized, arithmetic types

The basic, arithmetic traits guarantee a minimum size that is equivalent to the smallest member of its group, e.g. Uint is at least u8 and Float is at least f16.

Additionally, these three arithmetic traits have subtraits that guarantee wider types, for example:

Extremely-wide traits, e.g. IntLeast8 or IntLeast128, are considered redundant and are thus not provided.

§Array types

MultiType also provides the Array trait for generalising array types – most often over their length.

An example of this trait’s usecase is actually in this crate: Take, for instance, the definition of Uint: It has a Bytes associated type that is used by the bytewise constructors and destructors:

pub unsafe trait Uint: /* .. */ {
    type Bytes;

    fn from_ne_bytes(bytes: Self::Bytes) -> Self;

    fn to_ne_bytes(self) -> Self::Bytes;

    // ..
}

Now, anyone that would want to use the output of to_ne_bytes wouldn’t really have that many choices with regard to what to do with it. So, MultiType defines the Array trait:

use multitype::Array;

pub unsafe trait Uint: /* .. */ {
    type Bytes: Array<Scalar = u8>;

    // ..
}

With it, it’s possible for users to generically use Uint::to_ne_bytes as an array type through the trait methods.

§Examples

A generic Fibonacci sequence:

use multitype::Uint;

fn f<T: Uint>(x: T) -> T {
    let mut y    = T::from_u8(0x0);
    let mut y_m1 = T::from_u8(0x0);
    let mut y_m2 = T::from_u8(0x1);

    let mut i = T::from_u8(0x0);
    while i < x {
        y = y_m1 + y_m2;

        y_m2 = y_m1;
        y_m1 = y;

        i += T::from_u8(0x1);
    }

    y
}

assert_eq!(f(0u8),   0);
assert_eq!(f(1u8),   1);

assert_eq!(f(2u16),  1);
assert_eq!(f(3u16),  2);

assert_eq!(f(4u32),  3);
assert_eq!(f(5u32),  5);

assert_eq!(f(6u64),  8);
assert_eq!(f(7u64), 13);

Generic array indexing:

use core::f32;
use multitype::{Array, Float};

fn complicated_neg<T: Float>(value: T) -> T {
    let mut bytes = value.to_le_bytes();

    // Invert the sign bit -- which is always the most
    // significant bit of the most significant byte.
    *bytes.as_mut_slice().last_mut().unwrap() ^= 0b10000000;

    T::from_le_bytes(bytes)
}

assert_eq!(complicated_neg( 1.0f64), -1.0f64);
assert_eq!(complicated_neg(-1.0f64),  1.0f64);

assert_eq!(complicated_neg(f32::NEG_INFINITY), f32::INFINITY);

§Feature flags

  • alloc: Enables compatibility with alloc facilities
  • std: Enables compatibility with std facilities

Unstable features:

  • f16: Enables support for f16
  • f128: Enables support for f128
  • unstable-docs: Enables unstable documentation features

§MSRV policy

The goal of MultiType is to provide generic traits that bind as much of the standard interfaces as possible. We will attempt to backport all trivial interfaces as much as possible, but if any given interface is deemed to complicated, we will bump the MSRV to leverage it from the standard implementation.

When const-compatible traits land, MultiType will implement the feature as quickly as possible.

Copyright © 2025 Gabriel Bjørnager Jensen.

MultiType is distributed under either an MIT licence (see LICENCE-MIT) or version 2.0 of the Apache License (see LICENCE-APACHE), at your option.

Traits§

Array
Denotes an array.
Float
A generic, floating-point real.
FloatLeast32
Denotes a floating-pointer number that is at least as wide as f32.
FloatLeast64
Denotes a floating-pointer number that is at least as wide as f64.
FloatToInt
See core::convert::FloatToInt.
Int
A generic, signed integer.
IntLeast16
Denotes a signed integer that is at least as wide as i16.
IntLeast32
Denotes a signed integer that is at least as wide as i32.
IntLeast64
Denotes a signed integer that is at least as wide as i64.
StdFloat
Extends Float with std-only functionality.
Uint
A generic, unsigned integer.
UintLeast16
Denotes an unsigned that is at least as wide as u16.
UintLeast32
Denotes an unsigned that is at least as wide as u32.
UintLeast64
Denotes an unsigned that is at least as wide as u64.