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}