Trait bytemuck::Contiguous

source ·
pub unsafe trait Contiguous: Copy + 'static {
    type Int: Copy + Ord;

    const MAX_VALUE: Self::Int;
    const MIN_VALUE: Self::Int;

    // Provided methods
    fn from_integer(value: Self::Int) -> Option<Self> { ... }
    fn into_integer(self) -> Self::Int { ... }
}
Expand description

A trait indicating that:

  1. A type has an equivalent representation to some known integral type.
  2. All instances of this type fall in a fixed range of values.
  3. Within that range, there are no gaps.

This is generally useful for fieldless enums (aka “c-style” enums), however it’s important that it only be used for those with an explicit #[repr], as #[repr(Rust)] fieldess enums have an unspecified layout.

Additionally, you shouldn’t assume that all implementations are enums. Any type which meets the requirements above while following the rules under “Safety” below is valid.

Example

#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq)]
enum Foo {
  A = 0,
  B = 1,
  C = 2,
  D = 3,
  E = 4,
}
unsafe impl Contiguous for Foo {
  type Int = u8;
  const MIN_VALUE: u8 = Foo::A as u8;
  const MAX_VALUE: u8 = Foo::E as u8;
}
assert_eq!(Foo::from_integer(3).unwrap(), Foo::D);
assert_eq!(Foo::from_integer(8), None);
assert_eq!(Foo::C.into_integer(), 2);

Safety

This is an unsafe trait, and incorrectly implementing it is undefined behavior.

Informally, by implementing it, you’re asserting that C is identical to the integral type C::Int, and that every C falls between C::MIN_VALUE and C::MAX_VALUE exactly once, without any gaps.

Precisely, the guarantees you must uphold when implementing Contiguous for some type C are:

  1. The size of C and C::Int must be the same, and neither may be a ZST. (Note: alignment is explicitly allowed to differ)

  2. C::Int must be a primitive integer, and not a wrapper type. In the future, this may be lifted to include cases where the behavior is identical for a relevant set of traits (Ord, arithmetic, …).

  3. All C::Ints which are in the inclusive range between C::MIN_VALUE and C::MAX_VALUE are bitwise identical to unique valid instances of C.

  4. There exist no instances of C such that their bitpatterns, when interpreted as instances of C::Int, fall outside of the MAX_VALUE / MIN_VALUE range – It is legal for unsafe code to assume that if it gets a C that implements Contiguous, it is in the appropriate range.

  5. Finally, you promise not to provide overridden implementations of Contiguous::from_integer and Contiguous::into_integer.

For clarity, the following rules could be derived from the above, but are listed explicitly:

  • C::MAX_VALUE must be greater or equal to C::MIN_VALUE (therefore, C must be an inhabited type).

  • There exist no two values between MIN_VALUE and MAX_VALUE such that when interpreted as a C they are considered identical (by, say, match).

Required Associated Types§

source

type Int: Copy + Ord

The primitive integer type with an identical representation to this type.

Contiguous is broadly intended for use with fieldless enums, and for these the correct integer type is easy: The enum should have a #[repr(Int)] or #[repr(C)] attribute, (if it does not, it is unsound to implement Contiguous!).

  • For #[repr(Int)], use the listed Int. e.g. #[repr(u8)] should use type Int = u8.

  • For #[repr(C)], use whichever type the C compiler will use to represent the given enum. This is usually c_int (from std::os::raw or libc), but it’s up to you to make the determination as the implementer of the unsafe trait.

For precise rules, see the list under “Safety” above.

Required Associated Constants§

source

const MAX_VALUE: Self::Int

The upper inclusive bound for valid instances of this type.

source

const MIN_VALUE: Self::Int

The lower inclusive bound for valid instances of this type.

Provided Methods§

source

fn from_integer(value: Self::Int) -> Option<Self>

If value is within the range for valid instances of this type, returns Some(converted_value), otherwise, returns None.

This is a trait method so that you can write value.into_integer() in your code. It is a contract of this trait that if you implement Contiguous on your type you must not override this method.

Panics

We will not panic for any correct implementation of Contiguous, but may panic if we detect an incorrect one.

This is undefined behavior regardless, so it could have been the nasal demons at that point anyway ;).

source

fn into_integer(self) -> Self::Int

