Add Dynamic::NULL to simplify this pointer binding.

This commit is contained in:
Stephen Chung
2022-11-08 16:16:42 +08:00
parent 6053aa1641
commit 8f128f37f0
16 changed files with 126 additions and 77 deletions

View File

@@ -55,6 +55,9 @@ pub struct Dynamic(pub(crate) Union);
///
/// Most variants are boxed to reduce the size.
pub enum Union {
/// An error value which should not exist.
Null,
/// The Unit value - ().
Unit((), Tag, AccessMode),
/// A boolean value.
@@ -178,6 +181,8 @@ impl Dynamic {
#[must_use]
pub const fn tag(&self) -> Tag {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(_, tag, _)
| Union::Bool(_, tag, _)
| Union::Str(_, tag, _)
@@ -203,6 +208,8 @@ impl Dynamic {
/// Attach arbitrary data to this [`Dynamic`].
pub fn set_tag(&mut self, value: Tag) -> &mut Self {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(_, ref mut tag, _)
| Union::Bool(_, ref mut tag, _)
| Union::Str(_, ref mut tag, _)
@@ -226,6 +233,12 @@ impl Dynamic {
}
self
}
/// Is this [`Dynamic`] null?
#[inline(always)]
#[must_use]
pub(crate) const fn is_null(&self) -> bool {
matches!(self.0, Union::Null)
}
/// Does this [`Dynamic`] hold a variant data type instead of one of the supported system
/// primitive types?
#[inline(always)]
@@ -307,6 +320,8 @@ impl Dynamic {
#[must_use]
pub fn type_id(&self) -> TypeId {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(..) => TypeId::of::<()>(),
Union::Bool(..) => TypeId::of::<bool>(),
Union::Str(..) => TypeId::of::<ImmutableString>(),
@@ -341,6 +356,8 @@ impl Dynamic {
#[must_use]
pub fn type_name(&self) -> &'static str {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(..) => "()",
Union::Bool(..) => "bool",
Union::Str(..) => "string",
@@ -385,6 +402,8 @@ impl Hash for Dynamic {
mem::discriminant(&self.0).hash(state);
match self.0 {
Union::Null => unreachable!(),
Union::Unit(..) => (),
Union::Bool(ref b, ..) => b.hash(state),
Union::Str(ref s, ..) => s.hash(state),
@@ -416,6 +435,8 @@ impl Hash for Dynamic {
impl fmt::Display for Dynamic {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(..) => Ok(()),
Union::Bool(ref v, ..) => fmt::Display::fmt(v, f),
Union::Str(ref v, ..) => fmt::Display::fmt(v, f),
@@ -509,6 +530,8 @@ impl fmt::Debug for Dynamic {
#[inline(never)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(ref v, ..) => fmt::Debug::fmt(v, f),
Union::Bool(ref v, ..) => fmt::Debug::fmt(v, f),
Union::Str(ref v, ..) => fmt::Debug::fmt(v, f),
@@ -619,6 +642,8 @@ impl Clone for Dynamic {
/// The cloned copy is marked read-write even if the original is read-only.
fn clone(&self) -> Self {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(v, tag, ..) => Self(Union::Unit(v, tag, ReadWrite)),
Union::Bool(v, tag, ..) => Self(Union::Bool(v, tag, ReadWrite)),
Union::Str(ref v, tag, ..) => Self(Union::Str(v.clone(), tag, ReadWrite)),
@@ -666,6 +691,9 @@ use std::f32::consts as FloatConstants;
use std::f64::consts as FloatConstants;
impl Dynamic {
/// A [`Dynamic`] containing a `null`.
pub(crate) const NULL: Self = Self(Union::Null);
/// A [`Dynamic`] containing a `()`.
pub const UNIT: Self = Self(Union::Unit((), DEFAULT_TAG_VALUE, ReadWrite));
/// A [`Dynamic`] containing a `true`.
@@ -888,6 +916,8 @@ impl Dynamic {
#[must_use]
pub(crate) const fn access_mode(&self) -> AccessMode {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(.., access)
| Union::Bool(.., access)
| Union::Str(.., access)
@@ -913,6 +943,8 @@ impl Dynamic {
/// Set the [`AccessMode`] for this [`Dynamic`].
pub(crate) fn set_access_mode(&mut self, typ: AccessMode) -> &mut Self {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(.., ref mut access)
| Union::Bool(.., ref mut access)
| Union::Str(.., ref mut access)
@@ -1107,6 +1139,7 @@ impl Dynamic {
let _access = self.access_mode();
match self.0 {
Union::Null => unreachable!(),
Union::Shared(..) => self,
_ => Self(Union::Shared(
crate::Locked::new(self).into(),
@@ -1151,6 +1184,8 @@ impl Dynamic {
reify!(self, |v: T| return Some(v));
match self.0 {
Union::Null => unreachable!(),
Union::Int(v, ..) => reify!(v => Option<T>),
#[cfg(not(feature = "no_float"))]
Union::Float(v, ..) => reify!(*v => Option<T>),
@@ -1485,6 +1520,7 @@ impl Dynamic {
}
match self.0 {
Union::Null => unreachable!(),
Union::Variant(ref v, ..) => (***v).as_any().downcast_ref::<T>(),
#[cfg(not(feature = "no_closure"))]
Union::Shared(..) => None,
@@ -1583,6 +1619,7 @@ impl Dynamic {
}
match self.0 {
Union::Null => unreachable!(),
Union::Variant(ref mut v, ..) => (***v).as_any_mut().downcast_mut::<T>(),
#[cfg(not(feature = "no_closure"))]
Union::Shared(..) => None,