Struct PackedFeatureId

Source
pub struct PackedFeatureId(pub u32);
Expand description

A memory-efficient feature ID where the type and index are packed into a single u32.

PackedFeatureId is a space-optimized version of FeatureId that encodes both the feature type (vertex, edge, or face) and its numeric identifier in a single 32-bit value. This is particularly useful when storing large numbers of feature IDs, as it uses half the memory of a standard enum representation.

§Memory Layout

The packing scheme uses the upper 2 bits to encode the feature type, leaving 30 bits (0-1,073,741,823) for the feature index:

┌──┬──┬────────────────────────────────┐
│31│30│29                              0│
├──┴──┴────────────────────────────────┤
│Type │        Feature Index           │
│(2b) │           (30 bits)            │
└─────┴────────────────────────────────┘

Type encoding:
- 00: Unknown
- 01: Vertex
- 10: Edge (3D only)
- 11: Face

§Use Cases

Use PackedFeatureId when:

  • Storing feature IDs in large data structures (e.g., contact manifolds)
  • Passing feature IDs across FFI boundaries where a fixed size is required
  • Memory usage is a concern and you have many feature IDs

Use regular FeatureId when:

  • Code clarity is more important than memory usage
  • You need to pattern match on feature types frequently
  • Working with small numbers of feature IDs

§Examples

Creating and unpacking feature IDs in 2D:

use parry2d::shape::{FeatureId, PackedFeatureId};

// Create a packed vertex ID
let packed_vertex = PackedFeatureId::vertex(10);
assert!(packed_vertex.is_vertex());
assert!(!packed_vertex.is_face());

// Create a packed face ID
let packed_face = PackedFeatureId::face(5);
assert!(packed_face.is_face());

// Unpack to get the full enum
let unpacked = packed_face.unpack();
assert_eq!(unpacked, FeatureId::Face(5));

Creating and unpacking feature IDs in 3D:

use parry3d::shape::{FeatureId, PackedFeatureId};

// Create a packed vertex ID
let packed_vertex = PackedFeatureId::vertex(10);
assert!(packed_vertex.is_vertex());
assert!(!packed_vertex.is_face());

// Create a packed edge ID (3D only)
let packed_edge = PackedFeatureId::edge(7);
assert!(packed_edge.is_edge());

// Create a packed face ID
let packed_face = PackedFeatureId::face(5);
assert!(packed_face.is_face());

// Unpack to get the full enum
let unpacked = packed_face.unpack();
assert_eq!(unpacked, FeatureId::Face(5));

Converting between packed and unpacked forms:

use parry2d::shape::{FeatureId, PackedFeatureId};

// From FeatureId to PackedFeatureId
let feature = FeatureId::Vertex(42);
let packed: PackedFeatureId = feature.into();
assert!(packed.is_vertex());

// From PackedFeatureId back to FeatureId
let unpacked = packed.unpack();
assert_eq!(unpacked, FeatureId::Vertex(42));

Working with the unknown feature:

use parry2d::shape::PackedFeatureId;

let unknown = PackedFeatureId::UNKNOWN;
assert!(unknown.is_unknown());
assert!(!unknown.is_vertex());
assert!(!unknown.is_face());

Checking feature types efficiently in 3D:

use parry3d::shape::PackedFeatureId;

let vertex = PackedFeatureId::vertex(100);
let edge = PackedFeatureId::edge(50);
let face = PackedFeatureId::face(25);

// Type checking is very fast (just bit masking)
assert!(vertex.is_vertex());
assert!(edge.is_edge());
assert!(face.is_face());

// Different types are not equal
assert_ne!(vertex, edge);
assert_ne!(edge, face);

§Performance

PackedFeatureId provides several performance benefits:

  • Memory: Uses 4 bytes vs 8 bytes for FeatureId (on 64-bit systems)
  • Cache efficiency: Better cache utilization when storing many IDs
  • Type checking: Very fast (single bitwise AND operation)
  • Conversion: Converting to/from FeatureId is essentially free

§Limitations

The packing scheme limits feature indices to 30 bits (max value: 1,073,741,823). Attempting to create a packed feature ID with a larger index will panic in debug mode due to the assertion checks in the constructor methods.

Tuple Fields§

§0: u32

Implementations§

Source§

impl PackedFeatureId

Source

pub const UNKNOWN: Self

Constant representing an unknown or unidentified feature.

This is the default value and corresponds to FeatureId::Unknown.

§Examples
use parry2d::shape::{PackedFeatureId, FeatureId};

let unknown = PackedFeatureId::UNKNOWN;
assert!(unknown.is_unknown());
assert_eq!(unknown.unpack(), FeatureId::Unknown);
Source

pub fn vertex(code: u32) -> Self

Creates a packed feature ID for a vertex with the given index.

§Panics

Panics in debug mode if code uses any of the upper 2 bits (i.e., if code >= 2^30). The maximum valid value is 1,073,741,823 (0x3FFFFFFF).

§Examples
use parry2d::shape::{PackedFeatureId, FeatureId};