Perform the conversion from C into the underlying integral type. This mostly exists otherwise generic code would need unsafe for the value as integer

This is a trait method so that you can write value.into_integer() in your code. It is a contract of this trait that if you implement Contiguous on your type you must not override this method.

Panics

We will not panic for any correct implementation of Contiguous, but may panic if we detect an incorrect one.

This is undefined behavior regardless, so it could have been the nasal demons at that point anyway ;).

Implementations on Foreign Types§

source§

impl Contiguous for u16

§

type Int = u16

source§

const MAX_VALUE: u16 = 65_535u16

source§

const MIN_VALUE: u16 = 0u16

source§

impl Contiguous for bool

§

type Int = u8

source§

const MAX_VALUE: u8 = 1u8

source§

const MIN_VALUE: u8 = 0u8

source§

impl Contiguous for usize

§

type Int = usize

source§

const MAX_VALUE: usize = 18_446_744_073_709_551_615usize

source§

const MIN_VALUE: usize = 0usize

source§

impl Contiguous for NonZeroUsize

§

type Int = usize

source§

const MAX_VALUE: usize = 18_446_744_073_709_551_615usize

source§

const MIN_VALUE: usize = 1usize

source§

impl Contiguous for u128

§

type Int = u128

source§

const MAX_VALUE: u128 = 340_282_366_920_938_463_463_374_607_431_768_211_455u128

source§

const MIN_VALUE: u128 = 0u128

source§

impl Contiguous for u64

§

type Int = u64

source§

const MAX_VALUE: u64 = 18_446_744_073_709_551_615u64

source§

const MIN_VALUE: u64 = 0u64

source§

impl Contiguous for i64

§

type Int = i64

source§

const MAX_VALUE: i64 = 9_223_372_036_854_775_807i64

source§

const MIN_VALUE: i64 = -9_223_372_036_854_775_808i64

source§

impl Contiguous for isize

§

type Int = isize

source§

const MAX_VALUE: isize = 9_223_372_036_854_775_807isize

source§

const MIN_VALUE: isize = -9_223_372_036_854_775_808isize

source§

impl Contiguous for NonZeroU128

§

type Int = u128

source§

const MAX_VALUE: u128 = 340_282_366_920_938_463_463_374_607_431_768_211_455u128

source§

const MIN_VALUE: u128 = 1u128

source§

impl Contiguous for i128

§

type Int = i128

source§

const MAX_VALUE: i128 = 170_141_183_460_469_231_731_687_303_715_884_105_727i128

source§

const MIN_VALUE: i128 = -170_141_183_460_469_231_731_687_303_715_884_105_728i128

source§

impl Contiguous for i16

§

type Int = i16

source§

const MAX_VALUE: i16 = 32_767i16

source§

const MIN_VALUE: i16 = -32_768i16

source§

impl Contiguous for u8

§

type Int = u8

source§

const MAX_VALUE: u8 = 255u8

source§

const MIN_VALUE: u8 = 0u8

source§

impl Contiguous for NonZeroU64

§

type Int = u64

source§

const MAX_VALUE: u64 = 18_446_744_073_709_551_615u64

source§

const MIN_VALUE: u64 = 1u64

source§

impl Contiguous for i32

§

type Int = i32

source§

const MAX_VALUE: i32 = 2_147_483_647i32

source§

const MIN_VALUE: i32 = -2_147_483_648i32

source§

impl Contiguous for i8

§

type Int = i8

source§

const MAX_VALUE: i8 = 127i8

source§

const MIN_VALUE: i8 = -128i8

source§

impl Contiguous for NonZeroU8

§

type Int = u8

source§

const MAX_VALUE: u8 = 255u8

source§

const MIN_VALUE: u8 = 1u8

source§

impl Contiguous for NonZeroU16

§

type Int = u16

source§

const MAX_VALUE: u16 = 65_535u16

source§

const MIN_VALUE: u16 = 1u16

source§

impl Contiguous for u32

§

type Int = u32

source§

const MAX_VALUE: u32 = 4_294_967_295u32

source§

const MIN_VALUE: u32 = 0u32

source§

impl Contiguous for NonZeroU32

§

type Int = u32

source§

const MAX_VALUE: u32 = 4_294_967_295u32

source§

const MIN_VALUE: u32 = 1u32

Implementors§