partiql_value/
bag.rs

1use itertools::Itertools;
2
3use std::cmp::Ordering;
4
5use std::collections::HashSet;
6use std::fmt::{Debug, Formatter};
7use std::hash::{Hash, Hasher};
8
9use std::{slice, vec};
10
11use crate::sort::NullSortedValue;
12use crate::{EqualityValue, List, NullableEq, Value};
13#[cfg(feature = "serde")]
14use serde::{Deserialize, Serialize};
15
16#[derive(Default, Eq, Clone)]
17#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
18/// Represents a `PartiQL` BAG value, e.g.: <<1, 'two', 4>>
19pub struct Bag(Vec<Value>);
20
21impl Bag {
22    #[inline]
23    pub fn push(&mut self, value: Value) {
24        self.0.push(value);
25    }
26
27    #[inline]
28    #[must_use]
29    pub fn len(&self) -> usize {
30        self.0.len()
31    }
32
33    #[inline]
34    #[must_use]
35    pub fn is_empty(&self) -> bool {
36        self.len() == 0
37    }
38
39    #[inline]
40    #[must_use]
41    pub fn iter(&self) -> BagIter<'_> {
42        BagIter(self.0.iter())
43    }
44
45    #[inline]
46    pub fn reserve(&mut self, additional: usize) {
47        self.0.reserve(additional);
48    }
49
50    #[inline]
51    #[must_use]
52    pub fn to_vec(self) -> Vec<Value> {
53        self.0
54    }
55}
56
57impl Extend<Value> for Bag {
58    #[inline]
59    fn extend<Iter: IntoIterator<Item = Value>>(&mut self, iter: Iter) {
60        let iterator = iter.into_iter();
61        let (lower_bound, _) = iterator.size_hint();
62        self.reserve(lower_bound);
63        iterator.for_each(move |v| self.push(v));
64    }
65}
66
67impl From<Vec<Value>> for Bag {
68    #[inline]
69    fn from(values: Vec<Value>) -> Self {
70        Bag(values)
71    }
72}
73
74impl From<HashSet<Value>> for Bag {
75    #[inline]
76    fn from(values: HashSet<Value>) -> Self {
77        Bag(values.into_iter().collect())
78    }
79}
80
81impl From<List> for Bag {
82    #[inline]
83    fn from(list: List) -> Self {
84        Bag(list.to_vec())
85    }
86}
87
88impl<T> FromIterator<T> for Bag
89where
90    T: Into<Value>,
91{
92    #[inline]
93    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Bag {
94        let iterator = iter.into_iter().map(Into::into);
95        iterator.collect::<Vec<_>>().into()
96    }
97}
98
99#[macro_export]
100macro_rules! bag {
101    () => (
102        $crate::Bag::from(vec![])
103    );
104    ($elem:expr; $n:expr) => (
105        $crate::Bag::from(vec![Value::from($elem); $n])
106    );
107    ($($x:expr),+ $(,)?) => (
108        $crate::Bag::from(vec![$(Value::from($x)),+])
109    );
110}
111
112impl<'a> IntoIterator for &'a Bag {
113    type Item = &'a Value;
114    type IntoIter = BagIter<'a>;
115
116    #[inline]
117    fn into_iter(self) -> Self::IntoIter {
118        BagIter(self.0.iter())
119    }
120}
121
122#[derive(Debug, Clone)]
123pub struct BagIter<'a>(slice::Iter<'a, Value>);
124
125impl<'a> Iterator for BagIter<'a> {
126    type Item = &'a Value;
127
128    #[inline]
129    fn next(&mut self) -> Option<Self::Item> {
130        self.0.next()
131    }
132
133    #[inline]
134    fn size_hint(&self) -> (usize, Option<usize>) {
135        self.0.size_hint()
136    }
137}
138
139impl IntoIterator for Bag {
140    type Item = Value;
141    type IntoIter = BagIntoIterator;
142
143    fn into_iter(self) -> BagIntoIterator {
144        BagIntoIterator(self.0.into_iter())
145    }
146}
147
148pub struct BagIntoIterator(vec::IntoIter<Value>);
149
150impl Iterator for BagIntoIterator {
151    type Item = Value;
152
153    #[inline]
154    fn next(&mut self) -> Option<Self::Item> {
155        self.0.next()
156    }
157
158    #[inline]
159    fn size_hint(&self) -> (usize, Option<usize>) {
160        self.0.size_hint()
161    }
162}
163
164impl Debug for Bag {
165    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
166        write!(f, "<<")?;
167        let mut iter = self.iter().peekable();
168        while let Some(v) = iter.next() {
169            if iter.peek().is_some() {
170                write!(f, "{v:?}, ")?;
171            } else {
172                write!(f, "{v:?}")?;
173            }
174        }
175        write!(f, ">>")
176    }
177}
178
179impl PartialEq for Bag {
180    fn eq(&self, other: &Self) -> bool {
181        let wrap = EqualityValue::<true, false, _>;
182        NullableEq::eq(&wrap(self), &wrap(other)) == Value::Boolean(true)
183    }
184}
185
186impl<const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq
187    for EqualityValue<'_, NULLS_EQUAL, NAN_EQUAL, Bag>
188{
189    #[inline(always)]
190    fn eq(&self, other: &Self) -> Value {
191        let ord_wrap = NullSortedValue::<'_, false, _>;
192        let (l, r) = (self.0, other.0);
193        if l.len() != r.len() {
194            return Value::Boolean(false);
195        }
196
197        let li = l.iter().map(ord_wrap).sorted().map(|nsv| nsv.0);
198        let ri = r.iter().map(ord_wrap).sorted().map(|nsv| nsv.0);
199
200        for (v1, v2) in li.zip(ri) {
201            let wrap = EqualityValue::<{ NULLS_EQUAL }, { NAN_EQUAL }, Value>;
202            if NullableEq::eqg(&wrap(v1), &wrap(v2)) != Value::Boolean(true) {
203                return Value::Boolean(false);
204            }
205        }
206        Value::Boolean(true)
207    }
208
209    #[inline(always)]
210    fn eqg(&self, rhs: &Self) -> Value {
211        let wrap = EqualityValue::<'_, true, { NAN_EQUAL }, _>;
212        NullableEq::eq(&wrap(self.0), &wrap(rhs.0))
213    }
214}
215
216impl PartialOrd for Bag {
217    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
218        Some(self.cmp(other))
219    }
220}
221
222impl<const NULLS_FIRST: bool> Ord for NullSortedValue<'_, NULLS_FIRST, Bag> {
223    fn cmp(&self, other: &Self) -> Ordering {
224        let wrap = NullSortedValue::<{ NULLS_FIRST }, List>;
225
226        let mut l = self.0.clone();
227        l.0.sort();
228        let mut r = other.0.clone();
229        r.0.sort();
230        wrap(&List::from(l)).cmp(&wrap(&List::from(r)))
231    }
232}
233
234impl Ord for Bag {
235    fn cmp(&self, other: &Self) -> Ordering {
236        let mut l = self.0.clone();
237        l.sort();
238        let mut r = other.0.clone();
239        r.sort();
240        List::from(l).cmp(&List::from(r))
241    }
242}
243
244impl Hash for Bag {
245    fn hash<H: Hasher>(&self, state: &mut H) {
246        for v in self.0.iter().sorted() {
247            v.hash(state);
248        }
249    }
250}