use revision::revisioned;
use storekey::{BorrowDecode, Encode};
use surrealdb_collections::{VecSet, VecSetIntoIter};
use surrealdb_types::{SqlFormat, ToSql, write_sql};
use crate::expr::Expr;
use crate::val::{IndexFormat, Value};
#[revisioned(revision(1), revision(2, optimised))]
#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Hash, Encode, BorrowDecode)]
#[storekey(format = "()")]
#[storekey(format = "IndexFormat")]
pub(crate) struct Set(#[revision(indexed_set)] pub(crate) VecSet<Value>);
impl Set {
pub fn new() -> Self {
Set(VecSet::new())
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn first(&self) -> Option<&Value> {
self.0.first()
}
pub fn last(&self) -> Option<&Value> {
self.0.last()
}
pub fn nth(&self, index: usize) -> Option<&Value> {
self.0.iter().nth(index)
}
pub fn first_mut(&mut self) -> Option<&mut Value> {
self.0.first_mut()
}
pub fn last_mut(&mut self) -> Option<&mut Value> {
self.0.last_mut()
}
pub fn nth_mut(&mut self, index: usize) -> Option<&mut Value> {
self.0.get_mut(index)
}
pub fn iter(&self) -> impl Iterator<Item = &Value> {
self.0.iter()
}
pub fn insert(&mut self, value: Value) -> bool {
self.0.insert(value)
}
pub fn contains(&self, value: &Value) -> bool {
self.0.contains(value)
}
pub fn remove(&mut self, value: &Value) -> bool {
self.0.remove(value)
}
pub fn into_literal(self) -> Vec<Expr> {
self.0.into_iter().map(Value::into_literal).collect()
}
pub fn union(&self, other: &Set) -> Set {
Set(self.0.union(&other.0))
}
pub fn intersection(&self, other: &Set) -> Set {
Set(self.0.intersection(&other.0))
}
pub fn symmetric_difference(&self, other: &Set) -> Set {
Set(self.0.symmetric_difference(&other.0))
}
pub fn complement(&self, other: &Set) -> Set {
Set(self.0.difference(&other.0))
}
pub fn flatten(self) -> Set {
let mut out = Set::new();
for v in self {
match v {
Value::Array(arr) => {
for item in arr.0 {
out.insert(item);
}
}
Value::Set(set) => {
for item in set.0 {
out.insert(item);
}
}
_ => {
out.insert(v);
}
}
}
out
}
}
impl<T> From<Vec<T>> for Set
where
Value: From<T>,
{
fn from(v: Vec<T>) -> Self {
Set(v.into_iter().map(Value::from).collect())
}
}
impl From<std::collections::BTreeSet<Value>> for Set {
fn from(set: std::collections::BTreeSet<Value>) -> Self {
Set(set.into())
}
}
impl From<VecSet<Value>> for Set {
fn from(set: VecSet<Value>) -> Self {
Set(set)
}
}
impl From<Set> for Vec<Value> {
fn from(s: Set) -> Self {
s.0.into_iter().collect()
}
}
impl TryFrom<Set> for surrealdb_types::Set {
type Error = anyhow::Error;
fn try_from(s: Set) -> Result<Self, Self::Error> {
Ok(surrealdb_types::Set::from(
s.0.into_iter().map(surrealdb_types::Value::try_from).collect::<Result<Vec<_>, _>>()?,
))
}
}
impl From<surrealdb_types::Set> for Set {
fn from(s: surrealdb_types::Set) -> Self {
Set(s.into_iter().map(Value::from).collect())
}
}
impl FromIterator<Value> for Set {
fn from_iter<I: IntoIterator<Item = Value>>(iter: I) -> Self {
Set(iter.into_iter().collect())
}
}
impl IntoIterator for Set {
type Item = Value;
type IntoIter = VecSetIntoIter<Value>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl ToSql for Set {
fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
if self.is_empty() {
return f.push_str("{,}");
}
f.push('{');
let len = self.len();
for (i, v) in self.iter().enumerate() {
write_sql!(f, sql_fmt, "{}", v);
if len == 1 {
f.push(',');
} else if i < len - 1 {
f.push_str(", ");
}
}
f.push('}');
}
}