loose_liquid_core/model/value/
values.rs1#![allow(clippy::eq_op)]
2
3use std::cmp::Ordering;
4use std::fmt;
5
6use crate::model::KStringCow;
7
8use super::DisplayCow;
9use super::State;
10use super::{ValueView, ValueViewCmp};
11use crate::model::array::{Array, ArrayView};
12use crate::model::object::{Object, ObjectView};
13use crate::model::scalar::{Scalar, ScalarCow};
14
15#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
17#[serde(untagged)]
18pub enum Value {
19 Scalar(Scalar),
21 Array(Array),
23 Object(Object),
25 State(State),
27 Nil,
29}
30
31impl Value {
32 pub fn scalar<T: Into<Scalar>>(value: T) -> Self {
34 Value::Scalar(ScalarCow::new(value))
35 }
36
37 pub fn array<I: IntoIterator<Item = Value>>(iter: I) -> Value {
39 let v: Array = iter.into_iter().collect();
40 Value::Array(v)
41 }
42
43 pub fn as_view(&self) -> &dyn ValueView {
45 match &self {
46 Value::Scalar(ref x) => x,
47 Value::Object(ref x) => x,
48 Value::Array(ref x) => x,
49 Value::State(ref x) => x,
50 Value::Nil => self,
51 }
52 }
53
54 pub fn into_scalar(self) -> Option<Scalar> {
56 match self {
57 Value::Scalar(s) => Some(s),
58 _ => None,
59 }
60 }
61
62 pub fn into_array(self) -> Option<Array> {
64 match self {
65 Value::Array(s) => Some(s),
66 _ => None,
67 }
68 }
69
70 pub fn as_array_mut(&mut self) -> Option<&mut Array> {
72 match *self {
73 Value::Array(ref mut s) => Some(s),
74 _ => None,
75 }
76 }
77
78 pub fn into_object(self) -> Option<Object> {
80 match self {
81 Value::Object(s) => Some(s),
82 _ => None,
83 }
84 }
85
86 pub fn as_object_mut(&mut self) -> Option<&mut Object> {
88 match *self {
89 Value::Object(ref mut s) => Some(s),
90 _ => None,
91 }
92 }
93
94 pub fn into_state(self) -> Option<State> {
96 match self {
97 Value::State(s) => Some(s),
98 _ => None,
99 }
100 }
101}
102
103impl ValueView for Value {
104 fn as_debug(&self) -> &dyn fmt::Debug {
105 self
106 }
107
108 fn render(&self) -> DisplayCow<'_> {
109 match *self {
110 Value::Scalar(ref x) => x.render(),
111 Value::Array(ref x) => x.render(),
112 Value::Object(ref x) => x.render(),
113 Value::State(ref x) => x.render(),
114 Value::Nil => DisplayCow::Borrowed(&""),
115 }
116 }
117 fn source(&self) -> DisplayCow<'_> {
118 match *self {
119 Value::Scalar(ref x) => x.source(),
120 Value::Array(ref x) => x.source(),
121 Value::Object(ref x) => x.source(),
122 Value::State(ref x) => x.source(),
123 Value::Nil => DisplayCow::Owned(Box::new(super::StrDisplay {
124 s: self.type_name(),
125 })),
126 }
127 }
128 fn type_name(&self) -> &'static str {
129 match *self {
130 Value::Scalar(ref x) => x.type_name(),
131 Value::Array(ref x) => x.type_name(),
132 Value::Object(ref x) => x.type_name(),
133 Value::State(ref x) => x.type_name(),
134 Value::Nil => "nil",
135 }
136 }
137 fn query_state(&self, state: State) -> bool {
138 match *self {
139 Value::Scalar(ref x) => x.query_state(state),
140 Value::Array(ref x) => x.query_state(state),
141 Value::Object(ref x) => x.query_state(state),
142 Value::State(ref x) => x.query_state(state),
143 Value::Nil => match state {
144 State::Truthy => false,
145 State::DefaultValue => true,
146 State::Empty => true,
147 State::Blank => true,
148 },
149 }
150 }
151
152 fn to_kstr(&self) -> KStringCow<'_> {
153 match *self {
154 Value::Scalar(ref x) => x.to_kstr(),
155 Value::Array(ref x) => x.to_kstr(),
156 Value::Object(ref x) => x.to_kstr(),
157 Value::State(ref x) => x.to_kstr(),
158 Value::Nil => KStringCow::from_static(""),
159 }
160 }
161 fn to_value(&self) -> Value {
162 match self {
163 Value::Scalar(ref x) => {
164 let x = x.clone();
165 let x = x.into_owned();
166 Value::Scalar(x)
167 }
168 Value::Array(ref x) => Value::Array(x.clone()),
169 Value::Object(ref x) => Value::Object(x.clone()),
170 Value::State(ref x) => Value::State(*x),
171 Value::Nil => Value::Nil,
172 }
173 }
174
175 fn as_scalar(&self) -> Option<ScalarCow<'_>> {
176 match self {
177 Value::Scalar(s) => Some(s.as_ref()),
178 _ => None,
179 }
180 }
181 fn as_array(&self) -> Option<&dyn ArrayView> {
182 match self {
183 Value::Array(ref s) => Some(s),
184 _ => None,
185 }
186 }
187 fn as_object(&self) -> Option<&dyn ObjectView> {
188 match self {
189 Value::Object(ref s) => Some(s),
190 _ => None,
191 }
192 }
193 fn as_state(&self) -> Option<State> {
194 match self {
195 Value::State(s) => Some(*s),
196 _ => None,
197 }
198 }
199 fn is_nil(&self) -> bool {
200 matches!(self, Value::Nil)
201 }
202}
203
204impl From<Scalar> for Value {
205 fn from(other: Scalar) -> Self {
206 Value::Scalar(other)
207 }
208}
209
210impl From<Array> for Value {
211 fn from(other: Array) -> Self {
212 Value::Array(other)
213 }
214}
215
216impl From<Object> for Value {
217 fn from(other: Object) -> Self {
218 Value::Object(other)
219 }
220}
221
222impl From<State> for Value {
223 fn from(other: State) -> Self {
224 Value::State(other)
225 }
226}
227
228impl Default for Value {
229 fn default() -> Self {
230 Self::Nil
231 }
232}
233
234impl PartialEq<Value> for Value {
235 fn eq(&self, other: &Self) -> bool {
236 super::value_eq(self.as_view(), other.as_view())
237 }
238}
239
240impl<'v> PartialEq<ValueViewCmp<'v>> for Value {
241 fn eq(&self, other: &ValueViewCmp<'v>) -> bool {
242 ValueViewCmp::new(self.as_view()) == *other
243 }
244}
245
246impl PartialEq<i64> for Value {
247 fn eq(&self, other: &i64) -> bool {
248 super::value_eq(self.as_view(), other)
249 }
250}
251
252impl PartialEq<f64> for Value {
253 fn eq(&self, other: &f64) -> bool {
254 super::value_eq(self.as_view(), other)
255 }
256}
257
258impl PartialEq<bool> for Value {
259 fn eq(&self, other: &bool) -> bool {
260 super::value_eq(self.as_view(), other)
261 }
262}
263
264impl PartialEq<crate::model::scalar::DateTime> for Value {
265 fn eq(&self, other: &crate::model::scalar::DateTime) -> bool {
266 super::value_eq(self.as_view(), other)
267 }
268}
269
270impl PartialEq<crate::model::scalar::Date> for Value {
271 fn eq(&self, other: &crate::model::scalar::Date) -> bool {
272 super::value_eq(self.as_view(), other)
273 }
274}
275
276impl PartialEq<str> for Value {
277 fn eq(&self, other: &str) -> bool {
278 let other = KStringCow::from_ref(other);
279 super::value_eq(self.as_view(), &other)
280 }
281}
282
283impl<'s> PartialEq<&'s str> for Value {
284 fn eq(&self, other: &&str) -> bool {
285 super::value_eq(self.as_view(), other)
286 }
287}
288
289impl PartialEq<String> for Value {
290 fn eq(&self, other: &String) -> bool {
291 super::value_eq(self.as_view(), other)
292 }
293}
294
295impl PartialEq<crate::model::KString> for Value {
296 fn eq(&self, other: &crate::model::KString) -> bool {
297 super::value_eq(self.as_view(), &other.as_ref())
298 }
299}
300
301impl<'s> PartialEq<crate::model::KStringRef<'s>> for Value {
302 fn eq(&self, other: &crate::model::KStringRef<'s>) -> bool {
303 super::value_eq(self.as_view(), other)
304 }
305}
306
307impl<'s> PartialEq<crate::model::KStringCow<'s>> for Value {
308 fn eq(&self, other: &crate::model::KStringCow<'s>) -> bool {
309 super::value_eq(self.as_view(), other)
310 }
311}
312
313impl Eq for Value {}
314
315impl PartialOrd<Value> for Value {
316 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
317 super::value_cmp(self.as_view(), other)
318 }
319}
320
321#[cfg(test)]
322mod test {
323 use super::*;
324
325 #[test]
326 fn test_to_string_scalar() {
327 let val = Value::scalar(42f64);
328 assert_eq!(&val.render().to_string(), "42");
329 assert_eq!(&val.to_kstr(), "42");
330 }
331
332 #[test]
333 fn test_to_string_array() {
334 let val = Value::Array(vec![
335 Value::scalar(3f64),
336 Value::scalar("test"),
337 Value::scalar(5.3),
338 ]);
339 assert_eq!(&val.render().to_string(), "3test5.3");
340 assert_eq!(&val.to_kstr(), "3test5.3");
341 }
342
343 #[test]
346 fn test_to_string_nil() {
347 assert_eq!(&Value::Nil.render().to_string(), "");
348 assert_eq!(&Value::Nil.to_kstr(), "");
349 }
350
351 #[test]
352 fn scalar_equality() {
353 assert_eq!(Value::scalar("alpha"), Value::scalar("alpha"));
354 assert_eq!(Value::scalar(""), Value::scalar(""));
355 assert!(Value::scalar("alpha") != Value::scalar("beta"));
356 assert!(Value::scalar("beta") != Value::scalar("alpha"));
357 }
358
359 #[test]
360 fn scalars_have_ruby_truthiness() {
361 assert_eq!(Value::scalar(true), Value::scalar("All strings are truthy"));
363 assert_eq!(Value::scalar(true), Value::scalar(""));
364 assert!(Value::scalar("").query_state(State::Truthy));
365
366 assert_eq!(Value::scalar(true), Value::scalar(true));
367 assert!(Value::scalar(true) != Value::scalar(false));
368 }
369
370 #[test]
371 fn array_equality() {
372 let a = Value::Array(vec![Value::scalar("one"), Value::scalar("two")]);
373 let b = Value::Array(vec![Value::scalar("alpha"), Value::scalar("beta")]);
374
375 assert_eq!(a, a);
376 assert!(a != b);
377 assert!(b != a);
378 }
379
380 #[test]
381 fn arrays_have_ruby_truthiness() {
382 assert_eq!(Value::scalar(true), Value::Array(Vec::new()));
383 assert!(Value::Array(Vec::new()).query_state(State::Truthy));
384 }
385
386 #[test]
387 fn object_equality() {
388 let a: Object = [
389 ("alpha".into(), Value::scalar("1")),
390 ("beta".into(), Value::scalar(2f64)),
391 ]
392 .iter()
393 .cloned()
394 .collect();
395 let a = Value::Object(a);
396
397 let b: Object = [
398 ("alpha".into(), Value::scalar("1")),
399 ("beta".into(), Value::scalar(2f64)),
400 ("gamma".into(), Value::Array(vec![])),
401 ]
402 .iter()
403 .cloned()
404 .collect();
405 let b = Value::Object(b);
406
407 assert_eq!(a, a);
408 assert!(a != b);
409 assert!(b != a);
410 }
411
412 #[test]
413 fn objects_have_ruby_truthiness() {
414 assert_eq!(Value::scalar(true), Value::Object(Object::new()));
415 assert!(Value::Object(Object::new()).query_state(State::Truthy));
416 }
417
418 #[test]
419 fn nil_equality() {
420 assert_eq!(Value::Nil, Value::Nil);
421 }
422
423 #[test]
424 fn nils_have_ruby_truthiness() {
425 assert_eq!(Value::scalar(false), Value::Nil);
426 assert!(!Value::Nil.query_state(State::Truthy));
427
428 assert_eq!(Value::scalar(false), Value::Nil);
429 assert!(Value::scalar(true) != Value::Nil);
430 assert!(Value::scalar("") != Value::Nil);
431 }
432
433 #[test]
434 fn empty_equality() {
435 let blank = Value::State(State::Blank);
436 let empty = Value::State(State::Empty);
437 assert_eq!(empty, empty);
439 assert_eq!(empty, blank);
440 assert_eq!(empty, value!(""));
441 assert_ne!(empty, value!(" "));
442 assert_eq!(empty, value!([]));
443 assert_ne!(empty, value!([nil]));
444 assert_eq!(empty, value!({}));
445 assert_ne!(empty, value!({ "a": nil }));
446 }
447
448 #[test]
449 fn blank_equality() {
450 let blank = Value::State(State::Blank);
451 let empty = Value::State(State::Empty);
452 assert_eq!(blank, blank);
454 assert_eq!(blank, empty);
455 assert_eq!(blank, value!(nil));
456 assert_eq!(blank, value!(false));
457 assert_ne!(blank, value!(true));
458 assert_ne!(blank, value!(0));
459 assert_ne!(blank, value!(1));
460 assert_eq!(blank, value!(""));
461 assert_eq!(blank, value!(" "));
462 assert_eq!(blank, value!([]));
463 assert_ne!(blank, value!([nil]));
464 assert_eq!(blank, value!({}));
465 assert_ne!(blank, value!({ "a": nil }));
466 }
467}