Skip to main content

IntegerId

Trait IntegerId 

Source
pub trait IntegerId:
    Copy
    + Eq
    + Debug
    + Send
    + Sync
    + 'static {
    type Int: UnsignedPrimInt;

    const MIN_ID: Option<Self>;
    const MAX_ID: Option<Self>;
    const MIN_ID_INT: Option<Self::Int>;
    const MAX_ID_INT: Option<Self::Int>;
    const TRUSTED_RANGE: Option<TrustedRangeToken<Self>> = None;

    // Required methods
    fn from_int_checked(id: Self::Int) -> Option<Self>;
    fn to_int(self) -> Self::Int;

    // Provided methods
    fn from_int(id: Self::Int) -> Self { ... }
    unsafe fn from_int_unchecked(id: Self::Int) -> Self { ... }
}
Expand description

An identifier which can be sensibly converted to/from an unsigned integer value.

The type should not carry any information beyond that of the integer index, and be able to losslessly convert back and forth from Self::Int. It is possible that not all values of the underlying integer type are valid, allowing core::num::NonZero and C-like enums to implement this trait.

This is intended mostly for newtype wrappers around integer indexes, and the primitive integer types themselves.

The value of the underlying integer must be consistent. It cannot change over the course of the program’s lifetime.

§Safety

With one exception, this trait is safe to implement and cannot be relied upon by memory safety.

If the implementation of IntegerId::from_int_unchecked makes any sort of unsafe assumptions about the validity of the input, then the rest of the trait must be implemented correctly. This means that implementations of this trait fall into two categories:

  1. Potentially incorrect implemented entirely using safe code, where from_int_unchecked(x) is equivalent to calling from_int_checked(x).unwrap();
  2. Traits where from_int_unchecked could trigger undefined behavior on an invalid value, but every other part of this trait can be trusted to be implemented correctly.

In both these cases, the following code is always safe:

fn foo<T: IntegerId>(x: T) -> T {
    let y = x.to_int();
    let z = unsafe { T::from_int_unchecked(y) };
    z
}

In case 1, it doesn’t matter if x.to_int() produces garbage data, because T::from_int_unchecked method is safe to call. In case 2, the to_int method can be trusted to produce a valid value y that cannot fail when passed to T::from_int_unchecked.

The requirement for correctness in this case also apply to all sub-traits in this crate, including IntegerIdContiguous and IntegerIdCounter. So an unsafe implementation of from_int_unchecked can be similarly trusted to accept all integer values between IntegerId::MIN_ID and IntegerId::MAX_ID.

This restriction allows avoiding unnecessary checks when ids are stored to/from another data structure. Despite this requirement, I still consider this trait safe to implement, because safety can only be violated by an unsafe implementation offrom_int_unchecked.

This type should not have interior mutability. This is guaranteed by the Copy bound.

Required Associated Constants§

Source

const MIN_ID: Option<Self>

The value of this type with the smallest integer value, or None if this type is uninhabited.

Source

const MAX_ID: Option<Self>

The value of this type with the largest integer value, or None if this type is uninhabited.

Source

const MIN_ID_INT: Option<Self::Int>

The value of Self::MIN_ID a primitive integer, or None if this type is uninhabited.

This is necessary because trait methods cannot be marked const.

Source

const MAX_ID_INT: Option<Self::Int>

The value of Self::MAX_ID a primitive integer, or None if this type is uninhabited.

This is necessary because trait methods cannot be marked const.

Provided Associated Constants§

Source

const TRUSTED_RANGE: Option<TrustedRangeToken<Self>> = None

Indicates that the type’s implementation of IntegerId::to_int can be trusted to only return values in the range MIN_ID_INT..=MAX_ID_INT.

Creating this token means that all of these guarantees can be relied upon for memory safety. This allows unsafe code to avoid bounds checks, but turns a correctness invariant into a soundness invariant.

§Safety

The result of Self::to_int must always fall in the range MIN_ID_INT..=MAX_ID_INT.

If EnumId is implemented, then the requirements of the EnumId trait must be met as well. In particular, the index must always fit in a u32 and have the appropriately Array and BitSet items.

Required Associated Types§

Source

type Int: UnsignedPrimInt

The underlying integer type.

Every valid instance of Self should correspond to a valid Self::Int. However, the other direction may not always be true.

Required Methods§

Source

fn from_int_checked(id: Self::Int) -> Option<Self>

Create an id from the underlying integer value, returning None if the value is invalid.

Source

fn to_int(self) -> Self::Int

Convert this id into an underlying integer type.

This method can never fail, since valid instances Self always correspond to valid instances of Self::Int.

Provided Methods§

Source

fn from_int(id: Self::Int) -> Self

Create an id from the underlying integer value, panicking if the value is invalid.

§Correctness

