use serde::{Deserialize, Serialize};
use schemars::JsonSchema;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(untagged)]
#[schemars(rename = "functions.Function")]
pub enum Function {
#[schemars(title = "Remote")]
Remote(RemoteFunction),
#[schemars(title = "Inline")]
Inline(InlineFunction),
}
impl Function {
pub fn validate_input(
&self,
input: &super::expression::InputValue,
) -> Option<bool> {
match self {
Function::Remote(remote_function) => {
Some(remote_function.input_schema().validate_input(input))
}
Function::Inline(_) => None,
}
}
pub fn compile_tasks(
self,
input: &super::expression::InputValue,
) -> Result<
Vec<Option<super::CompiledTask>>,
super::expression::ExpressionError,
> {
let task_exprs = match self {
Function::Remote(RemoteFunction::Scalar { tasks, .. }) => tasks,
Function::Remote(RemoteFunction::Vector { tasks, .. }) => tasks,
Function::Inline(InlineFunction::Scalar { tasks, .. }) => tasks,
Function::Inline(InlineFunction::Vector { tasks, .. }) => tasks,
};
let mut params =
super::expression::Params::Ref(super::expression::ParamsRef {
input,
output: None,
map: None,
tasks_min: None,
tasks_max: None,
depth: None,
name: None,
spec: None,
});
let mut tasks = Vec::with_capacity(task_exprs.len());
for mut task_expr in task_exprs {
tasks.push(
if let Some(skip_expr) = task_expr.take_skip()
&& skip_expr.compile_one::<bool>(¶ms)?
{
None
} else if let Some(map_expr) = task_expr.map() {
let count: u64 = map_expr.compile_one(¶ms)?;
let mut map_tasks = Vec::with_capacity(count as usize);
for i in 0..count {
match &mut params {
super::expression::Params::Ref(params_ref) => {
params_ref.map = Some(i);
}
_ => unreachable!(),
}
map_tasks.push(task_expr.clone().compile(¶ms)?);
match &mut params {
super::expression::Params::Ref(params_ref) => {
params_ref.map = None;
}
_ => unreachable!(),
}
}
Some(super::CompiledTask::Many(map_tasks))
} else {
Some(super::CompiledTask::One(task_expr.compile(¶ms)?))
},
);
}
Ok(tasks)
}
pub fn compile_output_length(
self,
input: &super::expression::InputValue,
) -> Result<Option<u64>, super::expression::ExpressionError> {
let output_length_expr = match self {
Function::Remote(RemoteFunction::Scalar { .. }) => None,
Function::Remote(RemoteFunction::Vector {
output_length, ..
}) => Some(output_length),
Function::Inline(InlineFunction::Scalar { .. }) => None,
Function::Inline(InlineFunction::Vector { .. }) => None,
};
match output_length_expr {
Some(output_length_expr) => {
let params = super::expression::Params::Ref(
super::expression::ParamsRef {
input,
output: None,
map: None,
tasks_min: None,
tasks_max: None,
depth: None,
name: None,
spec: None,
},
);
let output_length = output_length_expr.compile_one(¶ms)?;
Ok(Some(output_length))
}
None => Ok(None),
}
}
pub fn compile_input_split(
self,
input: &super::expression::InputValue,
) -> Result<
Option<Vec<super::expression::InputValue>>,
super::expression::ExpressionError,
> {
let input_split_expr = match self {
Function::Remote(RemoteFunction::Scalar { .. }) => None,
Function::Remote(RemoteFunction::Vector {
input_split, ..
}) => Some(input_split),
Function::Inline(InlineFunction::Scalar { .. }) => None,
Function::Inline(InlineFunction::Vector {
input_split, ..
}) => input_split,
};
match input_split_expr {
Some(input_split_expr) => {
let params = super::expression::Params::Ref(
super::expression::ParamsRef {
input,
output: None,
map: None,
tasks_min: None,
tasks_max: None,
depth: None,
name: None,
spec: None,
},
);
let input_split = input_split_expr.compile_one(¶ms)?;
Ok(Some(input_split))
}
None => Ok(None),
}
}
pub fn compile_input_merge(
self,
input: &super::expression::InputValue,
) -> Result<
Option<super::expression::InputValue>,
super::expression::ExpressionError,
> {
let input_merge_expr = match self {
Function::Remote(RemoteFunction::Scalar { .. }) => None,
Function::Remote(RemoteFunction::Vector {
input_merge, ..
}) => Some(input_merge),
Function::Inline(InlineFunction::Scalar { .. }) => None,
Function::Inline(InlineFunction::Vector {
input_merge, ..
}) => input_merge,
};
match input_merge_expr {
Some(input_merge_expr) => {
let params = super::expression::Params::Ref(
super::expression::ParamsRef {
input,
output: None,
map: None,
tasks_min: None,
tasks_max: None,
depth: None,
name: None,
spec: None,
},
);
let input_merge = input_merge_expr.compile_one(¶ms)?;
Ok(Some(input_merge))
}
None => Ok(None),
}
}
pub fn description(&self) -> Option<&str> {
match self {
Function::Remote(remote_function) => {
Some(remote_function.description())
}
Function::Inline(_) => None,
}
}
pub fn input_schema(&self) -> Option<&super::expression::InputSchema> {
match self {
Function::Remote(remote_function) => {
Some(remote_function.input_schema())
}
Function::Inline(_) => None,
}
}
pub fn tasks(&self) -> &[super::TaskExpression] {
match self {
Function::Remote(remote_function) => remote_function.tasks(),
Function::Inline(inline_function) => inline_function.tasks(),
}
}
pub fn output_length(&self) -> Option<&super::expression::Expression> {
match self {
Function::Remote(remote_function) => {
remote_function.output_length()
}
Function::Inline(_) => None,
}
}
pub fn input_split(&self) -> Option<&super::expression::Expression> {
match self {
Function::Remote(remote_function) => remote_function.input_split(),
Function::Inline(inline_function) => inline_function.input_split(),
}
}
pub fn input_merge(&self) -> Option<&super::expression::Expression> {
match self {
Function::Remote(remote_function) => remote_function.input_merge(),
Function::Inline(inline_function) => inline_function.input_merge(),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, arbitrary::Arbitrary)]
#[serde(tag = "type")]
#[schemars(rename = "functions.RemoteFunction")]
pub enum RemoteFunction {
#[schemars(title = "Scalar")]
#[serde(rename = "scalar.function")]
Scalar {
description: String,
input_schema: super::expression::InputSchema,
tasks: Vec<super::TaskExpression>,
},
#[schemars(title = "Vector")]
#[serde(rename = "vector.function")]
Vector {
description: String,
input_schema: super::expression::InputSchema,
tasks: Vec<super::TaskExpression>,
output_length: super::expression::Expression,
input_split: super::expression::Expression,
input_merge: super::expression::Expression,
},
}
impl RemoteFunction {
pub fn description(&self) -> &str {
match self {
RemoteFunction::Scalar { description, .. } => description,
RemoteFunction::Vector { description, .. } => description,
}
}
pub fn input_schema(&self) -> &super::expression::InputSchema {
match self {
RemoteFunction::Scalar { input_schema, .. } => input_schema,
RemoteFunction::Vector { input_schema, .. } => input_schema,
}
}
pub fn tasks(&self) -> &[super::TaskExpression] {
match self {
RemoteFunction::Scalar { tasks, .. } => tasks,
RemoteFunction::Vector { tasks, .. } => tasks,
}
}
pub fn output_length(&self) -> Option<&super::expression::Expression> {
match self {
RemoteFunction::Scalar { .. } => None,
RemoteFunction::Vector { output_length, .. } => Some(output_length),
}
}
pub fn input_split(&self) -> Option<&super::expression::Expression> {
match self {
RemoteFunction::Scalar { .. } => None,
RemoteFunction::Vector { input_split, .. } => Some(input_split),
}
}
pub fn input_merge(&self) -> Option<&super::expression::Expression> {
match self {
RemoteFunction::Scalar { .. } => None,
RemoteFunction::Vector { input_merge, .. } => Some(input_merge),
}
}
pub fn remotes(&self) -> impl Iterator<Item = &crate::RemotePath> {
self.tasks().iter().filter_map(|task| match task {
super::TaskExpression::ScalarFunction(t) => Some(&t.path),
super::TaskExpression::VectorFunction(t) => Some(&t.path),
_ => None,
})
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type")]
#[schemars(rename = "functions.InlineFunction")]
pub enum InlineFunction {
#[schemars(title = "Scalar")]
#[serde(rename = "scalar.function")]
Scalar {
tasks: Vec<super::TaskExpression>,
},
#[schemars(title = "Vector")]
#[serde(rename = "vector.function")]
Vector {
tasks: Vec<super::TaskExpression>,
input_split: Option<super::expression::Expression>,
input_merge: Option<super::expression::Expression>,
},
}
impl InlineFunction {
pub fn tasks(&self) -> &[super::TaskExpression] {
match self {
InlineFunction::Scalar { tasks, .. } => tasks,
InlineFunction::Vector { tasks, .. } => tasks,
}
}
pub fn input_split(&self) -> Option<&super::expression::Expression> {
match self {
InlineFunction::Scalar { .. } => None,
InlineFunction::Vector { input_split, .. } => input_split.as_ref(),
}
}
pub fn input_merge(&self) -> Option<&super::expression::Expression> {
match self {
InlineFunction::Scalar { .. } => None,
InlineFunction::Vector { input_merge, .. } => input_merge.as_ref(),
}
}
pub fn remotes(&self) -> impl Iterator<Item = &crate::RemotePath> {
self.tasks().iter().filter_map(|task| match task {
super::TaskExpression::ScalarFunction(t) => Some(&t.path),
super::TaskExpression::VectorFunction(t) => Some(&t.path),
_ => None,
})
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
#[schemars(rename = "functions.FunctionType")]
pub enum FunctionType {
#[schemars(title = "Scalar")]
#[serde(rename = "scalar.function")]
Scalar,
#[schemars(title = "Vector")]
#[serde(rename = "vector.function")]
Vector,
}