let packed = PackedFeatureId::vertex(5);
assert!(packed.is_vertex());
assert_eq!(packed.unpack(), FeatureId::Vertex(5));
Source

pub fn edge(code: u32) -> Self

Creates a packed feature ID for an edge with the given index.

Available only in 3D mode (dim3 feature).

§Panics

Panics in debug mode if code uses any of the upper 2 bits (i.e., if code >= 2^30). The maximum valid value is 1,073,741,823 (0x3FFFFFFF).

§Examples
use parry3d::shape::{PackedFeatureId, FeatureId};

let packed = PackedFeatureId::edge(10);
assert!(packed.is_edge());
assert_eq!(packed.unpack(), FeatureId::Edge(10));
Source

pub fn face(code: u32) -> Self

Creates a packed feature ID for a face with the given index.

§Panics

Panics in debug mode if code uses any of the upper 2 bits (i.e., if code >= 2^30). The maximum valid value is 1,073,741,823 (0x3FFFFFFF).

§Examples
use parry2d::shape::{PackedFeatureId, FeatureId};

let packed = PackedFeatureId::face(15);
assert!(packed.is_face());
assert_eq!(packed.unpack(), FeatureId::Face(15));
Source

pub fn unpack(self) -> FeatureId

Unpacks this feature ID into the full FeatureId enum.

This converts the compact packed representation back into the explicit enum form, allowing you to pattern match on the feature type.

§Examples
use parry2d::shape::{FeatureId, PackedFeatureId};

let packed = PackedFeatureId::vertex(42);
let unpacked = packed.unpack();

match unpacked {
    FeatureId::Vertex(id) => assert_eq!(id, 42),
    _ => panic!("Expected a vertex!"),
}

Round-trip conversion:

use parry2d::shape::{FeatureId, PackedFeatureId};

let original = FeatureId::Face(100);
let packed: PackedFeatureId = original.into();
let unpacked = packed.unpack();

assert_eq!(original, unpacked);
Source

pub fn is_face(self) -> bool

Checks if this feature ID identifies a face.

This is a very fast operation (single bitwise AND and comparison).

§Examples
use parry2d::shape::PackedFeatureId;

let face = PackedFeatureId::face(5);
let vertex = PackedFeatureId::vertex(5);

assert!(face.is_face());
assert!(!vertex.is_face());
Source

pub fn is_vertex(self) -> bool

Checks if this feature ID identifies a vertex.

This is a very fast operation (single bitwise AND and comparison).

§Examples
use parry2d::shape::PackedFeatureId;

let vertex = PackedFeatureId::vertex(10);
let face = PackedFeatureId::face(10);

assert!(vertex.is_vertex());
assert!(!face.is_vertex());
Source

pub fn is_edge(self) -> bool

Checks if this feature ID identifies an edge.

Available only in 3D mode (dim3 feature).

This is a very fast operation (single bitwise AND and comparison).

§Examples
use parry3d::shape::PackedFeatureId;

let edge = PackedFeatureId::edge(7);
let vertex = PackedFeatureId::vertex(7);

assert!(edge.is_edge());
assert!(!vertex.is_edge());
Source

pub fn is_unknown(self) -> bool

Checks if this feature ID is unknown.

§Examples
use parry2d::shape::PackedFeatureId;

let unknown = PackedFeatureId::UNKNOWN;
let vertex = PackedFeatureId::vertex(0);

assert!(unknown.is_unknown());
assert!(!vertex.is_unknown());

Trait Implementations§

Source§

impl Clone for PackedFeatureId

Source§

fn clone(&self) -> PackedFeatureId

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for PackedFeatureId

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<FeatureId> for PackedFeatureId

Source§

fn from(value: FeatureId) -> Self

Converts a FeatureId into its packed representation.

This is a lossless conversion that encodes the feature type and index into a single u32 value.

§Examples
use parry2d::shape::{FeatureId, PackedFeatureId};

// Explicit conversion
let feature = FeatureId::Vertex(123);
let packed = PackedFeatureId::from(feature);
assert!(packed.is_vertex());

// Using Into trait
let feature = FeatureId::Face(456);
let packed: PackedFeatureId = feature.into();
assert!(packed.is_face());

// Round-trip conversion preserves the value
let original = FeatureId::Vertex(789);
let packed: PackedFeatureId = original.into();
assert_eq!(packed.unpack(), original);
Source§

impl Hash for PackedFeatureId

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for PackedFeatureId

Source§

fn eq(&self, other: &PackedFeatureId) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for PackedFeatureId

Source§

impl Eq for PackedFeatureId

Source§

impl StructuralPartialEq for PackedFeatureId

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_sync(self: Box<T>) -> Box<dyn Any + Sync + Send>

Converts Box<Trait> (where Trait: DowncastSync) to Box<dyn Any + Send + Sync>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Converts Arc<Trait> (where Trait: DowncastSync) to Arc<Any>, which can then be downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Scalar for T
where T: 'static + Clone + PartialEq + Debug,