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