1use std::borrow;
2use std::cmp::Ordering;
3use std::fmt;
4
5use itertools;
6
7use super::map;
8use super::Scalar;
9use super::ScalarCow;
10
11#[derive(Clone, Debug, Serialize, Deserialize)]
13#[serde(untagged)]
14pub enum Value {
15 Scalar(Scalar),
17 Array(Array),
19 Object(Object),
21 Nil,
23 Empty,
25 Blank,
27}
28
29pub type Array = Vec<Value>;
31
32pub type Object = map::Map;
34
35impl Value {
36 pub fn scalar<T: Into<Scalar>>(value: T) -> Self {
38 Value::Scalar(Scalar::new(value))
39 }
40
41 pub fn array<I: IntoIterator<Item = Self>>(iter: I) -> Self {
43 let v: Array = iter.into_iter().collect();
44 Value::Array(v)
45 }
46
47 pub fn nil() -> Self {
49 Value::Nil
50 }
51
52 pub fn source(&self) -> ValueSource<'_> {
54 ValueSource(&self)
55 }
56
57 pub fn render(&self) -> ValueRendered<'_> {
59 ValueRendered(&self)
60 }
61
62 pub fn to_str(&self) -> borrow::Cow<'_, str> {
64 match *self {
65 Value::Scalar(ref x) => x.to_str(),
66 Value::Array(ref x) => {
67 let arr: Vec<_> = x.iter().map(|v| v.render()).collect();
68 borrow::Cow::Owned(itertools::join(arr, ""))
69 }
70 Value::Object(ref x) => {
71 let arr: Vec<_> = x
72 .iter()
73 .map(|(k, v)| format!("{}{}", k, v.render()))
74 .collect();
75 borrow::Cow::Owned(itertools::join(arr, ""))
76 }
77 Value::Nil | Value::Empty | Value::Blank => borrow::Cow::Borrowed(""),
78 }
79 }
80
81 pub fn as_scalar(&self) -> Option<&Scalar> {
83 match *self {
84 Value::Scalar(ref s) => Some(s),
85 _ => None,
86 }
87 }
88
89 pub fn into_scalar(self) -> Option<Scalar> {
91 match self {
92 Value::Scalar(s) => Some(s),
93 _ => None,
94 }
95 }
96
97 pub fn is_scalar(&self) -> bool {
99 self.as_scalar().is_some()
100 }
101
102 pub fn as_array(&self) -> Option<&Array> {
104 match *self {
105 Value::Array(ref s) => Some(s),
106 _ => None,
107 }
108 }
109
110 pub fn as_array_mut(&mut self) -> Option<&mut Array> {
112 match *self {
113 Value::Array(ref mut s) => Some(s),
114 _ => None,
115 }
116 }
117
118 pub fn into_array(self) -> Option<Array> {
120 match self {
121 Value::Array(s) => Some(s),
122 _ => None,
123 }
124 }
125
126 pub fn is_array(&self) -> bool {
128 self.as_array().is_some()
129 }
130
131 pub fn as_object(&self) -> Option<&Object> {
133 match *self {
134 Value::Object(ref s) => Some(s),
135 _ => None,
136 }
137 }
138
139 pub fn as_object_mut(&mut self) -> Option<&mut Object> {
141 match *self {
142 Value::Object(ref mut s) => Some(s),
143 _ => None,
144 }
145 }
146
147 pub fn into_object(self) -> Option<Object> {
149 match self {
150 Value::Object(s) => Some(s),
151 _ => None,
152 }
153 }
154
155 pub fn is_object(&self) -> bool {
157 self.as_object().is_some()
158 }
159
160 pub fn as_nil(&self) -> Option<()> {
162 match *self {
163 Value::Nil => Some(()),
164 _ => None,
165 }
166 }
167
168 pub fn is_nil(&self) -> bool {
170 match *self {
171 Value::Nil => true,
172 _ => false,
173 }
174 }
175
176 pub fn as_empty(&self) -> Option<()> {
178 match *self {
179 Value::Empty => Some(()),
180 _ => None,
181 }
182 }
183
184 pub fn is_empty(&self) -> bool {
186 match *self {
187 Value::Empty => true,
188 _ => false,
189 }
190 }
191
192 pub fn as_blank(&self) -> Option<()> {
194 match *self {
195 Value::Blank => Some(()),
196 _ => None,
197 }
198 }
199
200 pub fn is_blank(&self) -> bool {
202 match *self {
203 Value::Blank => true,
204 _ => false,
205 }
206 }
207
208 pub fn is_truthy(&self) -> bool {
210 match *self {
212 Value::Scalar(ref x) => x.is_truthy(),
213 Value::Nil | Value::Empty | Value::Blank => false,
214 _ => true,
215 }
216 }
217
218 pub fn is_default(&self) -> bool {
220 match *self {
221 Value::Scalar(ref x) => x.is_default(),
222 Value::Nil => true,
223 Value::Empty => true,
224 Value::Blank => true,
225 Value::Array(ref x) => x.is_empty(),
226 Value::Object(ref x) => x.is_empty(),
227 }
228 }
229
230 pub fn type_name(&self) -> &'static str {
232 match *self {
233 Value::Scalar(ref x) => x.type_name(),
234 Value::Nil => "nil",
235 Value::Empty => "empty",
236 Value::Blank => "blank",
237 Value::Array(_) => "array",
238 Value::Object(_) => "object",
239 }
240 }
241
242 pub fn contains_key(&self, index: &Scalar) -> bool {
244 match *self {
245 Value::Array(ref x) => {
246 if let Some(index) = index.to_integer() {
247 let index = convert_index(index, x.len());
248 index < x.len()
249 } else {
250 match &*index.to_str() {
251 "first" | "last" => true,
252 _ => false,
253 }
254 }
255 }
256 Value::Object(ref x) => x.contains_key(index.to_str().as_ref()),
257 _ => false,
258 }
259 }
260
261 pub fn keys(&self) -> Keys {
263 let v = match *self {
264 Value::Array(ref x) => {
265 let start: i32 = 0;
266 let end = x.len() as i32;
267 let mut keys: Vec<_> = (start..end).map(Scalar::new).collect();
268 keys.push(Scalar::new("first"));
269 keys.push(Scalar::new("last"));
270 keys
271 }
272 Value::Object(ref x) => x
273 .keys()
274 .map(|s| match *s {
275 borrow::Cow::Borrowed(s) => Scalar::new(s),
276 borrow::Cow::Owned(ref s) => Scalar::new(s.to_owned()),
277 })
278 .collect(),
279 _ => vec![],
280 };
281 Keys(v.into_iter())
282 }
283
284 pub fn get<'s>(&'s self, index: &ScalarCow<'_>) -> Option<&'s Self> {
286 match *self {
287 Value::Array(ref x) => {
288 if let Some(index) = index.to_integer() {
289 let index = convert_index(index, x.len());
290 x.get(index as usize)
291 } else {
292 match &*index.to_str() {
293 "first" => x.get(0),
294 "last" => x.get(x.len() - 1),
295 _ => None,
296 }
297 }
298 }
299 Value::Object(ref x) => x.get(index.to_str().as_ref()),
300 _ => None,
301 }
302 }
303}
304
305#[derive(Debug)]
307pub struct Keys(::std::vec::IntoIter<Scalar>);
308
309impl Iterator for Keys {
310 type Item = Scalar;
311
312 #[inline]
313 fn next(&mut self) -> Option<Scalar> {
314 self.0.next()
315 }
316
317 #[inline]
318 fn size_hint(&self) -> (usize, Option<usize>) {
319 self.0.size_hint()
320 }
321
322 #[inline]
323 fn count(self) -> usize {
324 self.0.count()
325 }
326}
327
328impl ExactSizeIterator for Keys {
329 #[inline]
330 fn len(&self) -> usize {
331 self.0.len()
332 }
333}
334
335fn convert_index(index: i32, max_size: usize) -> usize {
336 let index = index as isize;
337 let max_size = max_size as isize;
338 let index = if 0 <= index { index } else { max_size + index };
339 index as usize
340}
341
342impl Default for Value {
343 fn default() -> Self {
344 Self::nil()
345 }
346}
347
348impl PartialEq<Value> for Value {
349 fn eq(&self, other: &Self) -> bool {
350 value_eq(self, other)
351 }
352}
353
354impl Eq for Value {}
355
356impl PartialOrd<Value> for Value {
357 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
358 value_cmp(self, other)
359 }
360}
361
362#[derive(Debug)]
364pub struct ValueSource<'s>(&'s Value);
365
366impl<'s> fmt::Display for ValueSource<'s> {
367 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
368 match self.0 {
369 Value::Scalar(ref x) => write!(f, "{}", x.render())?,
370 Value::Array(ref x) => {
371 write!(f, "[")?;
372 for item in x {
373 write!(f, "{}, ", item.render())?;
374 }
375 write!(f, "]")?;
376 }
377 Value::Object(ref x) => {
378 write!(f, "{{")?;
379 for (k, v) in x {
380 write!(f, r#""{}": {}, "#, k, v.render())?;
381 }
382 write!(f, "}}")?;
383 }
384 Value::Nil => write!(f, "nil")?,
385 Value::Empty => write!(f, "empty")?,
386 Value::Blank => write!(f, "blank")?,
387 }
388 Ok(())
389 }
390}
391
392#[derive(Debug)]
394pub struct ValueRendered<'s>(&'s Value);
395
396impl<'s> fmt::Display for ValueRendered<'s> {
397 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
398 match self.0 {
400 Value::Scalar(ref x) => write!(f, "{}", x.render())?,
401 Value::Array(ref x) => {
402 for item in x {
403 write!(f, "{}", item.render())?;
404 }
405 }
406 Value::Object(ref x) => {
407 for (k, v) in x {
408 write!(f, "{}{}", k, v.render())?;
409 }
410 }
411 Value::Nil | Value::Empty | Value::Blank => (),
412 }
413 Ok(())
414 }
415}
416
417fn value_eq(lhs: &Value, rhs: &Value) -> bool {
418 match (lhs, rhs) {
419 (&Value::Scalar(ref x), &Value::Scalar(ref y)) => x == y,
420 (&Value::Array(ref x), &Value::Array(ref y)) => x == y,
421 (&Value::Object(ref x), &Value::Object(ref y)) => x == y,
422 (&Value::Nil, &Value::Nil)
423 | (&Value::Empty, &Value::Empty)
424 | (&Value::Blank, &Value::Blank)
425 | (&Value::Empty, &Value::Blank)
426 | (&Value::Blank, &Value::Empty) => true,
427
428 (&Value::Empty, &Value::Scalar(ref s)) | (&Value::Scalar(ref s), &Value::Empty) => {
431 s.to_str().is_empty()
432 }
433 (&Value::Empty, &Value::Array(ref s)) | (&Value::Array(ref s), &Value::Empty) => {
434 s.is_empty()
435 }
436 (&Value::Empty, &Value::Object(ref s)) | (&Value::Object(ref s), &Value::Empty) => {
437 s.is_empty()
438 }
439
440 (&Value::Nil, &Value::Blank) | (&Value::Blank, &Value::Nil) => true,
443 (&Value::Blank, &Value::Scalar(ref s)) | (&Value::Scalar(ref s), &Value::Blank) => {
444 s.to_str().trim().is_empty() || !s.to_bool().unwrap_or(true)
445 }
446 (&Value::Blank, &Value::Array(ref s)) | (&Value::Array(ref s), &Value::Blank) => {
447 s.is_empty()
448 }
449 (&Value::Blank, &Value::Object(ref s)) | (&Value::Object(ref s), &Value::Blank) => {
450 s.is_empty()
451 }
452
453 (&Value::Nil, &Value::Scalar(ref b)) | (&Value::Scalar(ref b), &Value::Nil) => {
455 !b.to_bool().unwrap_or(true)
456 }
457 (_, &Value::Scalar(ref b)) | (&Value::Scalar(ref b), _) => b.to_bool().unwrap_or(false),
458
459 _ => false,
460 }
461}
462
463fn value_cmp(lhs: &Value, rhs: &Value) -> Option<Ordering> {
464 match (lhs, rhs) {
465 (&Value::Scalar(ref x), &Value::Scalar(ref y)) => x.partial_cmp(y),
466 (&Value::Array(ref x), &Value::Array(ref y)) => x.iter().partial_cmp(y.iter()),
467 (&Value::Object(ref x), &Value::Object(ref y)) => x.iter().partial_cmp(y.iter()),
468 _ => None,
469 }
470}
471
472#[cfg(test)]
473mod test {
474 use super::*;
475
476 #[test]
477 fn test_to_string_scalar() {
478 let val = Value::scalar(42f64);
479 assert_eq!(&val.render().to_string(), "42");
480 assert_eq!(&val.to_str(), "42");
481 }
482
483 #[test]
484 fn test_to_string_array() {
485 let val = Value::Array(vec![
486 Value::scalar(3f64),
487 Value::scalar("test"),
488 Value::scalar(5.3),
489 ]);
490 assert_eq!(&val.render().to_string(), "3test5.3");
491 assert_eq!(&val.to_str(), "3test5.3");
492 }
493
494 #[test]
497 fn test_to_string_nil() {
498 assert_eq!(&Value::nil().render().to_string(), "");
499 assert_eq!(&Value::nil().to_str(), "");
500 }
501
502 #[test]
503 fn scalar_equality() {
504 assert_eq!(Value::scalar("alpha"), Value::scalar("alpha"));
505 assert_eq!(Value::scalar(""), Value::scalar(""));
506 assert!(Value::scalar("alpha") != Value::scalar("beta"));
507 assert!(Value::scalar("beta") != Value::scalar("alpha"));
508 }
509
510 #[test]
511 fn scalars_have_ruby_truthiness() {
512 assert_eq!(Value::scalar(true), Value::scalar("All strings are truthy"));
514 assert_eq!(Value::scalar(true), Value::scalar(""));
515 assert!(Value::scalar("").is_truthy());
516
517 assert_eq!(Value::scalar(true), Value::scalar(true));
518 assert!(Value::scalar(true) != Value::scalar(false));
519 }
520
521 #[test]
522 fn array_equality() {
523 let a = Value::Array(vec![Value::scalar("one"), Value::scalar("two")]);
524 let b = Value::Array(vec![Value::scalar("alpha"), Value::scalar("beta")]);
525
526 assert_eq!(a, a);
527 assert!(a != b);
528 assert!(b != a);
529 }
530
531 #[test]
532 fn arrays_have_ruby_truthiness() {
533 assert_eq!(Value::scalar(true), Value::Array(Vec::new()));
534 assert!(Value::Array(Vec::new()).is_truthy());
535 }
536
537 #[test]
538 fn object_equality() {
539 let a: Object = [
540 ("alpha".into(), Value::scalar("1")),
541 ("beta".into(), Value::scalar(2f64)),
542 ]
543 .iter()
544 .cloned()
545 .collect();
546 let a = Value::Object(a);
547
548 let b: Object = [
549 ("alpha".into(), Value::scalar("1")),
550 ("beta".into(), Value::scalar(2f64)),
551 ("gamma".into(), Value::Array(vec![])),
552 ]
553 .iter()
554 .cloned()
555 .collect();
556 let b = Value::Object(b);
557
558 assert_eq!(a, a);
559 assert!(a != b);
560 assert!(b != a);
561 }
562
563 #[test]
564 fn objects_have_ruby_truthiness() {
565 assert_eq!(Value::scalar(true), Value::Object(Object::new()));
566 assert!(Value::Object(Object::new()).is_truthy());
567 }
568
569 #[test]
570 fn nil_equality() {
571 assert_eq!(Value::Nil, Value::Nil);
572 }
573
574 #[test]
575 fn nils_have_ruby_truthiness() {
576 assert_eq!(Value::scalar(false), Value::Nil);
577 assert!(!Value::Nil.is_truthy());
578
579 assert_eq!(Value::scalar(false), Value::Nil);
580 assert!(Value::scalar(true) != Value::Nil);
581 assert!(Value::scalar("") != Value::Nil);
582 }
583
584 #[test]
585 fn empty_equality() {
586 assert_eq!(Value::Empty, Value::Empty);
588 assert_eq!(Value::Empty, Value::Blank);
589 assert_eq!(Value::Empty, liquid_value!(""));
590 assert_ne!(Value::Empty, liquid_value!(" "));
591 assert_eq!(Value::Empty, liquid_value!([]));
592 assert_ne!(Value::Empty, liquid_value!([nil]));
593 assert_eq!(Value::Empty, liquid_value!({}));
594 assert_ne!(Value::Empty, liquid_value!({ "a": nil }));
595 }
596
597 #[test]
598 fn blank_equality() {
599 assert_eq!(Value::Blank, Value::Blank);
601 assert_eq!(Value::Blank, Value::Empty);
602 assert_eq!(Value::Blank, liquid_value!(nil));
603 assert_eq!(Value::Blank, liquid_value!(false));
604 assert_ne!(Value::Blank, liquid_value!(true));
605 assert_ne!(Value::Blank, liquid_value!(0));
606 assert_ne!(Value::Blank, liquid_value!(1));
607 assert_eq!(Value::Blank, liquid_value!(""));
608 assert_eq!(Value::Blank, liquid_value!(" "));
609 assert_eq!(Value::Blank, liquid_value!([]));
610 assert_ne!(Value::Blank, liquid_value!([nil]));
611 assert_eq!(Value::Blank, liquid_value!({}));
612 assert_ne!(Value::Blank, liquid_value!({ "a": nil }));
613 }
614}