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