1pub(crate) mod builtins;
4mod call;
5mod config;
6mod ctx;
7mod erased;
8mod layer;
9pub mod layers;
10mod outcome;
11mod overlay;
12mod registry;
13mod spec;
14mod sync;
15mod templated;
16pub mod testing;
17
18pub use crate::expr::{ExprVisitor, FieldKind, FieldSpec, Rendered, ValueKind};
19pub use call::{Function, Prepare};
20pub use config::FunctionConfig;
21pub(crate) use ctx::{Binding, CallStart, Primary};
22pub use ctx::{CallInfo, Ctx};
23pub use dataflow_rs_derive::FunctionConfig;
26pub(crate) use erased::BoundCall;
27pub use layer::{BoxFuture, CallLayer, Next};
28pub use outcome::Outcome;
29pub(crate) use overlay::Overlay;
30pub(crate) use registry::Entry;
31pub use registry::{FunctionInfo, Registry};
32pub use spec::{FunctionSpec, Reference, RetrySafety};
33pub(crate) use sync::{SyncCtx, eval, task_record, test};
34pub use templated::Templated;
35
36#[doc(hidden)]
40pub mod __private {
41 pub use super::config::FunctionConfig;
42 pub use crate::base::{AuthoredPath, Result};
43 pub use crate::expr::{
44 CompileCx, ConfigField, ExprVisitor, FieldKind, FieldSpec, Output, Resolver, ValueKind,
45 Visit,
46 };
47 pub use datavalue::OwnedDataValue;
48 pub use serde_json::Value;
49 pub use std::sync::OnceLock;
50
51 use crate::base::{Error, ErrorKind, IssueCode};
52 use serde::Serialize;
53 use serde::de::DeserializeOwned;
54 use serde_json::Map;
55 use std::borrow::Cow;
56
57 #[derive(Clone, Copy, Debug)]
59 pub struct Key {
60 key: &'static str,
62 default: Option<&'static str>,
64 output: bool,
66 }
67
68 impl Key {
69 pub const fn new(key: &'static str, default: Option<&'static str>, output: bool) -> Self {
72 Self {
73 key,
74 default,
75 output,
76 }
77 }
78 }
79
80 pub fn object<'v>(input: &'v Value, cx: &mut CompileCx<'_>) -> Option<&'v Map<String, Value>> {
82 let object = input.as_object();
83 if object.is_none() {
84 cx.issue(IssueCode::InputParse, "expected an object");
85 }
86 object
87 }
88
89 pub fn unknown_keys(object: &Map<String, Value>, known: &[&str], cx: &mut CompileCx<'_>) {
92 for key in object.keys().filter(|key| !known.contains(&key.as_str())) {
93 cx.at(key.as_str(), |cx| cx.unknown_key(key, known));
94 }
95 }
96
97 fn raw(object: &Map<String, Value>, key: Key) -> Option<Cow<'_, Value>> {
100 match object.get(key.key) {
101 Some(raw) if !(key.output && raw.is_null()) => Some(Cow::Borrowed(raw)),
102 _ => key.default.map(|text| Cow::Owned(default(text, key.key))),
103 }
104 }
105
106 fn default(text: &str, key: &str) -> Value {
109 serde_json::from_str(text).unwrap_or_else(|e| {
110 unreachable!("the default of `{key}` was validated by the derive ({e}): {text}")
111 })
112 }
113
114 pub(crate) fn missing(key: &str, cx: &mut CompileCx<'_>) {
116 cx.issue(IssueCode::InputParse, format!("missing field `{key}`"));
117 }
118
119 pub fn field<T: ConfigField>(
121 object: &Map<String, Value>,
122 key: Key,
123 cx: &mut CompileCx<'_>,
124 ) -> Option<T> {
125 cx.at(key.key, |cx| match raw(object, key) {
126 Some(raw) => T::compile(&raw, cx),
127 None => T::absent().or_else(|| {
128 missing(key.key, cx);
129 None
130 }),
131 })
132 }
133
134 pub fn serde_field<T: DeserializeOwned>(
136 object: &Map<String, Value>,
137 key: Key,
138 cx: &mut CompileCx<'_>,
139 ) -> Option<T> {
140 cx.at(key.key, |cx| {
141 let Some(raw) = raw(object, key) else {
142 return T::deserialize(&Value::Null).map_or_else(
143 |_| {
144 missing(key.key, cx);
145 None
146 },
147 Some,
148 );
149 };
150 T::deserialize(&*raw)
151 .map_err(|e| cx.issue(IssueCode::InputParse, e.to_string()))
152 .ok()
153 })
154 }
155
156 pub fn serde_required<T: DeserializeOwned>() -> bool {
159 T::deserialize(&Value::Null).is_err()
160 }
161
162 pub type Entries = Vec<(String, OwnedDataValue)>;
164
165 pub fn resolve_field<T: ConfigField>(
172 entries: &mut Entries,
173 key: &str,
174 field: &T,
175 r: &mut dyn Resolver,
176 ) -> Result<()> {
177 if let Some(value) = field.resolve(r)? {
178 entries.push((key.to_owned(), value));
179 }
180 Ok(())
181 }
182
183 pub fn resolve_serde<T: Serialize>(entries: &mut Entries, key: &str, field: &T) -> Result<()> {
192 let refused = |e: serde_json::Error| {
193 Error::new(
194 ErrorKind::Config,
195 format!("the field `{key}` does not serialize: {e}"),
196 )
197 };
198 let text = serde_json::to_string(field).map_err(refused)?;
199 let value =
202 crate::base::exact(&mut serde_json::Deserializer::from_str(&text)).map_err(refused)?;
203 if !value.is_null() {
204 entries.push((key.to_owned(), value));
205 }
206 Ok(())
207 }
208
209 pub fn finish<T>(out: T, rejected_before: usize, cx: &CompileCx<'_>) -> Option<T> {
211 (cx.rejected() == rejected_before).then_some(out)
212 }
213
214 pub fn spec(
217 name: &'static str,
218 kind: FieldKind,
219 required: bool,
220 records: bool,
221 default: Option<&'static str>,
222 primary: bool,
223 description: Option<&'static str>,
224 ) -> FieldSpec {
225 FieldSpec {
226 name: Cow::Borrowed(name),
227 kind,
228 required,
229 records: records || kind.contains_output(),
230 default: default.map(Cow::Borrowed),
231 primary,
232 description: description.map(Cow::Borrowed),
233 }
234 }
235}