reduce usage of unsafe
This commit is contained in:
1 parent
738f1b3ce0
commit
170a3669f7
3 files changed
+47
-39
No files matched your search
@@ -48,7 +48,20 @@ impl<'a> Mutations<'a> {
|
|||||||
|
|
||||||
/// Push a new mutation into the dom_edits list
|
/// Push a new mutation into the dom_edits list
|
||||||
pub(crate) fn push(&mut self, mutation: Mutation<'static>) {
|
pub(crate) fn push(&mut self, mutation: Mutation<'static>) {
|
||||||
unsafe { self.edits.push(std::mem::transmute(mutation)) }
|
self.edits.push(mutation.downcast_lifetime())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mutations<'static> {
|
||||||
|
pub(crate) fn take<'a>(&mut self) -> Mutations<'a> {
|
||||||
|
Mutations::<'a> {
|
||||||
|
subtree: self.subtree,
|
||||||
|
dirty_scopes: self.dirty_scopes.drain().collect(),
|
||||||
|
templates: self.templates.split_off(0),
|
||||||
|
// Safety: this downcasts the lifetime from 'static to 'a
|
||||||
|
// This is safe because 'static outlives 'a
|
||||||
|
edits: unsafe { std::mem::transmute(self.edits.split_off(0)) },
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,3 +257,9 @@ pub enum Mutation<'a> {
|
|||||||
id: ElementId,
|
id: ElementId,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Mutation<'static> {
|
||||||
|
pub(crate) fn downcast_lifetime<'a>(self) -> Mutation<'a> {
|
||||||
|
unsafe { std::mem::transmute(self) }
|
||||||
|
}
|
||||||
|
}
|
||||||
+22
-30
@@ -8,6 +8,7 @@ use std::{
|
|||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
fmt::Arguments,
|
fmt::Arguments,
|
||||||
future::Future,
|
future::Future,
|
||||||
|
ops::Deref,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type TemplateId = &'static str;
|
pub type TemplateId = &'static str;
|
||||||
@@ -416,26 +417,14 @@ impl AnyValueContainer {
|
|||||||
return Self(std::rc::Rc::new(value));
|
return Self(std::rc::Rc::new(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a reference to the inner value without checking the type.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
/// The caller must ensure that the type of the inner value is `T`.
|
|
||||||
pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
|
|
||||||
unsafe { &*(self.0.as_ref() as *const _ as *const T) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a reference to the inner value.
|
/// Returns a reference to the inner value.
|
||||||
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
|
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
|
||||||
if self.0.our_typeid() == TypeId::of::<T>() {
|
self.0.deref().as_any().downcast_ref()
|
||||||
Some(unsafe { self.downcast_ref_unchecked() })
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if the inner value is of type `T`.
|
/// Checks if the type of the inner value is 'T'.
|
||||||
pub fn is<T: Any>(&self) -> bool {
|
pub fn is<T: Any>(&self) -> bool {
|
||||||
self.0.our_typeid() == TypeId::of::<T>()
|
self.0.deref().as_any().is::<T>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,9 +435,6 @@ fn test_any_value_rc() {
|
|||||||
assert_eq!(a.downcast_ref::<i64>(), None);
|
assert_eq!(a.downcast_ref::<i64>(), None);
|
||||||
assert!(a.is::<i32>());
|
assert!(a.is::<i32>());
|
||||||
assert!(!a.is::<i64>());
|
assert!(!a.is::<i64>());
|
||||||
unsafe {
|
|
||||||
assert_eq!(a.downcast_ref_unchecked::<i32>(), &1i32);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
@@ -503,45 +489,51 @@ impl<'a> PartialEq for AttributeValue<'a> {
|
|||||||
// The sync_attributes flag restricts any valuse to be sync and send.
|
// The sync_attributes flag restricts any valuse to be sync and send.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[cfg(feature = "sync_attributes")]
|
#[cfg(feature = "sync_attributes")]
|
||||||
pub trait AnyValue: Sync + Send {
|
pub trait AnyValue: Sync + Send + 'static {
|
||||||
fn any_cmp(&self, other: &dyn AnyValue) -> bool;
|
fn any_cmp(&self, other: &dyn AnyValue) -> bool;
|
||||||
fn our_typeid(&self) -> TypeId;
|
fn as_any(&self) -> &dyn Any;
|
||||||
|
fn type_id(&self) -> TypeId {
|
||||||
|
self.as_any().type_id()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "sync_attributes")]
|
#[cfg(feature = "sync_attributes")]
|
||||||
impl<T: Any + PartialEq + Send + Sync> AnyValue for T {
|
impl<T: Any + PartialEq + Send + Sync + 'static> AnyValue for T {
|
||||||
fn any_cmp(&self, other: &dyn AnyValue) -> bool {
|
fn any_cmp(&self, other: &dyn AnyValue) -> bool {
|
||||||
if self.our_typeid() != other.our_typeid() {
|
if self.type_id() != other.type_id() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self == unsafe { &*(other as *const _ as *const T) }
|
self == unsafe { &*(other as *const _ as *const T) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn our_typeid(&self) -> TypeId {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self.type_id()
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[cfg(not(feature = "sync_attributes"))]
|
#[cfg(not(feature = "sync_attributes"))]
|
||||||
pub trait AnyValue {
|
pub trait AnyValue: 'static {
|
||||||
fn any_cmp(&self, other: &dyn AnyValue) -> bool;
|
fn any_cmp(&self, other: &dyn AnyValue) -> bool;
|
||||||
fn our_typeid(&self) -> TypeId;
|
fn as_any(&self) -> &dyn Any;
|
||||||
|
fn type_id(&self) -> TypeId {
|
||||||
|
self.as_any().type_id()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "sync_attributes"))]
|
#[cfg(not(feature = "sync_attributes"))]
|
||||||
impl<T: Any + PartialEq> AnyValue for T {
|
impl<T: Any + PartialEq + 'static> AnyValue for T {
|
||||||
fn any_cmp(&self, other: &dyn AnyValue) -> bool {
|
fn any_cmp(&self, other: &dyn AnyValue) -> bool {
|
||||||
if self.our_typeid() != other.our_typeid() {
|
if self.type_id() != other.type_id() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self == unsafe { &*(other as *const _ as *const T) }
|
self == unsafe { &*(other as *const _ as *const T) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn our_typeid(&self) -> TypeId {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self.type_id()
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -489,7 +489,7 @@ impl VirtualDom {
|
|||||||
RenderReturn::Async(_) => unreachable!("Root scope cannot be an async component"),
|
RenderReturn::Async(_) => unreachable!("Root scope cannot be an async component"),
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe { std::mem::transmute(self.finalize()) }
|
self.finalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render whatever the VirtualDom has ready as fast as possible without requiring an executor to progress
|
/// Render whatever the VirtualDom has ready as fast as possible without requiring an executor to progress
|
||||||
@@ -594,7 +594,7 @@ impl VirtualDom {
|
|||||||
|
|
||||||
// If there's no pending suspense, then we have no reason to wait for anything
|
// If there's no pending suspense, then we have no reason to wait for anything
|
||||||
if self.scheduler.leaves.borrow().is_empty() {
|
if self.scheduler.leaves.borrow().is_empty() {
|
||||||
return unsafe { std::mem::transmute(self.finalize()) };
|
return self.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Poll the suspense leaves in the meantime
|
// Poll the suspense leaves in the meantime
|
||||||
@@ -608,17 +608,14 @@ impl VirtualDom {
|
|||||||
if let Either::Left((_, _)) = select(&mut deadline, pinned).await {
|
if let Either::Left((_, _)) = select(&mut deadline, pinned).await {
|
||||||
// release the borrowed
|
// release the borrowed
|
||||||
drop(work);
|
drop(work);
|
||||||
return unsafe { std::mem::transmute(self.finalize()) };
|
return self.finalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Swap the current mutations with a new
|
/// Swap the current mutations with a new
|
||||||
fn finalize(&mut self) -> Mutations<'static> {
|
fn finalize<'a>(&'a mut self) -> Mutations<'a> {
|
||||||
// todo: make this a routine
|
self.mutations.take()
|
||||||
let mut out = Mutations::default();
|
|
||||||
std::mem::swap(&mut self.mutations, &mut out);
|
|
||||||
out
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user