Skip to main content

surrealdb_types/value/
set.rs

1use std::collections::BTreeSet;
2use std::ops::{Deref, DerefMut};
3
4use serde::{Deserialize, Serialize};
5
6use crate::Value;
7use crate::sql::{SqlFormat, ToSql};
8
9/// A set of unique values in SurrealDB
10///
11/// Sets are collections that maintain uniqueness and ordering of elements.
12/// The underlying storage is a `BTreeSet<Value>` which provides automatic
13/// deduplication and sorted iteration based on `Value`'s `Ord` implementation.
14#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
15#[serde(transparent)]
16#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
17pub struct Set(pub(crate) BTreeSet<Value>);
18
19impl Set {
20	/// Create a new empty set
21	pub fn new() -> Self {
22		Self(BTreeSet::new())
23	}
24
25	/// Convert into the inner `BTreeSet<Value>`
26	pub fn into_inner(self) -> BTreeSet<Value> {
27		self.0
28	}
29}
30
31impl From<Vec<Value>> for Set {
32	fn from(vec: Vec<Value>) -> Self {
33		Self(vec.into_iter().collect())
34	}
35}
36
37impl From<BTreeSet<Value>> for Set {
38	fn from(set: BTreeSet<Value>) -> Self {
39		Self(set)
40	}
41}
42
43impl From<Set> for Vec<Value> {
44	fn from(set: Set) -> Self {
45		set.0.into_iter().collect()
46	}
47}
48
49impl IntoIterator for Set {
50	type Item = Value;
51	type IntoIter = std::collections::btree_set::IntoIter<Value>;
52
53	fn into_iter(self) -> Self::IntoIter {
54		self.0.into_iter()
55	}
56}
57
58impl<'a> IntoIterator for &'a Set {
59	type Item = &'a Value;
60	type IntoIter = std::collections::btree_set::Iter<'a, Value>;
61
62	fn into_iter(self) -> Self::IntoIter {
63		self.0.iter()
64	}
65}
66
67impl Deref for Set {
68	type Target = BTreeSet<Value>;
69
70	fn deref(&self) -> &Self::Target {
71		&self.0
72	}
73}
74
75impl DerefMut for Set {
76	fn deref_mut(&mut self) -> &mut Self::Target {
77		&mut self.0
78	}
79}
80
81impl ToSql for Set {
82	fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
83		if self.is_empty() {
84			f.push_str("{,}");
85			return;
86		}
87
88		// Format as Python-style set literal: `{,}`, `{val,}`, `{val, val, val}`
89		f.push('{');
90		let len = self.len();
91		for (i, v) in self.iter().enumerate() {
92			v.fmt_sql(f, fmt);
93			if len == 1 {
94				f.push(',');
95			} else if i < len - 1 {
96				f.push_str(", ");
97			}
98		}
99		f.push('}');
100	}
101}