use std::collections::BTreeMap;
use anyhow::{Result, bail};
use surrealdb_strand::Strand;
use surrealdb_types::ToSql;
use crate::err::Error;
use crate::val::{Array, Object, Value};
pub fn entries((object,): (Object,)) -> Result<Value> {
Ok(Value::Array(Array(
object
.iter()
.map(|(k, v)| {
let k = Value::String(k.to_owned());
let v = v.clone();
Value::Array(Array(vec![k, v]))
})
.collect(),
)))
}
pub fn from_entries((array,): (Array,)) -> Result<Value> {
let mut obj: BTreeMap<Strand, Value> = BTreeMap::default();
for v in array.iter() {
match v {
Value::Array(Array(entry)) if entry.len() == 2 => {
let key: Strand = match entry.first() {
Some(v) => match v {
Value::String(v) => v.clone(),
v => v.to_sql().into(),
},
_ => {
bail!(Error::InvalidFunctionArguments {
name: "object::from_entries".to_string(),
message: "Expected entries, found invalid entry".to_string(),
})
}
};
let value = match entry.get(1) {
Some(v) => v,
_ => {
bail!(Error::InvalidFunctionArguments {
name: "object::from_entries".to_string(),
message: "Expected entries, found invalid entry".to_string(),
})
}
};
obj.insert(key, value.to_owned());
}
_ => {
bail!(Error::InvalidFunctionArguments {
name: "object::from_entries".to_string(),
message: format!("Expected entries, found {}", v.kind_of()),
})
}
}
}
Ok(Value::Object(Object::from(obj)))
}
pub fn extend((mut object, other): (Object, Object)) -> Result<Value> {
object.0.extend(other.0);
Ok(Value::Object(object))
}
pub fn is_empty((object,): (Object,)) -> Result<Value> {
Ok(Value::Bool(object.0.is_empty()))
}
pub fn len((object,): (Object,)) -> Result<Value> {
Ok(Value::from(object.len()))
}
pub fn keys((object,): (Object,)) -> Result<Value> {
Ok(Value::Array(Array(
object
.keys()
.map(|v| {
let strand = v.clone();
Value::String(strand)
})
.collect(),
)))
}
pub fn remove((mut object, targets): (Object, Value)) -> Result<Value> {
match targets {
Value::String(target) => {
object.remove(target.as_str());
}
Value::Array(targets) => {
for target in targets {
let Value::String(s) = target else {
bail!(Error::InvalidFunctionArguments {
name: "object::remove".to_string(),
message: format!(
"'{}' cannot be used as a key. Please use a string instead.",
target.to_sql()
),
});
};
object.remove(s.as_str());
}
}
other => {
bail!(Error::InvalidFunctionArguments {
name: "object::remove".to_string(),
message: format!(
"'{}' cannot be used as a key. Please use a string instead.",
other.to_sql()
),
})
}
}
Ok(Value::Object(object))
}
pub fn values((object,): (Object,)) -> Result<Value> {
Ok(Value::Array(Array(object.values().map(|v| v.to_owned()).collect())))
}