/// Base trait for all resources, allows downcasting via [`Any`]. pubtrait DynResource: Any + WasmNotSendSync + 'static { fn as_any(&self) -> &dyn Any; fn as_any_mut(&mutself) -> &mutdyn Any;
}
/// Utility macro for implementing `DynResource` for a list of types.
macro_rules! impl_dyn_resource {
($($type:ty),*) => {
$( implcrate::DynResource for $type { fn as_any(&self) -> &dyn ::std::any::Any { self
}
/// Extension trait for `DynResource` used by implementations of various dynamic resource traits. trait DynResourceExt { /// # Panics /// /// - Panics if `self` is not downcastable to `T`. fn expect_downcast_ref<T: DynResource>(&self) -> &T; /// # Panics /// /// - Panics if `self` is not downcastable to `T`. fn expect_downcast_mut<T: DynResource>(&mutself) -> &mut T;
/// Unboxes a `Box<dyn DynResource>` to a concrete type. /// /// # Safety /// /// - `self` must be the correct concrete type. unsafefn unbox<T: DynResource + 'static>(self: Box<Self>) -> T;
}
impl<R: DynResource + ?Sized> DynResourceExt for R { fn expect_downcast_ref<'a, T: DynResource>(&'a self) -> &'a T { self.as_any()
.downcast_ref()
.expect("Resource doesn't have the expected backend type.")
}
fn expect_downcast_mut<'a, T: DynResource>(&'a mutself) -> &'a mut T { self.as_any_mut()
.downcast_mut()
.expect("Resource doesn't have the expected backend type.")
}
unsafefn unbox<T: DynResource + 'static>(self: Box<Self>) -> T {
debug_assert!(
<Selfas Any>::type_id(self.as_ref()) == std::any::TypeId::of::<T>(), "Resource doesn't have the expected type, expected {:?}, got {:?}",
std::any::TypeId::of::<T>(),
<Selfas Any>::type_id(self.as_ref())
);
let casted_ptr = Box::into_raw(self).cast::<T>(); // SAFETY: This is adheres to the safety contract of `Box::from_raw` because: // // - We are casting the value of a previously `Box`ed value, which guarantees: // - `casted_ptr` is not null. // - `casted_ptr` is valid for reads and writes, though by itself this does not mean // valid reads and writes for `T` (read on for that). // - We don't change the allocator. // - The contract of `Box::from_raw` requires that an initialized and aligned `T` is stored // within `casted_ptr`.
*unsafe { Box::from_raw(casted_ptr) }
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.