Use immutable strings.

This commit is contained in:
Stephen Chung
2020-05-25 13:44:28 +08:00
parent bbed4c6ef4
commit 99ea2b33c9
14 changed files with 251 additions and 191 deletions

View File

@@ -1,6 +1,6 @@
//! Helper module which defines the `Any` trait to to allow dynamic value handling.
use crate::parser::INT;
use crate::parser::{ImmutableString, INT};
use crate::r#unsafe::{unsafe_cast_box, unsafe_try_cast};
#[cfg(not(feature = "no_module"))]
@@ -151,7 +151,7 @@ pub struct Dynamic(pub(crate) Union);
pub enum Union {
Unit(()),
Bool(bool),
Str(Box<String>),
Str(ImmutableString),
Char(char),
Int(INT),
#[cfg(not(feature = "no_float"))]
@@ -178,6 +178,10 @@ impl Dynamic {
/// Is the value held by this `Dynamic` a particular type?
pub fn is<T: Variant + Clone>(&self) -> bool {
self.type_id() == TypeId::of::<T>()
|| match self.0 {
Union::Str(_) => TypeId::of::<String>() == TypeId::of::<T>(),
_ => false,
}
}
/// Get the TypeId of the value held by this `Dynamic`.
@@ -185,7 +189,7 @@ impl Dynamic {
match &self.0 {
Union::Unit(_) => TypeId::of::<()>(),
Union::Bool(_) => TypeId::of::<bool>(),
Union::Str(_) => TypeId::of::<String>(),
Union::Str(_) => TypeId::of::<ImmutableString>(),
Union::Char(_) => TypeId::of::<char>(),
Union::Int(_) => TypeId::of::<INT>(),
#[cfg(not(feature = "no_float"))]
@@ -342,6 +346,12 @@ impl Dynamic {
return Self(result);
} else if let Some(result) = dyn_value.downcast_ref::<char>().cloned().map(Union::Char) {
return Self(result);
} else if let Some(result) = dyn_value
.downcast_ref::<ImmutableString>()
.cloned()
.map(Union::Str)
{
return Self(result);
}
#[cfg(not(feature = "no_float"))]
@@ -358,7 +368,7 @@ impl Dynamic {
Err(var) => var,
};
var = match unsafe_cast_box::<_, String>(var) {
Ok(s) => return Self(Union::Str(s)),
Ok(s) => return Self(Union::Str(s.into())),
Err(var) => var,
};
#[cfg(not(feature = "no_index"))]
@@ -395,14 +405,22 @@ impl Dynamic {
/// assert_eq!(x.try_cast::<u32>().unwrap(), 42);
/// ```
pub fn try_cast<T: Variant>(self) -> Option<T> {
if TypeId::of::<T>() == TypeId::of::<Dynamic>() {
let type_id = TypeId::of::<T>();
if type_id == TypeId::of::<Dynamic>() {
return unsafe_cast_box::<_, T>(Box::new(self)).ok().map(|v| *v);
}
match self.0 {
Union::Unit(value) => unsafe_try_cast(value),
Union::Bool(value) => unsafe_try_cast(value),
Union::Str(value) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
Union::Str(value) => {
if type_id == TypeId::of::<ImmutableString>() {
unsafe_try_cast(value)
} else {
unsafe_try_cast((*value).clone())
}
}
Union::Char(value) => unsafe_try_cast(value),
Union::Int(value) => unsafe_try_cast(value),
#[cfg(not(feature = "no_float"))]
@@ -434,16 +452,21 @@ impl Dynamic {
/// assert_eq!(x.cast::<u32>(), 42);
/// ```
pub fn cast<T: Variant + Clone>(self) -> T {
//self.try_cast::<T>().unwrap()
let type_id = TypeId::of::<T>();
if TypeId::of::<T>() == TypeId::of::<Dynamic>() {
if type_id == TypeId::of::<Dynamic>() {
return *unsafe_cast_box::<_, T>(Box::new(self)).unwrap();
}
match self.0 {
Union::Unit(value) => unsafe_try_cast(value).unwrap(),
Union::Bool(value) => unsafe_try_cast(value).unwrap(),
Union::Str(value) => *unsafe_cast_box::<_, T>(value).unwrap(),
Union::Str(value) => if type_id == TypeId::of::<ImmutableString>() {
unsafe_try_cast(value)
} else {
unsafe_try_cast((*value).clone())
}
.unwrap(),
Union::Char(value) => unsafe_try_cast(value).unwrap(),
Union::Int(value) => unsafe_try_cast(value).unwrap(),
#[cfg(not(feature = "no_float"))]
@@ -469,7 +492,9 @@ impl Dynamic {
match &self.0 {
Union::Unit(value) => (value as &dyn Any).downcast_ref::<T>(),
Union::Bool(value) => (value as &dyn Any).downcast_ref::<T>(),
Union::Str(value) => (value.as_ref() as &dyn Any).downcast_ref::<T>(),
Union::Str(value) => (value as &dyn Any)
.downcast_ref::<T>()
.or_else(|| (value.as_ref() as &dyn Any).downcast_ref::<T>()),
Union::Char(value) => (value as &dyn Any).downcast_ref::<T>(),
Union::Int(value) => (value as &dyn Any).downcast_ref::<T>(),
#[cfg(not(feature = "no_float"))]
@@ -495,7 +520,7 @@ impl Dynamic {
match &mut self.0 {
Union::Unit(value) => (value as &mut dyn Any).downcast_mut::<T>(),
Union::Bool(value) => (value as &mut dyn Any).downcast_mut::<T>(),
Union::Str(value) => (value.as_mut() as &mut dyn Any).downcast_mut::<T>(),
Union::Str(value) => (value as &mut dyn Any).downcast_mut::<T>(),
Union::Char(value) => (value as &mut dyn Any).downcast_mut::<T>(),
Union::Int(value) => (value as &mut dyn Any).downcast_mut::<T>(),
#[cfg(not(feature = "no_float"))]
@@ -560,7 +585,7 @@ impl Dynamic {
/// Returns the name of the actual type if the cast fails.
pub fn take_string(self) -> Result<String, &'static str> {
match self.0 {
Union::Str(s) => Ok(*s),
Union::Str(s) => Ok((*s).clone()),
_ => Err(self.type_name()),
}
}
@@ -594,7 +619,12 @@ impl From<char> for Dynamic {
}
impl From<String> for Dynamic {
fn from(value: String) -> Self {
Self(Union::Str(Box::new(value)))
Self(Union::Str(value.into()))
}
}
impl From<ImmutableString> for Dynamic {
fn from(value: ImmutableString) -> Self {
Self(Union::Str(value))
}
}
#[cfg(not(feature = "no_index"))]