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