ff_script/macros.rs
1//! The `ff_function!` declarative macro for typed FCALL wrappers.
2//!
3//! Generates an async function that:
4//! 1. Builds KEYS and ARGV vectors from the provided expressions
5//! 2. Calls `conn.fcall::<Value>(fn_name, &keys, &argv)`
6//! 3. Parses the result via `FromFcallResult`
7//!
8//! # Example
9//!
10//! ```ignore
11//! ff_function! {
12//! /// Complete an active execution.
13//! pub ff_complete_execution(args: CompleteExecutionArgs) -> CompleteExecutionResult {
14//! keys(ctx: &ExecKeyContext) {
15//! ctx.core(),
16//! ctx.attempt_hash(args.attempt_index),
17//! ctx.lease_current(),
18//! }
19//! argv {
20//! args.execution_id.to_string(),
21//! args.lease_id.to_string(),
22//! }
23//! }
24//! }
25//! ```
26
27/// Generate typed async FCALL wrappers from a declarative specification.
28///
29/// Each invocation defines one or more functions. The macro generates:
30/// - An `async fn` that takes `conn`, a key context, and typed args
31/// - Builds KEYS and ARGV vectors from the provided expressions
32/// - Calls `FCALL <function_name>` via the ferriskey client
33/// - Parses the result via the `FromFcallResult` trait
34#[macro_export]
35macro_rules! ff_function {
36 // Support multiple function definitions in one block
37 (
38 $(
39 $(#[$attr:meta])*
40 $vis:vis $fn_name:ident (
41 $args_name:ident : $args_type:ty
42 ) -> $result_type:ty {
43 keys( $ctx_name:ident : & $ctx_type:ty ) {
44 $( $key_expr:expr ),* $(,)?
45 }
46 argv {
47 $( $argv_expr:expr ),* $(,)?
48 }
49 }
50 )*
51 ) => {
52 $(
53 $(#[$attr])*
54 $vis async fn $fn_name(
55 conn: &ferriskey::Client,
56 $ctx_name: &$ctx_type,
57 $args_name: &$args_type,
58 ) -> ::core::result::Result<$result_type, $crate::error::ScriptError> {
59 let keys: ::std::vec::Vec<String> = vec![ $( $key_expr ),* ];
60 let argv: ::std::vec::Vec<String> = vec![ $( $argv_expr ),* ];
61 let key_refs: ::std::vec::Vec<&str> = keys.iter().map(|s| s.as_str()).collect();
62 let argv_refs: ::std::vec::Vec<&str> = argv.iter().map(|s| s.as_str()).collect();
63 let raw = conn
64 .fcall::<ferriskey::Value>(stringify!($fn_name), &key_refs, &argv_refs)
65 .await
66 .map_err($crate::error::ScriptError::Valkey)?;
67 <$result_type as $crate::result::FromFcallResult>::from_fcall_result(&raw)
68 }
69 )*
70 };
71}