A value returned by this method should never trigger an error if passed to Self::from_int_checked. This means the validity of certain ids can’t change over the course of the program.

Source

unsafe fn from_int_unchecked(id: Self::Int) -> Self

Create an id from the underlying integer value, triggering undefined behavior if the value is invalid.

§Safety

If the corresponding Self::from_int_checked method would fail, this triggers undefined behavior. The default implementation just invokes Self::from_int.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl IntegerId for !

Source§

const MIN_ID: Option<Self> = None

Source§

const MAX_ID: Option<Self> = None

Source§

const MIN_ID_INT: Option<Self::Int> = None

Source§

const MAX_ID_INT: Option<Self::Int> = None

Source§

const TRUSTED_RANGE: Option<TrustedRangeToken<Self>>

Source§

type Int = u8

Source§

fn from_int(id: Self::Int) -> Self

Source§

fn from_int_checked(_id: Self::Int) -> Option<Self>

Source§

unsafe fn from_int_unchecked(_id: Self::Int) -> Self

Source§

fn to_int(self) -> Self::Int

Source§

impl IntegerId for Infallible

Source§

const MIN_ID: Option<Self> = None

Source§

const MAX_ID: Option<Self> = None

Source§

const MIN_ID_INT: Option<Self::Int> = None

Source§

const MAX_ID_INT: Option<Self::Int> = None

Source§

const TRUSTED_RANGE: Option<TrustedRangeToken<Self>>

Source§

type Int = u8

Source§

fn from_int(id: Self::Int) -> Self

Source§

fn from_int_checked(_id: Self::Int) -> Option<Self>

Source§

unsafe fn from_int_unchecked(_id: Self::Int) -> Self

Source§

fn to_int(self) -> Self::Int

Source§

impl IntegerId for NonMaxU8

Source§

const MIN_ID: Option<Self>

Source§

const MAX_ID: Option<Self>

Source§

const MIN_ID_INT: Option<Self::Int>

Source§

const MAX_ID_INT: Option<Self::Int>

Source§

const TRUSTED_RANGE: Option<TrustedRangeToken<Self>>

Source§

type Int = u8

Source§

fn from_int_checked(id: Self::Int) -> Option<Self>

Source§

unsafe fn from_int_unchecked(id: Self::Int) -> Self

Source§

fn to_int(self) -> Self::Int

Source§

impl IntegerId for NonMaxU16

Source§

const MIN_ID: Option<Self>

Source§

const MAX_ID: Option<Self>

Source§

const MIN_ID_INT: Option<Self::Int>

Source§

const MAX_ID_INT: Option<Self::Int>

Source§

const TRUSTED_RANGE: Option<TrustedRangeToken<Self>>

Source§

type Int = u16

Source§

fn from_int_checked(id: Self::Int) -> Option<Self>

Source§

unsafe fn from_int_unchecked(id: Self::Int) -> Self

Source§

fn to_int(self) -> Self::Int

Source§

impl IntegerId for NonMaxU32

Source§

const MIN_ID: Option<Self>

Source§

const MAX_ID: Option<Self>

Source§

const MIN_ID_INT: Option<Self::Int>

Source§

const MAX_ID_INT: Option<Self::Int>

Source§

const TRUSTED_RANGE: Option<TrustedRangeToken<Self>>

Source§

type Int = u32

Source§

fn from_int_checked(id: Self::Int) -> Option<Self>

Source§

unsafe fn from_int_unchecked(id: Self::Int) -> Self

Source§

fn to_int(self) -> Self::Int

Source§

impl IntegerId for NonMaxU64

Source§

const MIN_ID: Option<Self>

Source§

const MAX_ID: Option<Self>

Source§

const MIN_ID_INT: Option<Self::Int>

Source§

const MAX_ID_INT: Option<Self::Int>

Source§

const TRUSTED_RANGE: Option<TrustedRangeToken<Self>>

Source§

type Int = u64

Source§

fn from_int_checked(id: Self::Int) -> Option<Self>

Source§

unsafe fn from_int_unchecked(id: Self::Int) -> Self

Source§

fn to_int(self) -> Self::Int

Source§

impl IntegerId for NonMaxU128

Source§

const MIN_ID: Option<Self>

Source§

const MAX_ID: Option<Self>

Source§

const MIN_ID_INT: Option<Self::Int>

Source§

const MAX_ID_INT: Option<Self::Int>

Source§

const TRUSTED_RANGE: Option<TrustedRangeToken<Self>>

Source§

type Int = u128

Source§

fn from_int_checked(id: Self::Int) -> Option<Self>

Source§

unsafe fn from_int_unchecked(id: Self::Int) -> Self

Source§

fn to_int(self) -> Self::Int

Source§

impl IntegerId for NonMaxUsize

Source§

const MIN_ID: Option<Self>

Source§

const MAX_ID: Option<Self>

