1use serde_json_bytes::Value as JSON;
2use shape::Shape;
3
4use super::ApplyToError;
5use super::MethodArgs;
6use super::VarsWithPathsMap;
7use super::immutable::InputPath;
8use super::location::WithRange;
9use crate::connectors::json_selection::ShapeContext;
10use crate::connectors::spec::ConnectSpec;
11
12mod common;
13
14mod future;
23mod public;
24
25#[cfg(test)]
26mod tests;
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub(super) enum ArrowMethod {
30 As,
32 Echo,
33 Map,
34 Match,
35 First,
36 Last,
37 Slice,
38 Size,
39 Entries,
40 JsonParse,
41 JsonStringify,
42 JoinNotNull,
43 Filter,
44 Find,
45 Gte,
46 Lte,
47 Eq,
48 Ne,
49 Or,
50 And,
51 Gt,
52 Lt,
53 Not,
54 In,
55 Contains,
56 Get,
57 ToString,
58 ParseInt,
59 Add,
60 Sub,
61 Mul,
62 Div,
63 Mod,
64 KeysToCamelCase,
65 KeysToCamelCaseDeep,
66 Split,
67 Trim,
68 TrimStart,
69 TrimEnd,
70
71 TypeOf,
73 MatchIf,
74 Has,
75 Keys,
76 Values,
77}
78
79#[macro_export]
80macro_rules! impl_arrow_method {
81 ($struct_name:ident, $impl_fn_name:ident, $shape_fn_name:ident) => {
82 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
83 pub(crate) struct $struct_name;
84 impl $crate::connectors::json_selection::methods::ArrowMethodImpl for $struct_name {
85 fn apply(
86 &self,
87 method_name: &WithRange<String>,
88 method_args: Option<&MethodArgs>,
89 data: &JSON,
90 vars: &VarsWithPathsMap,
91 input_path: &InputPath<JSON>,
92 spec: $crate::connectors::spec::ConnectSpec,
93 ) -> (Option<JSON>, Vec<ApplyToError>) {
94 $impl_fn_name(method_name, method_args, data, vars, input_path, spec)
95 }
96
97 fn shape(
98 &self,
99 context: &$crate::connectors::json_selection::apply_to::ShapeContext,
100 method_name: &WithRange<String>,
101 method_args: Option<&MethodArgs>,
102 input_shape: Shape,
103 dollar_shape: Shape,
104 ) -> Shape {
105 $shape_fn_name(context, method_name, method_args, input_shape, dollar_shape)
106 }
107 }
108 };
109}
110
111#[allow(dead_code)] pub(super) trait ArrowMethodImpl {
113 fn apply(
114 &self,
115 method_name: &WithRange<String>,
116 method_args: Option<&MethodArgs>,
117 data: &JSON,
118 vars: &VarsWithPathsMap,
119 input_path: &InputPath<JSON>,
120 spec: ConnectSpec,
121 ) -> (Option<JSON>, Vec<ApplyToError>);
122
123 fn shape(
124 &self,
125 context: &ShapeContext,
126 method_name: &WithRange<String>,
131 method_args: Option<&MethodArgs>,
135 input_shape: Shape,
138 dollar_shape: Shape,
141 ) -> Shape;
142}
143
144impl std::ops::Deref for ArrowMethod {
147 type Target = dyn ArrowMethodImpl;
148
149 fn deref(&self) -> &Self::Target {
150 match self {
151 Self::As => &public::AsMethod,
153 Self::Echo => &public::EchoMethod,
154 Self::Map => &public::MapMethod,
155 Self::Match => &public::MatchMethod,
156 Self::First => &public::FirstMethod,
157 Self::Last => &public::LastMethod,
158 Self::Slice => &public::SliceMethod,
159 Self::Size => &public::SizeMethod,
160 Self::Entries => &public::EntriesMethod,
161 Self::JsonParse => &public::JsonParseMethod,
162 Self::JsonStringify => &public::JsonStringifyMethod,
163 Self::JoinNotNull => &public::JoinNotNullMethod,
164 Self::Filter => &public::FilterMethod,
165 Self::Find => &public::FindMethod,
166 Self::Gte => &public::GteMethod,
167 Self::Lte => &public::LteMethod,
168 Self::Eq => &public::EqMethod,
169 Self::Ne => &public::NeMethod,
170 Self::Or => &public::OrMethod,
171 Self::And => &public::AndMethod,
172 Self::Gt => &public::GtMethod,
173 Self::Lt => &public::LtMethod,
174 Self::Not => &public::NotMethod,
175 Self::In => &public::InMethod,
176 Self::Contains => &public::ContainsMethod,
177 Self::Get => &public::GetMethod,
178 Self::ToString => &public::ToStringMethod,
179 Self::ParseInt => &public::ParseIntMethod,
180 Self::Add => &public::AddMethod,
181 Self::Sub => &public::SubMethod,
182 Self::Mul => &public::MulMethod,
183 Self::Div => &public::DivMethod,
184 Self::Mod => &public::ModMethod,
185 Self::KeysToCamelCase => &public::KeysToCamelCaseMethod,
186 Self::KeysToCamelCaseDeep => &public::KeysToCamelCaseDeepMethod,
187 Self::Split => &public::SplitMethod,
188 Self::Trim => &public::TrimMethod,
189 Self::TrimStart => &public::TrimStartMethod,
190 Self::TrimEnd => &public::TrimEndMethod,
191
192 Self::TypeOf => &future::TypeOfMethod,
194 Self::MatchIf => &future::MatchIfMethod,
195 Self::Has => &future::HasMethod,
196 Self::Keys => &future::KeysMethod,
197 Self::Values => &future::ValuesMethod,
198 }
199 }
200}
201
202impl ArrowMethod {
203 pub(super) fn lookup(name: &str) -> Option<Self> {
207 let method_opt = match name {
208 "as" => Some(Self::As),
209 "echo" => Some(Self::Echo),
210 "map" => Some(Self::Map),
211 "eq" => Some(Self::Eq),
212 "match" => Some(Self::Match),
213 "matchIf" | "match_if" => Some(Self::MatchIf),
217 "typeof" => Some(Self::TypeOf),
218 "add" => Some(Self::Add),
219 "sub" => Some(Self::Sub),
220 "mul" => Some(Self::Mul),
221 "div" => Some(Self::Div),
222 "mod" => Some(Self::Mod),
223 "first" => Some(Self::First),
224 "last" => Some(Self::Last),
225 "slice" => Some(Self::Slice),
226 "size" => Some(Self::Size),
227 "has" => Some(Self::Has),
228 "get" => Some(Self::Get),
229 "keys" => Some(Self::Keys),
230 "values" => Some(Self::Values),
231 "entries" => Some(Self::Entries),
232 "not" => Some(Self::Not),
233 "or" => Some(Self::Or),
234 "and" => Some(Self::And),
235 "jsonParse" => Some(Self::JsonParse),
236 "jsonStringify" => Some(Self::JsonStringify),
237 "joinNotNull" => Some(Self::JoinNotNull),
238 "filter" => Some(Self::Filter),
239 "find" => Some(Self::Find),
240 "gte" => Some(Self::Gte),
241 "lte" => Some(Self::Lte),
242 "ne" => Some(Self::Ne),
243 "gt" => Some(Self::Gt),
244 "lt" => Some(Self::Lt),
245 "in" => Some(Self::In),
246 "contains" => Some(Self::Contains),
247 "toString" => Some(Self::ToString),
248 "parseInt" => Some(Self::ParseInt),
249 "keysToCamelCase" => Some(Self::KeysToCamelCase),
250 "keysToCamelCaseDeep" => Some(Self::KeysToCamelCaseDeep),
251 "split" => Some(Self::Split),
252 "trim" => Some(Self::Trim),
253 "trimStart" => Some(Self::TrimStart),
254 "trimEnd" => Some(Self::TrimEnd),
255 _ => None,
256 };
257
258 match method_opt {
259 Some(method) if cfg!(test) || method.is_public() => Some(method),
260 _ => None,
261 }
262 }
263
264 pub(super) const fn is_public(&self) -> bool {
265 matches!(
269 self,
270 Self::As
271 | Self::Echo
272 | Self::Map
273 | Self::Match
274 | Self::First
275 | Self::Last
276 | Self::Slice
277 | Self::Size
278 | Self::Entries
279 | Self::JsonParse
280 | Self::JsonStringify
281 | Self::JoinNotNull
282 | Self::Filter
283 | Self::Find
284 | Self::Gte
285 | Self::Lte
286 | Self::Eq
287 | Self::Ne
288 | Self::Or
289 | Self::And
290 | Self::Gt
291 | Self::Lt
292 | Self::Not
293 | Self::In
294 | Self::Contains
295 | Self::Get
296 | Self::ToString
297 | Self::ParseInt
298 | Self::Add
299 | Self::Sub
300 | Self::Mul
301 | Self::Div
302 | Self::Mod
303 | Self::KeysToCamelCase
304 | Self::KeysToCamelCaseDeep
305 | Self::Split
306 | Self::Trim
307 | Self::TrimStart
308 | Self::TrimEnd
309 )
310 }
311}