funty
The funty
crate (fundamental types) provides traits that unify
the Rust non-pointer primitives. It also unifies pointers and references by
lifting access permissions into the trait system.
Fundamental Unification
The Rust primitives implement the following trait hierarchy and replicate their standard-library inherent API and trait implementations.
Fundamental
: this is implemented by all primitives:bool
,char
, all integers, and both floats. It requires all traits that all primitives implement, and provides.as_other()
methods that can replaceas
-casts.Numeric
: this is implemented by all integers and both floats. It adds the arithmetic operator traits, and methods for converting between the integer and its raw byte representation.Integral
: this is implemented by all integers. It adds bit-wise operator traits, attempted conversions between the other integers, and bit-shifts. It also provides most of the integer inherent API, as most of these methods are sign-agnostic.Signed
: this is implemented only by signed integers. It adds the absolute-value and sign-testing functions that unsigned integers don’t support.Unsigned
: this is implemented only by unsigned integers. It provides the{is,next}_power_of_two
one-hot methods that only make sense on unsigned integers.
Floating
: this is implemented by the floating-point numbers. Unlike the integral traits, it has a great deal of methods that only exist whencfg(feature = "std")
is active, as they require the platformlibm
mathematics library and are not provided by Rust’score
crate. It also provides both all of the associated constants, as well as all of the constants stored in eponymous modules but not associated with the actual floating-point primitive types.
Additionally, funty
provides marker traits for selecting bit-width: for N
in 8
, 16
, 32
, 64
, and 128
, the IsN
trait is implemented by types
that are exactly that wide, AtLeastN
is implemented by types that are that
width or more, and AtMostN
is implemented by types that are that width or
less.
You can use these traits as generic constraints in code that needs to accept a
range of different primitives. The integral traits provide Peano constants (zero
and one), and can be constructed from literals for non-const
work.
Pointer Unification
The funty::ptr
module provides Pointer
and NonNullPtr
types which are
replacements for raw pointers and core::ptr::NonNull
, respectively. They work
by lifting the *const T
/*mut T
distinction into the trait system, through
the Permission
trait and the Shared
, Unique
, and (Shared, Unique)
types.
The Permission
trait and its implementors implement a less-capable version of
the stacked-borrows experimental model found in Miri. Pointer<T, P>
implements
the read-only APIs found on both *const
and *mut
pointers, while
Pointer<T, Unique>
alone implements the write APIs only present on *mut
pointers. Additionally, type-level transitions allow safely casting Unique
pointers down to read-only and back up to Unique
, and unsafely casting
directly to a permission that you specify.
The NonNullPtr
behaves similarly to Pointer
, except that it encloses a
core::ptr::NonNull
in order to regain the null-pointer niche optimization. Its
API strives to match both the NonNull
and Pointer
APIs. As both raw pointers
and NonNull
still have large amounts of unstable API surface in the standard
library, these types will continue to grow in response to both Ferrilab’s needs
and the standard library’s evolution.