surrealdb_expr/val/
set.rs1use revision::revisioned;
2use storekey::{BorrowDecode, Encode};
3use surrealdb_collections::{VecSet, VecSetIntoIter};
4use surrealdb_types::{SqlFormat, ToSql, write_sql};
5
6use crate::expr::Expr;
7use crate::val::{IndexFormat, Value};
8
9#[revisioned(revision(1), revision(2, optimised))]
19#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Hash, Encode, BorrowDecode)]
20#[storekey(format = "()")]
21#[storekey(format = "IndexFormat")]
22pub struct Set(#[revision(indexed_set)] pub VecSet<Value>);
23
24impl Set {
25 pub fn new() -> Self {
27 Set(VecSet::new())
28 }
29
30 pub fn len(&self) -> usize {
32 self.0.len()
33 }
34
35 pub fn is_empty(&self) -> bool {
37 self.0.is_empty()
38 }
39
40 pub fn first(&self) -> Option<&Value> {
42 self.0.first()
43 }
44
45 pub fn last(&self) -> Option<&Value> {
47 self.0.last()
48 }
49
50 pub fn nth(&self, index: usize) -> Option<&Value> {
52 self.0.iter().nth(index)
53 }
54
55 pub fn first_mut(&mut self) -> Option<&mut Value> {
57 self.0.first_mut()
58 }
59
60 pub fn last_mut(&mut self) -> Option<&mut Value> {
62 self.0.last_mut()
63 }
64
65 pub fn nth_mut(&mut self, index: usize) -> Option<&mut Value> {
67 self.0.get_mut(index)
68 }
69
70 pub fn iter(&self) -> impl Iterator<Item = &Value> {
72 self.0.iter()
73 }
74
75 pub fn insert(&mut self, value: Value) -> bool {
78 self.0.insert(value)
79 }
80
81 pub fn contains(&self, value: &Value) -> bool {
83 self.0.contains(value)
84 }
85
86 pub fn remove(&mut self, value: &Value) -> bool {
89 self.0.remove(value)
90 }
91
92 pub fn into_literal(self) -> Vec<Expr> {
94 self.0.into_iter().map(Value::into_literal).collect()
95 }
96
97 pub fn union(&self, other: &Set) -> Set {
99 Set(self.0.union(&other.0))
100 }
101
102 pub fn intersection(&self, other: &Set) -> Set {
104 Set(self.0.intersection(&other.0))
105 }
106
107 pub fn symmetric_difference(&self, other: &Set) -> Set {
109 Set(self.0.symmetric_difference(&other.0))
110 }
111
112 pub fn complement(&self, other: &Set) -> Set {
114 Set(self.0.difference(&other.0))
115 }
116
117 pub fn normalize(self) -> Self {
122 Set::from(Vec::from(self))
123 }
124
125 pub fn flatten(self) -> Set {
127 let mut out = Set::new();
128 for v in self {
129 match v {
130 Value::Array(arr) => {
131 for item in arr.0 {
132 out.insert(item);
133 }
134 }
135 Value::Set(set) => {
136 for item in set.0 {
137 out.insert(item);
138 }
139 }
140 _ => {
141 out.insert(v);
142 }
143 }
144 }
145 out
146 }
147}
148
149impl<T> From<Vec<T>> for Set
150where
151 Value: From<T>,
152{
153 fn from(v: Vec<T>) -> Self {
154 Set(v.into_iter().map(Value::from).collect())
155 }
156}
157
158impl From<std::collections::BTreeSet<Value>> for Set {
159 fn from(set: std::collections::BTreeSet<Value>) -> Self {
160 Set(set.into())
161 }
162}
163
164impl From<VecSet<Value>> for Set {
165 fn from(set: VecSet<Value>) -> Self {
166 Set(set)
167 }
168}
169
170impl From<Set> for Vec<Value> {
171 fn from(s: Set) -> Self {
172 s.0.into_iter().collect()
173 }
174}
175
176impl TryFrom<Set> for surrealdb_types::Set {
177 type Error = anyhow::Error;
178
179 fn try_from(s: Set) -> Result<Self, Self::Error> {
180 Ok(surrealdb_types::Set::from(
181 s.0.into_iter().map(surrealdb_types::Value::try_from).collect::<Result<Vec<_>, _>>()?,
182 ))
183 }
184}
185
186impl From<surrealdb_types::Set> for Set {
187 fn from(s: surrealdb_types::Set) -> Self {
188 Set(s.into_iter().map(Value::from).collect())
189 }
190}
191
192impl FromIterator<Value> for Set {
193 fn from_iter<I: IntoIterator<Item = Value>>(iter: I) -> Self {
194 Set(iter.into_iter().collect())
195 }
196}
197
198impl IntoIterator for Set {
199 type Item = Value;
200 type IntoIter = VecSetIntoIter<Value>;
201 fn into_iter(self) -> Self::IntoIter {
202 self.0.into_iter()
203 }
204}
205
206impl ToSql for Set {
207 fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
208 if self.is_empty() {
209 return f.push_str("{,}");
210 }
211
212 f.push('{');
214 let len = self.len();
215 for (i, v) in self.iter().enumerate() {
216 write_sql!(f, sql_fmt, "{}", v);
217 if len == 1 {
220 f.push(',');
221 } else if i < len - 1 {
222 f.push_str(", ");
223 }
224 }
225 f.push('}');
226 }
227}