macro_rules! make_filter_function {
    (
        $struct_name:ident, $function_name:tt

        $(#[$attr:meta])*
        fn $create_fn_name:ident<$lifetime:tt>(
            $api_arg_name:ident : $api_arg_type:ty,
            $core_arg_name:ident : $core_arg_type:ty,
            $($arg_name:ident : $arg_type:ty),* $(,)*
        ) -> $return_type:ty {
            $($body:tt)*
        }
    ) => { ... };
}
Expand description

Make a filter function easily and avoid boilerplate.

This macro accepts the name of the filter function type, the name of the filter and the create function.

The macro generates a type implementing FilterFunction with the correct args() string derived from the function parameters of the specified create function. The generated FilterFunction::create() extracts all parameters from the argument map received from VapourSynth and passes them into the specified create function.

The create function should look like:

fn create<'core>(
    api: API,
    core: CoreRef<'core>,
    /* filter arguments */
) -> Result<Option<Box<Filter<'core> + 'core>>, Error> {
    /* ... */
}

All VapourSynth-supported types can be used, as well as Option<T> for optional parameters and ValueIter<T> for array parameters. Array parameters can be empty.

Caveat: the macro doesn’t currently allow specifying mutable parameters, so to do that they have to be reassigned to a mutable variable in the function body. This is mainly a problem for array parameters. See how the example below handles it.

Another caveat: underscore lifetimes are required for receiving ValueIter<T>.

Example

make_filter_function! {
    MyFilterFunction, "MyFilter"

    fn create_my_filter<'core>(
        _api: API,
        _core: CoreRef<'core>,
        int_parameter: i64,
        some_data: &[u8],
        optional_parameter: Option<f64>,
        array_parameter: ValueIter<'_, 'core, Node<'core>>,
        optional_array_parameter: Option<ValueIter<'_, 'core, FrameRef<'core>>>,
    ) -> Result<Option<Box<Filter<'core> + 'core>>, Error> {
        let mut array_parameter = array_parameter;
        Ok(Some(Box::new(MyFilter::new(/* ... */))));
    }
}