Skip to main content

teaql_core/
list.rs

1use std::collections::BTreeMap;
2use std::hash::Hash;
3use std::ops::{Index, IndexMut};
4
5use crate::{Entity, IdentifiableEntity, Record, Value, VersionedEntity};
6
7#[derive(Debug, Clone, PartialEq)]
8pub struct SmartList<T> {
9    pub data: Vec<T>,
10    pub total_count: Option<u64>,
11    pub aggregations: Record,
12    pub summary: Record,
13    pub facets: BTreeMap<String, SmartList<Record>>,
14}
15
16impl<T> SmartList<T> {
17    pub fn empty() -> Self {
18        Self::new(Vec::new())
19    }
20
21    pub fn new(data: Vec<T>) -> Self {
22        Self {
23            data,
24            total_count: None,
25            aggregations: Record::new(),
26            summary: Record::new(),
27            facets: BTreeMap::new(),
28        }
29    }
30
31    pub fn with_total_count(mut self, total_count: u64) -> Self {
32        self.total_count = Some(total_count);
33        self
34    }
35
36    pub fn with_aggregation(mut self, key: impl Into<String>, value: impl Into<Value>) -> Self {
37        self.aggregations.insert(key.into(), value.into());
38        self
39    }
40
41    pub fn with_summary(mut self, key: impl Into<String>, value: impl Into<Value>) -> Self {
42        self.summary.insert(key.into(), value.into());
43        self
44    }
45
46    pub fn with_facet(mut self, key: impl Into<String>, facet: SmartList<Record>) -> Self {
47        self.facets.insert(key.into(), facet);
48        self
49    }
50
51    pub fn add_facet(&mut self, key: impl Into<String>, facet: SmartList<Record>) {
52        self.facets.insert(key.into(), facet);
53    }
54
55    pub fn push(&mut self, value: T) {
56        self.data.push(value);
57    }
58
59    pub fn extend(&mut self, values: impl IntoIterator<Item = T>) {
60        self.data.extend(values);
61    }
62
63    pub fn set(&mut self, index: usize, value: T) -> Option<T> {
64        if index >= self.data.len() {
65            return None;
66        }
67        Some(std::mem::replace(&mut self.data[index], value))
68    }
69
70    pub fn get(&self, index: usize) -> Option<&T> {
71        self.data.get(index)
72    }
73
74    pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
75        self.data.get_mut(index)
76    }
77
78    pub fn last(&self) -> Option<&T> {
79        self.data.last()
80    }
81
82    pub fn len(&self) -> usize {
83        self.data.len()
84    }
85
86    pub fn is_empty(&self) -> bool {
87        self.data.is_empty()
88    }
89
90    pub fn first(&self) -> Option<&T> {
91        self.data.first()
92    }
93
94    pub fn iter(&self) -> std::slice::Iter<'_, T> {
95        self.data.iter()
96    }
97
98    pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
99        self.data.iter_mut()
100    }
101
102    pub fn as_slice(&self) -> &[T] {
103        &self.data
104    }
105
106    pub fn as_mut_slice(&mut self) -> &mut [T] {
107        &mut self.data
108    }
109
110    pub fn retain(&mut self, filter: impl FnMut(&T) -> bool) {
111        self.data.retain(filter);
112    }
113
114    pub fn total_count_or_len(&self) -> u64 {
115        self.total_count.unwrap_or(self.data.len() as u64)
116    }
117
118    pub fn aggregation(&self, key: &str) -> Option<&Value> {
119        self.aggregations.get(key)
120    }
121
122    pub fn summary(&self, key: &str) -> Option<&Value> {
123        self.summary.get(key)
124    }
125
126    pub fn aggregation_json(&self) -> serde_json::Value {
127        crate::record_to_json_value(&self.aggregations)
128    }
129
130    pub fn summary_json(&self) -> serde_json::Value {
131        crate::record_to_json_value(&self.summary)
132    }
133
134    pub fn into_vec(self) -> Vec<T> {
135        self.data
136    }
137
138    pub fn map<U>(self, mapper: impl FnMut(T) -> U) -> SmartList<U> {
139        SmartList {
140            data: self.data.into_iter().map(mapper).collect(),
141            total_count: self.total_count,
142            aggregations: self.aggregations,
143            summary: self.summary,
144            facets: self.facets,
145        }
146    }
147
148    pub fn to_list<U>(&self, mapper: impl FnMut(&T) -> U) -> Vec<U> {
149        self.data.iter().map(mapper).collect()
150    }
151
152    pub fn to_set<U>(&self, mapper: impl FnMut(&T) -> U) -> std::collections::BTreeSet<U>
153    where
154        U: Ord,
155    {
156        self.data.iter().map(mapper).collect()
157    }
158
159    pub fn identity_map<K>(&self, mut key: impl FnMut(&T) -> K) -> BTreeMap<K, T>
160    where
161        K: Ord,
162        T: Clone,
163    {
164        self.data
165            .iter()
166            .map(|item| (key(item), item.clone()))
167            .collect()
168    }
169
170    pub fn group_by<K>(&self, mut key: impl FnMut(&T) -> K) -> BTreeMap<K, Vec<T>>
171    where
172        K: Ord,
173        T: Clone,
174    {
175        let mut groups = BTreeMap::new();
176        for item in &self.data {
177            groups
178                .entry(key(item))
179                .or_insert_with(Vec::new)
180                .push(item.clone());
181        }
182        groups
183    }
184
185    pub fn merge_by<K>(
186        &mut self,
187        incoming: impl IntoIterator<Item = T>,
188        mut key: impl FnMut(&T) -> K,
189    ) where
190        K: Eq + Hash,
191    {
192        let mut positions = self
193            .data
194            .iter()
195            .enumerate()
196            .map(|(index, item)| (key(item), index))
197            .collect::<std::collections::HashMap<_, _>>();
198        for item in incoming {
199            let item_key = key(&item);
200            if let Some(index) = positions.get(&item_key).copied() {
201                self.data[index] = item;
202            } else {
203                positions.insert(item_key, self.data.len());
204                self.data.push(item);
205            }
206        }
207    }
208
209    pub fn into_records(self) -> SmartList<Record>
210    where
211        T: Entity,
212    {
213        SmartList {
214            data: self.data.into_iter().map(Entity::into_record).collect(),
215            total_count: self.total_count,
216            aggregations: self.aggregations,
217            summary: self.summary,
218            facets: self.facets,
219        }
220    }
221}
222
223impl<T> SmartList<T>
224where
225    T: IdentifiableEntity,
226{
227    pub fn ids(&self) -> Vec<Value> {
228        self.data.iter().map(IdentifiableEntity::id_value).collect()
229    }
230
231    pub fn map_by_id(&self) -> BTreeMap<String, T>
232    where
233        T: Clone,
234    {
235        self.data
236            .iter()
237            .map(|item| (id_key(&item.id_value()), item.clone()))
238            .collect()
239    }
240}
241
242impl<T> SmartList<T>
243where
244    T: VersionedEntity,
245{
246    pub fn versions(&self) -> Vec<i64> {
247        self.data.iter().map(VersionedEntity::version).collect()
248    }
249}
250
251impl<T> From<Vec<T>> for SmartList<T> {
252    fn from(data: Vec<T>) -> Self {
253        Self::new(data)
254    }
255}
256
257impl<T> Default for SmartList<T> {
258    fn default() -> Self {
259        Self::new(Vec::new())
260    }
261}
262
263impl<T> IntoIterator for SmartList<T> {
264    type Item = T;
265    type IntoIter = std::vec::IntoIter<T>;
266
267    fn into_iter(self) -> Self::IntoIter {
268        self.data.into_iter()
269    }
270}
271
272impl<'a, T> IntoIterator for &'a SmartList<T> {
273    type Item = &'a T;
274    type IntoIter = std::slice::Iter<'a, T>;
275
276    fn into_iter(self) -> Self::IntoIter {
277        self.data.iter()
278    }
279}
280
281impl<'a, T> IntoIterator for &'a mut SmartList<T> {
282    type Item = &'a mut T;
283    type IntoIter = std::slice::IterMut<'a, T>;
284
285    fn into_iter(self) -> Self::IntoIter {
286        self.data.iter_mut()
287    }
288}
289
290impl<T> FromIterator<T> for SmartList<T> {
291    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
292        Self::new(iter.into_iter().collect())
293    }
294}
295
296impl<T> Extend<T> for SmartList<T> {
297    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
298        self.data.extend(iter);
299    }
300}
301
302impl<T> Index<usize> for SmartList<T> {
303    type Output = T;
304
305    fn index(&self, index: usize) -> &Self::Output {
306        &self.data[index]
307    }
308}
309
310impl<T> IndexMut<usize> for SmartList<T> {
311    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
312        &mut self.data[index]
313    }
314}
315
316fn id_key(value: &Value) -> String {
317    match value {
318        Value::Null => "null".to_owned(),
319        Value::Bool(value) => format!("b:{value}"),
320        Value::I64(value) => format!("i:{value}"),
321        Value::U64(value) => format!("u:{value}"),
322        Value::F64(value) => format!("f:{value}"),
323        Value::Decimal(value) => format!("d:{value}"),
324        Value::Text(value) => format!("t:{value}"),
325        Value::Json(value) => format!("j:{value}"),
326        Value::Date(value) => format!("d:{value}"),
327        Value::Timestamp(value) => format!("ts:{}", value.to_rfc3339()),
328        Value::Object(_) => "object".to_owned(),
329        Value::List(_) => "list".to_owned(),
330    }
331}