use crate::Result;
use crate::regex_dialect::RegexDialect;
use crate::semantics::{builtin_function, builtin_method_with, coerce_collection};
use crate::value::{Object, Value};
pub trait DataContext {
fn root(&self, name: &str) -> Value;
fn get(&self, row: &Value, key: &str) -> Result<Value>;
fn to_rows(&self, value: &Value) -> Vec<Value>;
fn identity(&self, row: &Value) -> Value;
fn call_function(&self, name: &str, args: &[Value]) -> Option<Result<Value>> {
let _ = (name, args);
None
}
fn call_method(&self, name: &str, recv: &Value, args: &[Value]) -> Option<Result<Value>> {
let _ = (name, recv, args);
None
}
fn regex_dialect(&self) -> RegexDialect {
RegexDialect::Oqx
}
}
#[derive(Clone, Debug, Default)]
pub struct DefaultContext {
roots: Object,
regex_dialect: RegexDialect,
}
impl DefaultContext {
pub fn new(roots: Object) -> Self {
Self {
roots,
regex_dialect: RegexDialect::Oqx,
}
}
pub fn with_regex_dialect(mut self, dialect: RegexDialect) -> Self {
self.regex_dialect = dialect;
self
}
pub fn roots(&self) -> &Object {
&self.roots
}
pub fn read(row: &Value, key: &str) -> Value {
match row {
Value::Object(o) => o.get(key).cloned().unwrap_or(Value::Undefined),
Value::Array(a) => match key.parse::<usize>() {
Ok(i) if key == i.to_string() => a.get(i).cloned().unwrap_or(Value::Undefined),
_ => Value::Undefined,
},
_ => Value::Undefined,
}
}
}
impl DataContext for DefaultContext {
fn root(&self, name: &str) -> Value {
self.roots.get(name).cloned().unwrap_or(Value::Undefined)
}
fn get(&self, row: &Value, key: &str) -> Result<Value> {
Ok(Self::read(row, key))
}
fn to_rows(&self, value: &Value) -> Vec<Value> {
coerce_collection(value).into_owned()
}
fn identity(&self, row: &Value) -> Value {
if let Value::Object(o) = row {
if let Some(id) = o.get("id") {
return id.clone();
}
}
row.clone()
}
fn call_function(&self, name: &str, args: &[Value]) -> Option<Result<Value>> {
builtin_function(name, args)
}
fn call_method(&self, name: &str, recv: &Value, args: &[Value]) -> Option<Result<Value>> {
builtin_method_with(self.regex_dialect, name, recv, args)
}
fn regex_dialect(&self) -> RegexDialect {
self.regex_dialect
}
}