Reduce size of Dynamic by boxing large types.

This commit is contained in:
Stephen Chung 2020-04-18 11:10:03 +08:00
parent f5fff828e8
commit a0bc49c867
3 changed files with 45 additions and 28 deletions

View File

@ -135,13 +135,13 @@ pub struct Dynamic(pub(crate) Union);
pub enum Union { pub enum Union {
Unit(()), Unit(()),
Bool(bool), Bool(bool),
Str(String), Str(Box<String>),
Char(char), Char(char),
Int(INT), Int(INT),
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Float(FLOAT), Float(FLOAT),
Array(Array), Array(Box<Array>),
Map(Box<Map>), // Box it to reduce size Map(Box<Map>),
Variant(Box<dyn Variant>), Variant(Box<dyn Variant>),
} }
@ -324,10 +324,17 @@ impl Dynamic {
cast_box::<_, Dynamic>(var) cast_box::<_, Dynamic>(var)
.map(|x| x.0) .map(|x| x.0)
.or_else(|var| { .or_else(|var| {
cast_box::<_, String>(var).map(Union::Str).or_else(|var| { cast_box::<_, String>(var)
cast_box::<_, Array>(var).map(Union::Array).or_else(|var| { .map(Box::new)
.map(Union::Str)
.or_else(|var| {
cast_box::<_, Array>(var)
.map(Box::new)
.map(Union::Array)
.or_else(|var| {
cast_box::<_, Map>(var) cast_box::<_, Map>(var)
.map(|v| Union::Map(Box::new(v))) .map(Box::new)
.map(Union::Map)
.or_else(|var| -> Result<Union, ()> { .or_else(|var| -> Result<Union, ()> {
Ok(Union::Variant(var as Box<dyn Variant>)) Ok(Union::Variant(var as Box<dyn Variant>))
}) })
@ -360,12 +367,16 @@ impl Dynamic {
match &self.0 { match &self.0 {
Union::Unit(value) => (value as &dyn Variant).downcast_ref::<T>().cloned(), Union::Unit(value) => (value as &dyn Variant).downcast_ref::<T>().cloned(),
Union::Bool(value) => (value as &dyn Variant).downcast_ref::<T>().cloned(), Union::Bool(value) => (value as &dyn Variant).downcast_ref::<T>().cloned(),
Union::Str(value) => (value as &dyn Variant).downcast_ref::<T>().cloned(), Union::Str(value) => (value.as_ref() as &dyn Variant)
.downcast_ref::<T>()
.cloned(),
Union::Char(value) => (value as &dyn Variant).downcast_ref::<T>().cloned(), Union::Char(value) => (value as &dyn Variant).downcast_ref::<T>().cloned(),
Union::Int(value) => (value as &dyn Variant).downcast_ref::<T>().cloned(), Union::Int(value) => (value as &dyn Variant).downcast_ref::<T>().cloned(),
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Union::Float(value) => (value as &dyn Variant).downcast_ref::<T>().cloned(), Union::Float(value) => (value as &dyn Variant).downcast_ref::<T>().cloned(),
Union::Array(value) => (value as &dyn Variant).downcast_ref::<T>().cloned(), Union::Array(value) => (value.as_ref() as &dyn Variant)
.downcast_ref::<T>()
.cloned(),
Union::Map(value) => (value.as_ref() as &dyn Variant) Union::Map(value) => (value.as_ref() as &dyn Variant)
.downcast_ref::<T>() .downcast_ref::<T>()
.cloned(), .cloned(),
@ -404,12 +415,12 @@ impl Dynamic {
match &self.0 { match &self.0 {
Union::Unit(value) => (value as &dyn Variant).downcast_ref::<T>(), Union::Unit(value) => (value as &dyn Variant).downcast_ref::<T>(),
Union::Bool(value) => (value as &dyn Variant).downcast_ref::<T>(), Union::Bool(value) => (value as &dyn Variant).downcast_ref::<T>(),
Union::Str(value) => (value as &dyn Variant).downcast_ref::<T>(), Union::Str(value) => (value.as_ref() as &dyn Variant).downcast_ref::<T>(),
Union::Char(value) => (value as &dyn Variant).downcast_ref::<T>(), Union::Char(value) => (value as &dyn Variant).downcast_ref::<T>(),
Union::Int(value) => (value as &dyn Variant).downcast_ref::<T>(), Union::Int(value) => (value as &dyn Variant).downcast_ref::<T>(),
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Union::Float(value) => (value as &dyn Variant).downcast_ref::<T>(), Union::Float(value) => (value as &dyn Variant).downcast_ref::<T>(),
Union::Array(value) => (value as &dyn Variant).downcast_ref::<T>(), Union::Array(value) => (value.as_ref() as &dyn Variant).downcast_ref::<T>(),
Union::Map(value) => (value.as_ref() as &dyn Variant).downcast_ref::<T>(), Union::Map(value) => (value.as_ref() as &dyn Variant).downcast_ref::<T>(),
Union::Variant(value) => value.as_ref().downcast_ref::<T>(), Union::Variant(value) => value.as_ref().downcast_ref::<T>(),
} }
@ -426,12 +437,12 @@ impl Dynamic {
match &mut self.0 { match &mut self.0 {
Union::Unit(value) => (value as &mut dyn Variant).downcast_mut::<T>(), Union::Unit(value) => (value as &mut dyn Variant).downcast_mut::<T>(),
Union::Bool(value) => (value as &mut dyn Variant).downcast_mut::<T>(), Union::Bool(value) => (value as &mut dyn Variant).downcast_mut::<T>(),
Union::Str(value) => (value as &mut dyn Variant).downcast_mut::<T>(), Union::Str(value) => (value.as_mut() as &mut dyn Variant).downcast_mut::<T>(),
Union::Char(value) => (value as &mut dyn Variant).downcast_mut::<T>(), Union::Char(value) => (value as &mut dyn Variant).downcast_mut::<T>(),
Union::Int(value) => (value as &mut dyn Variant).downcast_mut::<T>(), Union::Int(value) => (value as &mut dyn Variant).downcast_mut::<T>(),
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Union::Float(value) => (value as &mut dyn Variant).downcast_mut::<T>(), Union::Float(value) => (value as &mut dyn Variant).downcast_mut::<T>(),
Union::Array(value) => (value as &mut dyn Variant).downcast_mut::<T>(), Union::Array(value) => (value.as_mut() as &mut dyn Variant).downcast_mut::<T>(),
Union::Map(value) => (value.as_mut() as &mut dyn Variant).downcast_mut::<T>(), Union::Map(value) => (value.as_mut() as &mut dyn Variant).downcast_mut::<T>(),
Union::Variant(value) => value.as_mut().downcast_mut::<T>(), Union::Variant(value) => value.as_mut().downcast_mut::<T>(),
} }
@ -477,7 +488,7 @@ impl Dynamic {
/// Returns the name of the actual type if the cast fails. /// Returns the name of the actual type if the cast fails.
pub(crate) fn take_string(self) -> Result<String, &'static str> { pub(crate) fn take_string(self) -> Result<String, &'static str> {
match self.0 { match self.0 {
Union::Str(s) => Ok(s), Union::Str(s) => Ok(*s),
_ => Err(self.type_name()), _ => Err(self.type_name()),
} }
} }
@ -499,7 +510,7 @@ impl Dynamic {
Self(Union::Char(value)) Self(Union::Char(value))
} }
pub(crate) fn from_string(value: String) -> Self { pub(crate) fn from_string(value: String) -> Self {
Self(Union::Str(value)) Self(Union::Str(Box::new(value)))
} }
} }

View File

@ -1167,7 +1167,9 @@ impl Engine {
Dynamic(Union::Map(rhs_value)) => { Dynamic(Union::Map(rhs_value)) => {
// Only allows String or char // Only allows String or char
match lhs_value { match lhs_value {
Dynamic(Union::Str(s)) => Ok(Dynamic::from_bool(rhs_value.contains_key(&s))), Dynamic(Union::Str(s)) => {
Ok(Dynamic::from_bool(rhs_value.contains_key(s.as_ref())))
}
Dynamic(Union::Char(c)) => { Dynamic(Union::Char(c)) => {
Ok(Dynamic::from_bool(rhs_value.contains_key(&c.to_string()))) Ok(Dynamic::from_bool(rhs_value.contains_key(&c.to_string())))
} }
@ -1177,7 +1179,9 @@ impl Engine {
Dynamic(Union::Str(rhs_value)) => { Dynamic(Union::Str(rhs_value)) => {
// Only allows String or char // Only allows String or char
match lhs_value { match lhs_value {
Dynamic(Union::Str(s)) => Ok(Dynamic::from_bool(rhs_value.contains(&s))), Dynamic(Union::Str(s)) => {
Ok(Dynamic::from_bool(rhs_value.contains(s.as_ref())))
}
Dynamic(Union::Char(c)) => Ok(Dynamic::from_bool(rhs_value.contains(c))), Dynamic(Union::Char(c)) => Ok(Dynamic::from_bool(rhs_value.contains(c))),
_ => Err(Box::new(EvalAltResult::ErrorInExpr(lhs.position()))), _ => Err(Box::new(EvalAltResult::ErrorInExpr(lhs.position()))),
} }
@ -1314,7 +1318,7 @@ impl Engine {
.map(|val| arr.push(val)) .map(|val| arr.push(val))
})?; })?;
Ok(Dynamic(Union::Array(arr))) Ok(Dynamic(Union::Array(Box::new(arr))))
} }
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]

View File

@ -330,12 +330,14 @@ impl Expr {
Self::False(_) => Dynamic::from_bool(false), Self::False(_) => Dynamic::from_bool(false),
Self::Unit(_) => Dynamic::from_unit(), Self::Unit(_) => Dynamic::from_unit(),
Self::Array(items, _) if items.iter().all(Self::is_constant) => Dynamic(Union::Array( Self::Array(items, _) if items.iter().all(Self::is_constant) => {
Dynamic(Union::Array(Box::new(
items items
.iter() .iter()
.map(Self::get_constant_value) .map(Self::get_constant_value)
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
)), )))
}
Self::Map(items, _) if items.iter().all(|(_, v, _)| v.is_constant()) => { Self::Map(items, _) if items.iter().all(|(_, v, _)| v.is_constant()) => {
Dynamic(Union::Map(Box::new( Dynamic(Union::Map(Box::new(
@ -1818,7 +1820,7 @@ pub fn map_dynamic_to_expr(value: Dynamic, pos: Position) -> Option<Expr> {
Union::Unit(_) => Some(Expr::Unit(pos)), Union::Unit(_) => Some(Expr::Unit(pos)),
Union::Int(value) => Some(Expr::IntegerConstant(value, pos)), Union::Int(value) => Some(Expr::IntegerConstant(value, pos)),
Union::Char(value) => Some(Expr::CharConstant(value, pos)), Union::Char(value) => Some(Expr::CharConstant(value, pos)),
Union::Str(value) => Some(Expr::StringConstant(value.into(), pos)), Union::Str(value) => Some(Expr::StringConstant((*value).into(), pos)),
Union::Bool(true) => Some(Expr::True(pos)), Union::Bool(true) => Some(Expr::True(pos)),
Union::Bool(false) => Some(Expr::False(pos)), Union::Bool(false) => Some(Expr::False(pos)),
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]