liquid_core/model/array/
mod.rs1use 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
12pub trait ArrayView: ValueView {
14 fn as_value(&self) -> &dyn ValueView;
16
17 fn size(&self) -> i64;
19
20 fn values<'k>(&'k self) -> Box<dyn Iterator<Item = &'k dyn ValueView> + 'k>;
22
23 fn contains_key(&self, index: i64) -> bool;
25 fn get(&self, index: i64) -> Option<&dyn ValueView>;
27 fn first(&self) -> Option<&dyn ValueView> {
29 self.get(0)
30 }
31 fn last(&self) -> Option<&dyn ValueView> {
33 self.get(-1)
34 }
35}
36
37pub 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}