use anyhow::Result;
use reblessive::tree::TreeStack;
use crate::exec::function::{FunctionRegistry, ScalarFunction, Signature};
use crate::exec::physical_expr::EvalContext;
use crate::expr::Kind;
use crate::fnc::args::FromArgs;
use crate::val::Value;
#[derive(Debug, Clone, Copy, Default)]
pub struct ValueDiff;
impl ScalarFunction for ValueDiff {
fn name(&self) -> &'static str {
"value::diff"
}
fn signature(&self) -> Signature {
Signature::new().arg("val1", Kind::Any).arg("val2", Kind::Any).returns(Kind::Any)
}
fn is_pure(&self) -> bool {
true
}
fn is_async(&self) -> bool {
true
}
fn invoke(&self, _args: Vec<Value>) -> Result<Value> {
Err(anyhow::anyhow!("Function '{}' requires async execution", self.name()))
}
fn invoke_async<'a>(
&'a self,
_ctx: &'a EvalContext<'_>,
args: Vec<Value>,
) -> crate::exec::BoxFut<'a, Result<Value>> {
Box::pin(async move {
let args = FromArgs::from_args("value::diff", args)?;
crate::fnc::value::diff(args).await
})
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ValuePatch;
impl ScalarFunction for ValuePatch {
fn name(&self) -> &'static str {
"value::patch"
}
fn signature(&self) -> Signature {
Signature::new().arg("value", Kind::Any).arg("patch", Kind::Any).returns(Kind::Any)
}
fn is_pure(&self) -> bool {
true
}
fn is_async(&self) -> bool {
true
}
fn invoke(&self, _args: Vec<Value>) -> Result<Value> {
Err(anyhow::anyhow!("Function '{}' requires async execution", self.name()))
}
fn invoke_async<'a>(
&'a self,
_ctx: &'a EvalContext<'_>,
args: Vec<Value>,
) -> crate::exec::BoxFut<'a, Result<Value>> {
Box::pin(async move {
let args = FromArgs::from_args("value::patch", args)?;
crate::fnc::value::patch(args).await
})
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ValueChain;
impl ScalarFunction for ValueChain {
fn name(&self) -> &'static str {
"value::chain"
}
fn signature(&self) -> Signature {
Signature::new().arg("value", Kind::Any).arg("closure", Kind::Any).returns(Kind::Any)
}
fn is_pure(&self) -> bool {
false
}
fn is_async(&self) -> bool {
true
}
fn invoke(&self, _args: Vec<Value>) -> Result<Value> {
Err(anyhow::anyhow!("Function '{}' requires async execution", self.name()))
}
fn invoke_async<'a>(
&'a self,
ctx: &'a EvalContext<'_>,
args: Vec<Value>,
) -> crate::exec::BoxFut<'a, Result<Value>> {
Box::pin(async move {
use crate::doc::CursorDoc;
let args = FromArgs::from_args("value::chain", args)?;
let frozen = ctx.exec_ctx.ctx();
let opt = ctx.exec_ctx.options();
let doc = ctx
.document_root
.or(ctx.current_value)
.map(|v| CursorDoc::new(None, None, v.clone()));
let mut stack = TreeStack::new();
stack
.enter(|stk| async move {
crate::fnc::value::chain((stk, frozen, opt, doc.as_ref()), args).await
})
.finish()
.await
})
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ValueExpect;
impl ScalarFunction for ValueExpect {
fn name(&self) -> &'static str {
"value::expect"
}
fn signature(&self) -> Signature {
Signature::new()
.arg("value", Kind::Any)
.arg("closure", Kind::Any)
.optional("message", Kind::String)
.returns(Kind::Any)
}
fn is_pure(&self) -> bool {
false
}
fn is_async(&self) -> bool {
true
}
fn invoke(&self, _args: Vec<Value>) -> Result<Value> {
Err(anyhow::anyhow!("Function '{}' requires async execution", self.name()))
}
fn invoke_async<'a>(
&'a self,
ctx: &'a EvalContext<'_>,
args: Vec<Value>,
) -> crate::exec::BoxFut<'a, Result<Value>> {
Box::pin(async move {
use crate::doc::CursorDoc;
let args = FromArgs::from_args("value::expect", args)?;
let frozen = ctx.exec_ctx.ctx();
let opt = ctx.exec_ctx.options();
let doc = ctx
.document_root
.or(ctx.current_value)
.map(|v| CursorDoc::new(None, None, v.clone()));
let mut stack = TreeStack::new();
stack
.enter(|stk| async move {
crate::fnc::value::expect((stk, frozen, opt, doc.as_ref()), args).await
})
.finish()
.await
})
}
}
pub fn register(registry: &mut FunctionRegistry) {
registry.register(ValueDiff);
registry.register(ValuePatch);
registry.register(ValueChain);
registry.register(ValueExpect);
}