Source§

const MIN_ID_INT: Option<Self::Int>

Source§

const MAX_ID_INT: Option<Self::Int>

Source§

const TRUSTED_RANGE: Option<TrustedRangeToken<Self>>

Source§

type Int = usize

Source§

fn from_int_checked(id: Self::Int) -> Option<Self>

Source§

unsafe fn from_int_unchecked(id: Self::Int) -> Self

Source§

fn to_int(self) -> Self::Int

Source§

impl IntegerId for NonZeroU8

Source§

const MIN_ID: Option<Self>

Source§

const MAX_ID: Option<Self>

Source§

const MIN_ID_INT: Option<Self::Int>

Source§

const MAX_ID_INT: Option<Self::Int>

Source§

const TRUSTED_RANGE: Option<TrustedRangeToken<Self>>

Source§

type Int = u8

Source§

fn from_int_checked(id: Self::Int) -> Option<Self>

Source§

unsafe fn from_int_unchecked(id: Self::Int) -> Self

Source§

fn to_int(self) -> Self::Int

Source§

impl IntegerId for NonZeroU16

Source§

const MIN_ID: Option<Self>

Source§

const MAX_ID: Option<Self>

Source§

const MIN_ID_INT: Option<Self::Int>

Source§

const MAX_ID_INT: Option<Self::Int>

Source§

const TRUSTED_RANGE: Option<TrustedRangeToken<Self>>

Source§

type Int = u16

Source§

fn from_int_checked(id: Self::Int) -> Option<Self>

Source§

unsafe fn from_int_unchecked(id: Self::Int) -> Self

Source§

fn to_int(self) -> Self::Int

Source§

impl IntegerId for NonZeroU32

Source§

const MIN_ID: Option<Self>

Source§

const MAX_ID: Option<Self>

Source§

const MIN_ID_INT: Option<Self::Int>

Source§

const MAX_ID_INT: Option<Self::Int>

Source§

const TRUSTED_RANGE: Option<TrustedRangeToken<Self>>

Source§

type Int = u32

Source§

fn from_int_checked(id: Self::Int) -> Option<Self>

Source§

unsafe fn from_int_unchecked(id: Self::Int) -> Self

Source§

fn to_int(self) -> Self::Int

Source§

impl IntegerId for NonZeroU64

Source§

const MIN_ID: Option<Self>

Source§

const MAX_ID: Option<Self>

Source§

const MIN_ID_INT: Option<Self::Int>

Source§

const MAX_ID_INT: Option<Self::Int>

Source§

const TRUSTED_RANGE: Option<TrustedRangeToken<Self>>

Source§

type Int = u64

Source§

fn from_int_checked(id: Self::Int) -> Option<Self>

Source§

unsafe fn from_int_unchecked(id: Self::Int) -> Self

Source§

fn to_int(self) -> Self::Int

Source§

impl IntegerId for NonZeroU128

Source§

const MIN_ID: Option<Self>

Source§

const MAX_ID: Option<Self>

Source§

const MIN_ID_INT: Option<Self::Int>

Source§

const MAX_ID_INT: Option<Self::Int>

Source§

const TRUSTED_RANGE: Option<TrustedRangeToken<Self>>

Source§

type Int = u128

Source§

fn from_int_checked(id: Self::Int) -> Option<Self>

Source§

unsafe fn from_int_unchecked(id: Self::Int) -> Self

Source§

fn to_int(self) -> Self::Int

Source§

impl IntegerId for NonZeroUsize

Source§

const MIN_ID: Option<Self>

Source§

const MAX_ID: Option<Self>

Source§

const MIN_ID_INT: Option<Self::Int>

Source§

const MAX_ID_INT: Option<Self::Int>

Source§

const TRUSTED_RANGE: Option<TrustedRangeToken<Self>>

Source§

type Int = usize

Source§

fn from_int_checked(id: Self::Int) -> Option<Self>

Source§

unsafe fn from_int_unchecked(id: Self::Int) -> Self

Source§

fn to_int(self) -> Self::Int

Source§

impl IntegerId for u8

Source§

impl IntegerId for u16

Source§

impl IntegerId for u32

Source§

impl IntegerId for u64

Source§

impl IntegerId for u128

Source§

impl IntegerId for usize

Implementors§

Source§

impl<T: IntegerId> IntegerId for OrderByInt<T>

Source§

const MIN_ID: Option<Self>

Source§

const MAX_ID: Option<Self>

Source§

const MIN_ID_INT: Option<Self::Int> = <T as crate::IntegerId>::MIN_ID_INT

Source§

const MAX_ID_INT: Option<Self::Int> = <T as crate::IntegerId>::MAX_ID_INT

Source§

const TRUSTED_RANGE: Option<TrustedRangeToken<Self>>

Source§

type Int = <T as IntegerId>::Int