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
FeatureIdis 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: u32Implementations§
Source§impl PackedFeatureId
impl PackedFeatureId
Sourcepub const UNKNOWN: Self
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);Sourcepub fn vertex(code: u32) -> Self
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));Sourcepub fn edge(code: u32) -> Self
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));Sourcepub fn face(code: u32) -> Self
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));Sourcepub fn unpack(self) -> FeatureId
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);Sourcepub fn is_face(self) -> bool
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());Sourcepub fn is_vertex(self) -> bool
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());Sourcepub fn is_edge(self) -> bool
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());Sourcepub fn is_unknown(self) -> bool
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
impl Clone for PackedFeatureId
Source§fn clone(&self) -> PackedFeatureId
fn clone(&self) -> PackedFeatureId
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for PackedFeatureId
impl Debug for PackedFeatureId
Source§impl From<FeatureId> for PackedFeatureId
impl From<FeatureId> for PackedFeatureId
Source§fn from(value: FeatureId) -> Self
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
impl Hash for PackedFeatureId
Source§impl PartialEq for PackedFeatureId
impl PartialEq for PackedFeatureId
impl Copy for PackedFeatureId
impl Eq for PackedFeatureId
impl StructuralPartialEq for PackedFeatureId
Auto Trait Implementations§
impl Freeze for PackedFeatureId
impl RefUnwindSafe for PackedFeatureId
impl Send for PackedFeatureId
impl Sync for PackedFeatureId
impl Unpin for PackedFeatureId
impl UnwindSafe for PackedFeatureId
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&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
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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 moreSource§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.