Repository: cobalt-org/liquid-rust
Pull request #370 (2019-12-17 19:50:49)

feat(value): Support a ValueCow
BREAKING CHANGE: Some limits with making `Value` a type alias.

- [ ] Tests created for any new feature or regression tests for bugfixes.



Patch:
diff --git a/crates/value/src/values.rs b/crates/value/src/values.rs
index 8019b81..7bb4cdb 100644
--- a/crates/value/src/values.rs
+++ b/crates/value/src/values.rs
@@ -6,12 +6,15 @@ use super::map;
 use super::Scalar;
 use super::ScalarCow;
 
+/// An enum to represent different value types
+pub type Value = ValueCow<'static>;
+
 /// An enum to represent different value types
 #[derive(Clone, Debug, Serialize, Deserialize)]
 #[serde(untagged)]
-pub enum Value {
+pub enum ValueCow<'v> {
     /// A scalar value.
-    Scalar(Scalar),
+    Scalar(ScalarCow<'v>),
     /// A sequence of `Value`s.
     Array(Array),
     /// A sequence of key/`Value` pairs.
@@ -30,16 +33,16 @@ pub type Array = Vec<Value>;
 /// Type representing a Liquid object, payload of the `Value::Object` variant
 pub type Object = map::Map;
 
-impl Value {
+impl<'v> ValueCow<'v> {
     /// Create as a `Scalar`.
-    pub fn scalar<T: Into<Scalar>>(value: T) -> Self {
-        Value::Scalar(Scalar::new(value))
+    pub fn scalar<T: Into<ScalarCow<'v>>>(value: T) -> Self {
+        ValueCow::Scalar(ScalarCow::new(value))
     }
 
     /// Create as an `Array`.
-    pub fn array<I: IntoIterator<Item = Self>>(iter: I) -> Self {
+    pub fn array<I: IntoIterator<Item = Value>>(iter: I) -> Value {
         let v: Array = iter.into_iter().collect();
-        Value::Array(v)
+        ValueCow::Array(v)
     }
 
     /// A `Display` for a `Scalar` as source code.
@@ -55,24 +58,26 @@ impl Value {
     /// Interpret as a string.
     pub fn to_str(&self) -> borrow::Cow<'_, str> {
         match *self {
-            Value::Scalar(ref x) => x.to_str(),
-            Value::Array(_) | Value::Object(_) => borrow::Cow::Owned(self.render().to_string()),
-            Value::Nil | Value::Empty | Value::Blank => borrow::Cow::Borrowed(""),
+            ValueCow::Scalar(ref x) => x.to_str(),
+            ValueCow::Array(_) | ValueCow::Object(_) => {
+                borrow::Cow::Owned(self.render().to_string())
+            }
+            ValueCow::Nil | ValueCow::Empty | ValueCow::Blank => borrow::Cow::Borrowed(""),
         }
     }
 
     /// Extracts the scalar value if it is a scalar.
-    pub fn as_scalar(&self) -> Option<&Scalar> {
+    pub fn as_scalar(&self) -> Option<&ScalarCow<'v>> {
         match *self {
-            Value::Scalar(ref s) => Some(s),
+            ValueCow::Scalar(ref s) => Some(s),
             _ => None,
         }
     }
 
     /// Extracts the scalar value if it is a scalar.
-    pub fn into_scalar(self) -> Option<Scalar> {
+    pub fn into_scalar(self) -> Option<ScalarCow<'v>> {
         match self {
-            Value::Scalar(s) => Some(s),
+            ValueCow::Scalar(s) => Some(s),
             _ => None,
         }
     }
@@ -85,7 +90,7 @@ impl Value {
     /// Extracts the array value if it is an array.
     pub fn as_array(&self) -> Option<&Array> {
         match *self {
-            Value::Array(ref s) => Some(s),
+            ValueCow::Array(ref s) => Some(s),
             _ => None,
         }
     }
@@ -93,7 +98,7 @@ impl Value {
     /// Extracts the array value if it is an array.
     pub fn into_array(self) -> Option<Array> {
         match self {
-            Value::Array(s) => Some(s),
+            ValueCow::Array(s) => Some(s),
             _ => None,
         }
     }
@@ -106,7 +111,7 @@ impl Value {
     /// Extracts the object value if it is a object.
     pub fn as_object(&self) -> Option<&Object> {
         match *self {
-            Value::Object(ref s) => Some(s),
+            ValueCow::Object(ref s) => Some(s),
             _ => None,
         }
     }
@@ -114,7 +119,7 @@ impl Value {
     /// Extracts the object value if it is a object.
     pub fn into_object(self) -> Option<Object> {
         match self {
-            Value::Object(s) => Some(s),
+            ValueCow::Object(s) => Some(s),
             _ => None,
         }
     }
@@ -127,7 +132,7 @@ impl Value {
     /// Tests whether this value is Nil
     pub fn is_nil(&self) -> bool {
         match *self {
-            Value::Nil => true,
+            ValueCow::Nil => true,
             _ => false,
         }
     }
@@ -135,7 +140,7 @@ impl Value {
     /// Tests whether this value is Empty
     pub fn is_empty(&self) -> bool {
         match *self {
-            Value::Empty => true,
+            ValueCow::Empty => true,
             _ => false,
         }
     }
@@ -143,7 +148,7 @@ impl Value {
     /// Tests whether this value is Blank
     pub fn is_blank(&self) -> bool {
         match *self {
-            Value::Blank => true,
+            ValueCow::Blank => true,
             _ => false,
         }
     }
@@ -152,40 +157,40 @@ impl Value {
     pub fn is_truthy(&self) -> bool {
         // encode Ruby truthiness: all values except false and nil are true
         match *self {
-            Value::Scalar(ref x) => x.is_truthy(),
-            Value::Nil | Value::Empty | Value::Blank => false,
-            Value::Array(_) | Value::Object(_) => true,
+            ValueCow::Scalar(ref x) => x.is_truthy(),
+            ValueCow::Nil | ValueCow::Empty | ValueCow::Blank => false,
+            ValueCow::Array(_) | ValueCow::Object(_) => true,
         }
     }
 
     /// Whether a default constructed value.
     pub fn is_default(&self) -> bool {
         match *self {
-            Value::Scalar(ref x) => x.is_default(),
-            Value::Nil => true,
-            Value::Empty => true,
-            Value::Blank => true,
-            Value::Array(ref x) => x.is_empty(),
-            Value::Object(ref x) => x.is_empty(),
+            ValueCow::Scalar(ref x) => x.is_default(),
+            ValueCow::Nil => true,
+            ValueCow::Empty => true,
+            ValueCow::Blank => true,
+            ValueCow::Array(ref x) => x.is_empty(),
+            ValueCow::Object(ref x) => x.is_empty(),
         }
     }
 
     /// Report the data type (generally for error reporting).
     pub fn type_name(&self) -> &'static str {
         match *self {
-            Value::Scalar(ref x) => x.type_name(),
-            Value::Nil => "nil",
-            Value::Empty => "empty",
-            Value::Blank => "blank",
-            Value::Array(_) => "array",
-            Value::Object(_) => "object",
+            ValueCow::Scalar(ref x) => x.type_name(),
+            ValueCow::Nil => "nil",
+            ValueCow::Empty => "empty",
+            ValueCow::Blank => "blank",
+            ValueCow::Array(_) => "array",
+            ValueCow::Object(_) => "object",
         }
     }
 
     /// Access a contained `Value`.
     pub fn contains_key(&self, index: &ScalarCow<'_>) -> bool {
         match *self {
-            Value::Array(ref x) => {
+            ValueCow::Array(ref x) => {
                 if let Some(index) = index.to_integer() {
                     let index = convert_index(index, x.len());
                     index < x.len()
@@ -196,7 +201,7 @@ impl Value {
                     }
                 }
             }
-            Value::Object(ref x) => x.contains_key(index.to_str().as_ref()),
+            ValueCow::Object(ref x) => x.contains_key(index.to_str().as_ref()),
             _ => false,
         }
     }
@@ -204,13 +209,13 @@ impl Value {
     /// Keys available for lookup.
     pub fn keys(&self) -> Keys {
         let v = match *self {
-            Value::Array(ref x) => {
+            ValueCow::Array(ref x) => {
                 let start: i32 = 0;
                 let end = x.len() as i32;
                 let keys: Vec<_> = (start..end).map(Scalar::new).collect();
                 keys
             }
-            Value::Object(ref x) => x
+            ValueCow::Object(ref x) => x
                 .keys()
                 .map(|s| match *s {
                     borrow::Cow::Borrowed(s) => Scalar::new(s),
@@ -225,7 +230,7 @@ impl Value {
     /// Access a contained `Value`.
     pub fn get<'s>(&'s self, index: &ScalarCow<'_>) -> Option<&'s Self> {
         match *self {
-            Value::Array(ref x) => {
+            ValueCow::Array(ref x) => {
                 if let Some(index) = index.to_integer() {
                     let index = convert_index(index, x.len());
                     x.get(index as usize)
@@ -237,7 +242,7 @@ impl Value {
                     }
                 }
             }
-            Value::Object(ref x) => x.get(index.to_str().as_ref()),
+            ValueCow::Object(ref x) => x.get(index.to_str().as_ref()),
             _ => None,
         }
     }
@@ -302,29 +307,29 @@ impl PartialOrd<Value> for Value {
 
 /// A `Display` for a `Scalar` as source code.
 #[derive(Debug)]
-pub struct ValueSource<'s>(&'s Value);
+pub struct ValueSource<'s>(&'s ValueCow<'s>);
 
 impl<'s> fmt::Display for ValueSource<'s> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {
-            Value::Scalar(ref x) => write!(f, "{}", x.render())?,
-            Value::Array(ref x) => {
+            ValueCow::Scalar(ref x) => write!(f, "{}", x.render())?,
+            ValueCow::Array(ref x) => {
                 write!(f, "[")?;
                 for item in x {
                     write!(f, "{}, ", item.render())?;
                 }
                 write!(f, "]")?;
             }
-            Value::Object(ref x) => {
+            ValueCow::Object(ref x) => {
                 write!(f, "{{")?;
                 for (k, v) in x {
                     write!(f, r#""{}": {}, "#, k, v.render())?;
                 }
                 write!(f, "}}")?;
             }
-            Value::Nil => write!(f, "nil")?,
-            Value::Empty => write!(f, "empty")?,
-            Value::Blank => write!(f, "blank")?,
+            ValueCow::Nil => write!(f, "nil")?,
+            ValueCow::Empty => write!(f, "empty")?,
+            ValueCow::Blank => write!(f, "blank")?,
         }
         Ok(())
     }
@@ -332,24 +337,24 @@ impl<'s> fmt::Display for ValueSource<'s> {
 
 /// A `Display` for a `Value` rendered for the user.
 #[derive(Debug)]
-pub struct ValueRendered<'s>(&'s Value);
+pub struct ValueRendered<'s>(&'s ValueCow<'s>);
 
 impl<'s> fmt::Display for ValueRendered<'s> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // Must match `Value::to_str`
+        // Must match `ValueCow::to_str`
         match self.0 {
-            Value::Scalar(ref x) => write!(f, "{}", x.render())?,
-            Value::Array(ref x) => {
+            ValueCow::Scalar(ref x) => write!(f, "{}", x.render())?,
+            ValueCow::Array(ref x) => {
                 for item in x {
                     write!(f, "{}", item.render())?;
                 }
             }
-            Value::Object(ref x) => {
+            ValueCow::Object(ref x) => {
                 for (k, v) in x {
                     write!(f, "{}{}", k, v.render())?;
                 }
             }
-            Value::Nil | Value::Empty | Value::Blank => (),
+            ValueCow::Nil | ValueCow::Empty | ValueCow::Blank => (),
         }
         Ok(())
     }
@@ -357,44 +362,42 @@ impl<'s> fmt::Display for ValueRendered<'s> {
 
 fn value_eq(lhs: &Value, rhs: &Value) -> bool {
     match (lhs, rhs) {
-        (&Value::Scalar(ref x), &Value::Scalar(ref y)) => x == y,
-        (&Value::Array(ref x), &Value::Array(ref y)) => x == y,
-        (&Value::Object(ref x), &Value::Object(ref y)) => x == y,
+        (&ValueCow::Scalar(ref x), &ValueCow::Scalar(ref y)) => x == y,
+        (&ValueCow::Array(ref x), &ValueCow::Array(ref y)) => x == y,
+        (&ValueCow::Object(ref x), &ValueCow::Object(ref y)) => x == y,
 
         // encode a best-guess of empty rules
         // See tables in https://stackoverflow.com/questions/885414/a-concise-explanation-of-nil-v-empty-v-blank-in-ruby-on-rails
-        (&Value::Nil, &Value::Nil)
-        | (&Value::Empty, &Value::Empty)
-        | (&Value::Blank, &Value::Blank)
-        | (&Value::Empty, &Value::Blank)
-        | (&Value::Blank, &Value::Empty) => true,
-
-        (&Value::Empty, &Value::Scalar(ref s)) | (&Value::Scalar(ref s), &Value::Empty) => {
-            s.to_str().is_empty()
-        }
-        (&Value::Empty, &Value::Array(ref s)) | (&Value::Array(ref s), &Value::Empty) => {
-            s.is_empty()
-        }
-        (&Value::Empty, &Value::Object(ref s)) | (&Value::Object(ref s), &Value::Empty) => {
-            s.is_empty()
-        }
-
-        (&Value::Nil, &Value::Blank) | (&Value::Blank, &Value::Nil) => true,
-        (&Value::Blank, &Value::Scalar(ref s)) | (&Value::Scalar(ref s), &Value::Blank) => {
+        (&ValueCow::Nil, &ValueCow::Nil)
+        | (&ValueCow::Empty, &ValueCow::Empty)
+        | (&ValueCow::Blank, &ValueCow::Blank)
+        | (&ValueCow::Empty, &ValueCow::Blank)
+        | (&ValueCow::Blank, &ValueCow::Empty) => true,
+
+        (&ValueCow::Empty, &ValueCow::Scalar(ref s))
+        | (&ValueCow::Scalar(ref s), &ValueCow::Empty) => s.to_str().is_empty(),
+        (&ValueCow::Empty, &ValueCow::Array(ref s))
+        | (&ValueCow::Array(ref s), &ValueCow::Empty) => s.is_empty(),
+        (&ValueCow::Empty, &ValueCow::Object(ref s))
+        | (&ValueCow::Object(ref s), &ValueCow::Empty) => s.is_empty(),
+
+        (&ValueCow::Nil, &ValueCow::Blank) | (&ValueCow::Blank, &ValueCow::Nil) => true,
+        (&ValueCow::Blank, &ValueCow::Scalar(ref s))
+        | (&ValueCow::Scalar(ref s), &ValueCow::Blank) => {
             s.to_str().trim().is_empty() || !s.to_bool().unwrap_or(true)
         }
-        (&Value::Blank, &Value::Array(ref s)) | (&Value::Array(ref s), &Value::Blank) => {
-            s.is_empty()
-        }
-        (&Value::Blank, &Value::Object(ref s)) | (&Value::Object(ref s), &Value::Blank) => {
-            s.is_empty()
-        }
+        (&ValueCow::Blank, &ValueCow::Array(ref s))
+        | (&ValueCow::Array(ref s), &ValueCow::Blank) => s.is_empty(),
+        (&ValueCow::Blank, &ValueCow::Object(ref s))
+        | (&ValueCow::Object(ref s), &ValueCow::Blank) => s.is_empty(),
 
         // encode Ruby truthiness: all values except false and nil are true
-        (&Value::Nil, &Value::Scalar(ref b)) | (&Value::Scalar(ref b), &Value::Nil) => {
+        (&ValueCow::Nil, &ValueCow::Scalar(ref b)) | (&ValueCow::Scalar(ref b), &ValueCow::Nil) => {
             !b.to_bool().unwrap_or(true)
         }
-        (_, &Value::Scalar(ref b)) | (&Value::Scalar(ref b), _) => b.to_bool().unwrap_or(false),
+        (_, &ValueCow::Scalar(ref b)) | (&ValueCow::Scalar(ref b), _) => {
+            b.to_bool().unwrap_or(false)
+        }
 
         _ => false,
     }
@@ -402,9 +405,9 @@ fn value_eq(lhs: &Value, rhs: &Value) -> bool {
 
 fn value_cmp(lhs: &Value, rhs: &Value) -> Option<Ordering> {
     match (lhs, rhs) {
-        (&Value::Scalar(ref x), &Value::Scalar(ref y)) => x.partial_cmp(y),
-        (&Value::Array(ref x), &Value::Array(ref y)) => x.iter().partial_cmp(y.iter()),
-        (&Value::Object(ref x), &Value::Object(ref y)) => x.iter().partial_cmp(y.iter()),
+        (&ValueCow::Scalar(ref x), &ValueCow::Scalar(ref y)) => x.partial_cmp(y),
+        (&ValueCow::Array(ref x), &ValueCow::Array(ref y)) => x.iter().partial_cmp(y.iter()),
+        (&ValueCow::Object(ref x), &ValueCow::Object(ref y)) => x.iter().partial_cmp(y.iter()),
         _ => None,
     }
 }
@@ -415,17 +418,17 @@ mod test {
 
     #[test]
     fn test_to_string_scalar() {
-        let val = Value::scalar(42f64);
+        let val = ValueCow::scalar(42f64);
         assert_eq!(&val.render().to_string(), "42");
         assert_eq!(&val.to_str(), "42");
     }
 
     #[test]
     fn test_to_string_array() {
-        let val = Value::Array(vec![
-            Value::scalar(3f64),
-            Value::scalar("test"),
-            Value::scalar(5.3),
+        let val = ValueCow::Array(vec![
+            ValueCow::scalar(3f64),
+            ValueCow::scalar("test"),
+            ValueCow::scalar(5.3),
         ]);
         assert_eq!(&val.render().to_string(), "3test5.3");
         assert_eq!(&val.to_str(), "3test5.3");
@@ -435,33 +438,36 @@ mod test {
 
     #[test]
     fn test_to_string_nil() {
-        assert_eq!(&Value::Nil.render().to_string(), "");
-        assert_eq!(&Value::Nil.to_str(), "");
+        assert_eq!(&ValueCow::Nil.render().to_string(), "");
+        assert_eq!(&ValueCow::Nil.to_str(), "");
     }
 
     #[test]
     fn scalar_equality() {
-        assert_eq!(Value::scalar("alpha"), Value::scalar("alpha"));
-        assert_eq!(Value::scalar(""), Value::scalar(""));
-        assert!(Value::scalar("alpha") != Value::scalar("beta"));
-        assert!(Value::scalar("beta") != Value::scalar("alpha"));
+        assert_eq!(ValueCow::scalar("alpha"), ValueCow::scalar("alpha"));
+        assert_eq!(ValueCow::scalar(""), ValueCow::scalar(""));
+        assert!(ValueCow::scalar("alpha") != ValueCow::scalar("beta"));
+        assert!(ValueCow::scalar("beta") != ValueCow::scalar("alpha"));
     }
 
     #[test]
     fn scalars_have_ruby_truthiness() {
         // all strings in ruby are true
-        assert_eq!(Value::scalar(true), Value::scalar("All strings are truthy"));
-        assert_eq!(Value::scalar(true), Value::scalar(""));
-        assert!(Value::scalar("").is_truthy());
+        assert_eq!(
+            ValueCow::scalar(true),
+            ValueCow::scalar("All strings are truthy")
+        );
+        assert_eq!(ValueCow::scalar(true), ValueCow::scalar(""));
+        assert!(ValueCow::scalar("").is_truthy());
 
-        assert_eq!(Value::scalar(true), Value::scalar(true));
-        assert!(Value::scalar(true) != Value::scalar(false));
+        assert_eq!(ValueCow::scalar(true), ValueCow::scalar(true));
+        assert!(ValueCow::scalar(true) != ValueCow::scalar(false));
     }
 
     #[test]
     fn array_equality() {
-        let a = Value::Array(vec![Value::scalar("one"), Value::scalar("two")]);
-        let b = Value::Array(vec![Value::scalar("alpha"), Value::scalar("beta")]);
+        let a = ValueCow::Array(vec![ValueCow::scalar("one"), ValueCow::scalar("two")]);
+        let b = ValueCow::Array(vec![ValueCow::scalar("alpha"), ValueCow::scalar("beta")]);
 
         assert_eq!(a, a);
         assert!(a != b);
@@ -470,30 +476,30 @@ mod test {
 
     #[test]
     fn arrays_have_ruby_truthiness() {
-        assert_eq!(Value::scalar(true), Value::Array(Vec::new()));
-        assert!(Value::Array(Vec::new()).is_truthy());
+        assert_eq!(ValueCow::scalar(true), ValueCow::Array(Vec::new()));
+        assert!(ValueCow::Array(Vec::new()).is_truthy());
     }
 
     #[test]
     fn object_equality() {
         let a: Object = [
-            ("alpha".into(), Value::scalar("1")),
-            ("beta".into(), Value::scalar(2f64)),
+            ("alpha".into(), ValueCow::scalar("1")),
+            ("beta".into(), ValueCow::scalar(2f64)),
         ]
         .iter()
         .cloned()
         .collect();
-        let a = Value::Object(a);
+        let a = ValueCow::Object(a);
 
         let b: Object = [
-            ("alpha".into(), Value::scalar("1")),
-            ("beta".into(), Value::scalar(2f64)),
-            ("gamma".into(), Value::Array(vec![])),
+            ("alpha".into(), ValueCow::scalar("1")),
+            ("beta".into(), ValueCow::scalar(2f64)),
+            ("gamma".into(), ValueCow::Array(vec![])),
         ]
         .iter()
         .cloned()
         .collect();
-        let b = Value::Object(b);
+        let b = ValueCow::Object(b);
 
         assert_eq!(a, a);
         assert!(a != b);
@@ -502,53 +508,53 @@ mod test {
 
     #[test]
     fn objects_have_ruby_truthiness() {
-        assert_eq!(Value::scalar(true), Value::Object(Object::new()));
-        assert!(Value::Object(Object::new()).is_truthy());
+        assert_eq!(ValueCow::scalar(true), ValueCow::Object(Object::new()));
+        assert!(ValueCow::Object(Object::new()).is_truthy());
     }
 
     #[test]
     fn nil_equality() {
-        assert_eq!(Value::Nil, Value::Nil);
+        assert_eq!(ValueCow::Nil, ValueCow::Nil);
     }
 
     #[test]
     fn nils_have_ruby_truthiness() {
-        assert_eq!(Value::scalar(false), Value::Nil);
-        assert!(!Value::Nil.is_truthy());
+        assert_eq!(ValueCow::scalar(false), ValueCow::Nil);
+        assert!(!ValueCow::Nil.is_truthy());
 
-        assert_eq!(Value::scalar(false), Value::Nil);
-        assert!(Value::scalar(true) != Value::Nil);
-        assert!(Value::scalar("") != Value::Nil);
+        assert_eq!(ValueCow::scalar(false), ValueCow::Nil);
+        assert!(ValueCow::scalar(true) != ValueCow::Nil);
+        assert!(ValueCow::scalar("") != ValueCow::Nil);
     }
 
     #[test]
     fn empty_equality() {
         // Truth table from https://stackoverflow.com/questions/885414/a-concise-explanation-of-nil-v-empty-v-blank-in-ruby-on-rails
-        assert_eq!(Value::Empty, Value::Empty);
-        assert_eq!(Value::Empty, Value::Blank);
-        assert_eq!(Value::Empty, liquid_value!(""));
-        assert_ne!(Value::Empty, liquid_value!(" "));
-        assert_eq!(Value::Empty, liquid_value!([]));
-        assert_ne!(Value::Empty, liquid_value!([nil]));
-        assert_eq!(Value::Empty, liquid_value!({}));
-        assert_ne!(Value::Empty, liquid_value!({ "a": nil }));
+        assert_eq!(ValueCow::Empty, ValueCow::Empty);
+        assert_eq!(ValueCow::Empty, ValueCow::Blank);
+        assert_eq!(ValueCow::Empty, liquid_value!(""));
+        assert_ne!(ValueCow::Empty, liquid_value!(" "));
+        assert_eq!(ValueCow::Empty, liquid_value!([]));
+        assert_ne!(ValueCow::Empty, liquid_value!([nil]));
+        assert_eq!(ValueCow::Empty, liquid_value!({}));
+        assert_ne!(ValueCow::Empty, liquid_value!({ "a": nil }));
     }
 
     #[test]
     fn blank_equality() {
         // Truth table from https://stackoverflow.com/questions/885414/a-concise-explanation-of-nil-v-empty-v-blank-in-ruby-on-rails
-        assert_eq!(Value::Blank, Value::Blank);
-        assert_eq!(Value::Blank, Value::Empty);
-        assert_eq!(Value::Blank, liquid_value!(nil));
-        assert_eq!(Value::Blank, liquid_value!(false));
-        assert_ne!(Value::Blank, liquid_value!(true));
-        assert_ne!(Value::Blank, liquid_value!(0));
-        assert_ne!(Value::Blank, liquid_value!(1));
-        assert_eq!(Value::Blank, liquid_value!(""));
-        assert_eq!(Value::Blank, liquid_value!(" "));
-        assert_eq!(Value::Blank, liquid_value!([]));
-        assert_ne!(Value::Blank, liquid_value!([nil]));
-        assert_eq!(Value::Blank, liquid_value!({}));
-        assert_ne!(Value::Blank, liquid_value!({ "a": nil }));
+        assert_eq!(ValueCow::Blank, ValueCow::Blank);
+        assert_eq!(ValueCow::Blank, ValueCow::Empty);
+        assert_eq!(ValueCow::Blank, liquid_value!(nil));
+        assert_eq!(ValueCow::Blank, liquid_value!(false));
+        assert_ne!(ValueCow::Blank, liquid_value!(true));
+        assert_ne!(ValueCow::Blank, liquid_value!(0));
+        assert_ne!(ValueCow::Blank, liquid_value!(1));
+        assert_eq!(ValueCow::Blank, liquid_value!(""));
+        assert_eq!(ValueCow::Blank, liquid_value!(" "));
+        assert_eq!(ValueCow::Blank, liquid_value!([]));
+        assert_ne!(ValueCow::Blank, liquid_value!([nil]));
+        assert_eq!(ValueCow::Blank, liquid_value!({}));
+        assert_ne!(ValueCow::Blank, liquid_value!({ "a": nil }));
     }
 }


Test patch:
diff --git a/tests/test_helper.rs b/tests/test_helper.rs
index 8471fb3..ed6a5c2 100644
--- a/tests/test_helper.rs
+++ b/tests/test_helper.rs
@@ -2,7 +2,7 @@ extern crate chrono;
 extern crate liquid;
 extern crate regex;
 
-pub use liquid::value::Value::Nil;
+pub use liquid::value::ValueCow::Nil;
 
 #[allow(dead_code)]
 pub fn date(y: i32, m: u32, d: u32) -> liquid::value::Value {