Add an is_castable() function to stop casting to number for booleans in the @size helper.

This commit is contained in:
Tom Alexander 2020-06-14 18:27:28 -04:00
parent e54e20d254
commit a622a7e1bc
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
4 changed files with 45 additions and 5 deletions

View File

@ -317,6 +317,17 @@ impl Loopable for serde_json::Value {
}
impl Sizable for serde_json::Value {
fn is_castable(&self) -> bool {
match self {
serde_json::Value::Null => true,
serde_json::Value::Bool(_) => false,
serde_json::Value::Number(_) => true,
serde_json::Value::String(_) => true,
serde_json::Value::Array(_) => true,
serde_json::Value::Object(_) => true,
}
}
fn get_size<'a>(&'a self) -> Option<IceResult<'a>> {
match self {
serde_json::Value::Null => {
@ -368,7 +379,7 @@ impl Castable for serde_json::Value {
(serde_json::Value::Array(_), "number") => None,
(serde_json::Value::Object(_), "number") => None,
(serde_json::Value::String(text), "string") => Some(IceResult::from_borrowed(self)),
(serde_json::Value::String(_), "string") => Some(IceResult::from_borrowed(self)),
(serde_json::Value::Number(num), "string") => Some(IceResult::from_owned(
serde_json::Value::String(num.to_string()),
)),

View File

@ -65,6 +65,18 @@ pub trait Castable {
}
pub trait Sizable {
/// Special case: In DustJS the @size helper usually attempts to
/// cast to a number before calculating the size. The exception to
/// this is booleans. `Number(true) == 1` but `@size` on any
/// boolean is always 0. Make this function return false for any
/// type that casting to a number shouldn't be attempted.
///
/// Note: Its fine for objects that cannot be cast to a number to
/// return true here. False is only needed for cases where casting
/// to a number would cause a deviation in the final value for
/// `@size`.
fn is_castable(&self) -> bool;
fn get_size<'a>(&'a self) -> Option<IceResult<'a>>;
}

View File

@ -196,6 +196,16 @@ impl Walkable for OwnedLiteral {
}
impl Sizable for OwnedLiteral {
fn is_castable(&self) -> bool {
match self {
OwnedLiteral::LBoolean(_) => false,
OwnedLiteral::LFloat(_) => true,
OwnedLiteral::LPositiveInteger(_) => true,
OwnedLiteral::LNegativeInteger(_) => true,
OwnedLiteral::LString(_) => true,
}
}
fn get_size<'a>(&'a self) -> Option<IceResult<'a>> {
match self {
OwnedLiteral::LBoolean(_) => {

View File

@ -730,7 +730,6 @@ impl<'a> DustRenderer<'a> {
maybe_ice
.as_ref()
.map(|ice| ice.get_context_element_reference())
// .map(|ce| ce.get_size())
});
match value_ce {
// If "key" is not on the @size tag at all, render 0.
@ -742,8 +741,8 @@ impl<'a> DustRenderer<'a> {
// numbers, and if that succeeds it uses the
// number, otherwise we'll get the size of the
// original type.
match ce.cast_to_type("number") {
Some(ice) => {
match (ce.cast_to_type("number"), ce.is_castable()) {
(Some(ice), true) => {
return ice
.get_context_element_reference()
.get_size()
@ -752,7 +751,15 @@ impl<'a> DustRenderer<'a> {
})
.unwrap_or(Ok("".to_owned()))
}
None => {
(Some(_), false) => {
return ce
.get_size()
.map(|ce_size| {
ce_size.get_context_element_reference().render(&Vec::new())
})
.unwrap_or(Ok("".to_owned()))
}
(None, _) => {
return ce
.get_size()
.map(|ce_size| {