Skip to content

Commit

Permalink
use a reference to shrink the stack size
Browse files Browse the repository at this point in the history
  • Loading branch information
JoJoJet committed Aug 9, 2022
1 parent 239f8dc commit f584e12
Showing 1 changed file with 25 additions and 7 deletions.
32 changes: 25 additions & 7 deletions crates/bevy_utils/src/label.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ pub trait LabelDowncast<Id> {
fn downcast_from(data: u64) -> Option<Self::Output>;
}

#[doc(hidden)]
pub struct VTable {
pub ty: fn() -> ::std::any::TypeId,
pub fmt: fn(u64, &mut ::std::fmt::Formatter) -> ::std::fmt::Result,
}

/// Macro to define a new label trait
///
/// # Example
Expand All @@ -81,25 +87,30 @@ macro_rules! define_label {
$(#[$id_attr])*
#[derive(Clone, Copy)]
pub struct $id_name {
ty: ::std::any::TypeId,
data: u64,
f: fn(u64, &mut ::std::fmt::Formatter) -> ::std::fmt::Result,
vtable: &'static $crate::label::VTable,
}

impl ::std::fmt::Debug for $id_name {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
let data = self.data();
(self.f)(data, f)
(self.vtable.fmt)(data, f)
}
}

$(#[$label_attr])*
pub trait $label_name: 'static {
/// Essentially acts like a dynamic dispatch virtual table,
/// but specialized for labels.
const VTABLE : $crate::label::VTable = $crate::label::VTable {
ty: || ::std::any::TypeId::of::<Self>(),
fmt: Self::fmt,
};
/// Converts this type into an opaque, strongly-typed label.
#[inline]
fn as_label(&self) -> $id_name {
let data = self.data();
$id_name { data, ty: ::std::any::TypeId::of::<Self>(), f: Self::fmt }
$id_name { data, vtable: &Self::VTABLE }
}
/// Returns a number used to distinguish different labels of the same type.
fn data(&self) -> u64;
Expand Down Expand Up @@ -129,23 +140,30 @@ macro_rules! define_label {
impl PartialEq for $id_name {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.ty == rhs.ty && self.data() == rhs.data()
self.data() == rhs.data() && self.type_id() == rhs.type_id()
}
}
impl Eq for $id_name {}


impl std::hash::Hash for $id_name {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.ty.hash(state);
self.type_id().hash(state);
self.data().hash(state);
}
}

impl $id_name {
/// Returns the [`TypeId`] of the label from which this ID was constructed.
///
/// [`TypeId`]: ::std::any::TypeId
#[inline]
pub fn type_id(self) -> ::std::any::TypeId {
(self.vtable.ty)()
}
/// Returns true if this label was constructed from an instance of type `L`.
pub fn is<L: $label_name>(self) -> bool {
self.ty == ::std::any::TypeId::of::<L>()
self.type_id() == ::std::any::TypeId::of::<L>()
}
/// Attempts to downcast this label to type `L`.
///
Expand Down

0 comments on commit f584e12

Please sign in to comment.