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
346fn id_key(value: &Value) -> String {
347 match value {
348 Value::Null => "null".to_owned(),
349 Value::Bool(value) => format!("b:{value}"),
350 Value::I64(value) => format!("i:{value}"),
351 Value::U64(value) => format!("u:{value}"),
352 Value::F64(value) => format!("f:{value}"),
353 Value::Decimal(value) => format!("d:{value}"),
354 Value::Text(value) => format!("t:{value}"),
355 Value::Json(value) => format!("j:{value}"),
356 Value::Date(value) => format!("d:{value}"),
357 Value::Timestamp(value) => format!("ts:{}", value.to_rfc3339()),
358 Value::Object(_) => "object".to_owned(),
359 Value::List(_) => "list".to_owned(),
360 }
361}