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 {
Unit(()),
Bool(bool),
Str(String),
Str(Box<String>),
Char(char),
Int(INT),
#[cfg(not(feature = "no_float"))]
Float(FLOAT),
Array(Array),
Map(Box<Map>), // Box it to reduce size
Array(Box<Array>),
Map(Box<Map>),
Variant(Box<dyn Variant>),
}
@ -324,15 +324,22 @@ impl Dynamic {
cast_box::<_, Dynamic>(var)
.map(|x| x.0)
.or_else(|var| {
cast_box::<_, String>(var).map(Union::Str).or_else(|var| {
cast_box::<_, Array>(var).map(Union::Array).or_else(|var| {
cast_box::<_, Map>(var)
.map(|v| Union::Map(Box::new(v)))
.or_else(|var| -> Result<Union, ()> {
Ok(Union::Variant(var as Box<dyn Variant>))
cast_box::<_, String>(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)
.map(Box::new)
.map(Union::Map)
.or_else(|var| -> Result<Union, ()> {
Ok(Union::Variant(var as Box<dyn Variant>))
})
})
})
})
})
.unwrap(),
)
@ -360,12 +367,16 @@ impl Dynamic {
match &self.0 {
Union::Unit(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::Int(value) => (value as &dyn Variant).downcast_ref::<T>().cloned(),
#[cfg(not(feature = "no_float"))]
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)
.downcast_ref::<T>()
.cloned(),
@ -404,12 +415,12 @@ impl Dynamic {
match &self.0 {
Union::Unit(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::Int(value) => (value as &dyn Variant).downcast_ref::<T>(),
#[cfg(not(feature = "no_float"))]
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::Variant(value) => value.as_ref().downcast_ref::<T>(),
}
@ -426,12 +437,12 @@ impl Dynamic {
match &mut self.0 {
Union::Unit(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::Int(value) => (value as &mut dyn Variant).downcast_mut::<T>(),
#[cfg(not(feature = "no_float"))]
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::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.
pub(crate) fn take_string(self) -> Result<String, &'static str> {
match self.0 {
Union::Str(s) => Ok(s),
Union::Str(s) => Ok(*s),
_ => Err(self.type_name()),
}
}
@ -499,7 +510,7 @@ impl Dynamic {
Self(Union::Char(value))
}
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)) => {
// Only allows String or char
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)) => {
Ok(Dynamic::from_bool(rhs_value.contains_key(&c.to_string())))
}
@ -1177,7 +1179,9 @@ impl Engine {
Dynamic(Union::Str(rhs_value)) => {
// Only allows String or char
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))),
_ => Err(Box::new(EvalAltResult::ErrorInExpr(lhs.position()))),
}
@ -1314,7 +1318,7 @@ impl Engine {
.map(|val| arr.push(val))
})?;
Ok(Dynamic(Union::Array(arr)))
Ok(Dynamic(Union::Array(Box::new(arr))))
}
#[cfg(not(feature = "no_object"))]

View File

@ -330,12 +330,14 @@ impl Expr {
Self::False(_) => Dynamic::from_bool(false),
Self::Unit(_) => Dynamic::from_unit(),
Self::Array(items, _) if items.iter().all(Self::is_constant) => Dynamic(Union::Array(
items
.iter()
.map(Self::get_constant_value)
.collect::<Vec<_>>(),
)),
Self::Array(items, _) if items.iter().all(Self::is_constant) => {
Dynamic(Union::Array(Box::new(
items
.iter()
.map(Self::get_constant_value)
.collect::<Vec<_>>(),
)))
}
Self::Map(items, _) if items.iter().all(|(_, v, _)| v.is_constant()) => {
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::Int(value) => Some(Expr::IntegerConstant(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(false) => Some(Expr::False(pos)),
#[cfg(not(feature = "no_index"))]