use serde_json_bytes::Value as JSON;
use shape::Shape;
use super::ApplyToError;
use super::MethodArgs;
use super::VarsWithPathsMap;
use super::immutable::InputPath;
use super::location::WithRange;
use crate::connectors::json_selection::ShapeContext;
use crate::connectors::spec::ConnectSpec;
mod common;
mod future;
mod public;
#[cfg(test)]
mod tests;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum ArrowMethod {
As,
Echo,
Map,
Match,
First,
Last,
Slice,
Size,
Entries,
JsonStringify,
JoinNotNull,
Filter,
Find,
Gte,
Lte,
Eq,
Ne,
Or,
And,
Gt,
Lt,
Not,
In,
Contains,
Get,
ToString,
ParseInt,
Add,
Sub,
Mul,
Div,
Mod,
TypeOf,
MatchIf,
Has,
Keys,
Values,
}
#[macro_export]
macro_rules! impl_arrow_method {
($struct_name:ident, $impl_fn_name:ident, $shape_fn_name:ident) => {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct $struct_name;
impl $crate::connectors::json_selection::methods::ArrowMethodImpl for $struct_name {
fn apply(
&self,
method_name: &WithRange<String>,
method_args: Option<&MethodArgs>,
data: &JSON,
vars: &VarsWithPathsMap,
input_path: &InputPath<JSON>,
spec: $crate::connectors::spec::ConnectSpec,
) -> (Option<JSON>, Vec<ApplyToError>) {
$impl_fn_name(method_name, method_args, data, vars, input_path, spec)
}
fn shape(
&self,
context: &$crate::connectors::json_selection::apply_to::ShapeContext,
method_name: &WithRange<String>,
method_args: Option<&MethodArgs>,
input_shape: Shape,
dollar_shape: Shape,
) -> Shape {
$shape_fn_name(context, method_name, method_args, input_shape, dollar_shape)
}
}
};
}
#[allow(dead_code)] pub(super) trait ArrowMethodImpl {
fn apply(
&self,
method_name: &WithRange<String>,
method_args: Option<&MethodArgs>,
data: &JSON,
vars: &VarsWithPathsMap,
input_path: &InputPath<JSON>,
spec: ConnectSpec,
) -> (Option<JSON>, Vec<ApplyToError>);
fn shape(
&self,
context: &ShapeContext,
method_name: &WithRange<String>,
method_args: Option<&MethodArgs>,
input_shape: Shape,
dollar_shape: Shape,
) -> Shape;
}
impl std::ops::Deref for ArrowMethod {
type Target = dyn ArrowMethodImpl;
fn deref(&self) -> &Self::Target {
match self {
Self::As => &public::AsMethod,
Self::Echo => &public::EchoMethod,
Self::Map => &public::MapMethod,
Self::Match => &public::MatchMethod,
Self::First => &public::FirstMethod,
Self::Last => &public::LastMethod,
Self::Slice => &public::SliceMethod,
Self::Size => &public::SizeMethod,
Self::Entries => &public::EntriesMethod,
Self::JsonStringify => &public::JsonStringifyMethod,
Self::JoinNotNull => &public::JoinNotNullMethod,
Self::Filter => &public::FilterMethod,
Self::Find => &public::FindMethod,
Self::Gte => &public::GteMethod,
Self::Lte => &public::LteMethod,
Self::Eq => &public::EqMethod,
Self::Ne => &public::NeMethod,
Self::Or => &public::OrMethod,
Self::And => &public::AndMethod,
Self::Gt => &public::GtMethod,
Self::Lt => &public::LtMethod,
Self::Not => &public::NotMethod,
Self::In => &public::InMethod,
Self::Contains => &public::ContainsMethod,
Self::Get => &public::GetMethod,
Self::ToString => &public::ToStringMethod,
Self::ParseInt => &public::ParseIntMethod,
Self::Add => &public::AddMethod,
Self::Sub => &public::SubMethod,
Self::Mul => &public::MulMethod,
Self::Div => &public::DivMethod,
Self::Mod => &public::ModMethod,
Self::TypeOf => &future::TypeOfMethod,
Self::MatchIf => &future::MatchIfMethod,
Self::Has => &future::HasMethod,
Self::Keys => &future::KeysMethod,
Self::Values => &future::ValuesMethod,
}
}
}
impl ArrowMethod {
pub(super) fn lookup(name: &str) -> Option<Self> {
let method_opt = match name {
"as" => Some(Self::As),
"echo" => Some(Self::Echo),
"map" => Some(Self::Map),
"eq" => Some(Self::Eq),
"match" => Some(Self::Match),
"matchIf" | "match_if" => Some(Self::MatchIf),
"typeof" => Some(Self::TypeOf),
"add" => Some(Self::Add),
"sub" => Some(Self::Sub),
"mul" => Some(Self::Mul),
"div" => Some(Self::Div),
"mod" => Some(Self::Mod),
"first" => Some(Self::First),
"last" => Some(Self::Last),
"slice" => Some(Self::Slice),
"size" => Some(Self::Size),
"has" => Some(Self::Has),
"get" => Some(Self::Get),
"keys" => Some(Self::Keys),
"values" => Some(Self::Values),
"entries" => Some(Self::Entries),
"not" => Some(Self::Not),
"or" => Some(Self::Or),
"and" => Some(Self::And),
"jsonStringify" => Some(Self::JsonStringify),
"joinNotNull" => Some(Self::JoinNotNull),
"filter" => Some(Self::Filter),
"find" => Some(Self::Find),
"gte" => Some(Self::Gte),
"lte" => Some(Self::Lte),
"ne" => Some(Self::Ne),
"gt" => Some(Self::Gt),
"lt" => Some(Self::Lt),
"in" => Some(Self::In),
"contains" => Some(Self::Contains),
"toString" => Some(Self::ToString),
"parseInt" => Some(Self::ParseInt),
_ => None,
};
match method_opt {
Some(method) if cfg!(test) || method.is_public() => Some(method),
_ => None,
}
}
pub(super) const fn is_public(&self) -> bool {
matches!(
self,
Self::As
| Self::Echo
| Self::Map
| Self::Match
| Self::First
| Self::Last
| Self::Slice
| Self::Size
| Self::Entries
| Self::JsonStringify
| Self::JoinNotNull
| Self::Filter
| Self::Find
| Self::Gte
| Self::Lte
| Self::Eq
| Self::Ne
| Self::Or
| Self::And
| Self::Gt
| Self::Lt
| Self::Not
| Self::In
| Self::Contains
| Self::Get
| Self::ToString
| Self::ParseInt
| Self::Add
| Self::Sub
| Self::Mul
| Self::Div
| Self::Mod
)
}
}