liquid_core/model/array/
mod.rs

1//! Type representing a Liquid array, payload of the `Value::Array` variant
2
3use std::fmt;
4
5use crate::model::KStringCow;
6
7use crate::model::value::DisplayCow;
8use crate::model::State;
9use crate::model::Value;
10use crate::model::ValueView;
11
12/// Accessor for arrays.
13pub trait ArrayView: ValueView {
14    /// Cast to ValueView
15    fn as_value(&self) -> &dyn ValueView;
16
17    /// Returns the number of elements.
18    fn size(&self) -> i64;
19
20    /// Returns an iterator .
21    fn values<'k>(&'k self) -> Box<dyn Iterator<Item = &'k dyn ValueView> + 'k>;
22
23    /// Access a contained `Value`.
24    fn contains_key(&self, index: i64) -> bool;
25    /// Access a contained `Value`.
26    fn get(&self, index: i64) -> Option<&dyn ValueView>;
27    /// Returns the first element.
28    fn first(&self) -> Option<&dyn ValueView> {
29        self.get(0)
30    }
31    /// Returns the last element.
32    fn last(&self) -> Option<&dyn ValueView> {
33        self.get(-1)
34    }
35}
36
37/// Type representing a Liquid array, payload of the `Value::Array` variant
38pub type Array = Vec<Value>;
39
40impl<T: ValueView> ValueView for Vec<T> {
41    fn as_debug(&self) -> &dyn fmt::Debug {
42        self
43    }
44
45    fn render(&self) -> DisplayCow<'_> {
46        DisplayCow::Owned(Box::new(ArrayRender { s: self }))
47    }
48    fn source(&self) -> DisplayCow<'_> {
49        DisplayCow::Owned(Box::new(ArraySource { s: self }))
50    }
51    fn type_name(&self) -> &'static str {
52        "array"
53    }
54    fn query_state(&self, state: State) -> bool {
55        match state {
56            State::Truthy => true,
57            State::DefaultValue | State::Empty | State::Blank => self.is_empty(),
58        }
59    }
60
61    fn to_kstr(&self) -> KStringCow<'_> {
62        let s = ArrayRender { s: self }.to_string();
63        KStringCow::from_string(s)
64    }
65    fn to_value(&self) -> Value {
66        let a = self.iter().map(|v| v.to_value()).collect();
67        Value::Array(a)
68    }
69
70    fn as_array(&self) -> Option<&dyn ArrayView> {
71        Some(self)
72    }
73}
74
75impl<T: ValueView> ArrayView for Vec<T> {
76    fn as_value(&self) -> &dyn ValueView {
77        self
78    }
79
80    fn size(&self) -> i64 {
81        self.len() as i64
82    }
83
84    fn values<'k>(&'k self) -> Box<dyn Iterator<Item = &'k dyn ValueView> + 'k> {
85        let i = self.as_slice().iter().map(|v| convert_value(v));
86        Box::new(i)
87    }
88
89    fn contains_key(&self, index: i64) -> bool {
90        let index = convert_index(index, self.size());
91        index < self.size()
92    }
93
94    fn get(&self, index: i64) -> Option<&dyn ValueView> {
95        let index = convert_index(index, self.size());
96        let value = self.as_slice().get(index as usize);
97        value.map(|v| convert_value(v))
98    }
99}
100
101impl<A: ArrayView + ?Sized> ArrayView for &A {
102    fn as_value(&self) -> &dyn ValueView {
103        <A as ArrayView>::as_value(self)
104    }
105
106    fn size(&self) -> i64 {
107        <A as ArrayView>::size(self)
108    }
109
110    fn values<'k>(&'k self) -> Box<dyn Iterator<Item = &'k dyn ValueView> + 'k> {
111        <A as ArrayView>::values(self)
112    }
113
114    fn contains_key(&self, index: i64) -> bool {
115        <A as ArrayView>::contains_key(self, index)
116    }
117
118    fn get(&self, index: i64) -> Option<&dyn ValueView> {
119        <A as ArrayView>::get(self, index)
120    }
121}
122
123fn convert_value(s: &dyn ValueView) -> &dyn ValueView {
124    s
125}
126
127fn convert_index(index: i64, max_size: i64) -> i64 {
128    if 0 <= index {
129        index
130    } else {
131        max_size + index
132    }
133}
134
135struct ArraySource<'s, T: ValueView> {
136    s: &'s Vec<T>,
137}
138
139impl<T: ValueView> fmt::Display for ArraySource<'_, T> {
140    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141        write!(f, "[")?;
142        for item in self.s {
143            write!(f, "{}, ", item.render())?;
144        }
145        write!(f, "]")?;
146        Ok(())
147    }
148}
149
150struct ArrayRender<'s, T: ValueView> {
151    s: &'s Vec<T>,
152}
153
154impl<T: ValueView> fmt::Display for ArrayRender<'_, T> {
155    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156        for item in self.s {
157            write!(f, "{}", item.render())?;
158        }
159        Ok(())
160    }
161}
162
163#[cfg(test)]
164mod test {
165    use super::*;
166
167    #[test]
168    fn test_array() {
169        let arr = Array::new();
170        println!("{}", arr.source());
171        let array: &dyn ArrayView = &arr;
172        println!("{}", array.source());
173        let view: &dyn ValueView = array.as_value();
174        println!("{}", view.source());
175    }
176}