macro_rules! interface_builder {
(
$interface_name:ident {
$(
(
$required_field_js_name:literal: $required_field_js_type:ty,
$required_field_rust_name:ident: $required_field_rust_type:ty
),
)*
$(
$required_function_generic:ident: $required_function_setter:ident =
$required_function_rust_name:ident(
$(
$required_function_argument_name:ident: $required_function_argument_type:ty
),*
) -> $required_function_return_type:ty;
)*
}
$(
($optional_field_js_name:literal, $optional_field_rust_name:ident: $optional_field_type:ty),
)*
) => {
#[derive(Clone, Copy)]
pub struct $interface_name<'env> {
inner: ::napi::bindgen_prelude::Object<'env>
}
impl<'env> $interface_name<'env> {
pub fn new<$($required_function_generic),*>(
env: &napi::Env,
$($required_field_rust_name: $required_field_rust_type),*
$($required_function_rust_name: $required_function_generic),*
) -> Result<Self, napi::Error>
where
$(
$required_function_generic: for<'function_context> Fn(
&'function_context napi::Env,
$($required_function_argument_type,)*
) -> Result<
Option<$required_function_return_type>,
napi::Error,
>
+ std::panic::RefUnwindSafe
+ 'static,
)*
{
#[allow(unused_mut)]
let mut builder = Self {
inner: bindgen_prelude::Object::new(env)?,
};
$(builder.inner.set_named_property($required_field_js_name, $required_field_rust_name)?;)*
$(builder.$required_function_setter(env, $required_function_rust_name)?;)*
Ok(builder)
}
$(
pub fn $optional_field_rust_name(mut self, $optional_field_rust_name: $optional_field_type) -> Result<Self, ::napi::Error> {
self.inner.set_named_property($optional_field_js_name, $optional_field_rust_name)?;
Ok(self)
}
)*
}
impl<'env> bindgen_prelude::ToNapiValue for &$interface_name<'env> {
unsafe fn to_napi_value(env: napi_sys::napi_env, val: Self) -> Result<napi_sys::napi_value, napi::Error> {
unsafe { bindgen_prelude::Object::to_napi_value(env, val.inner) }
}
}
impl<'env> bindgen_prelude::ToNapiValue for $interface_name<'env> {
unsafe fn to_napi_value(env: napi_sys::napi_env, val: Self) -> Result<napi_sys::napi_value, napi::Error> {
unsafe { bindgen_prelude::Object::to_napi_value(env, val.inner) }
}
}
impl<'env> bindgen_prelude::TypeName for $interface_name<'env> {
fn type_name() -> &'static str {
bindgen_prelude::Object::type_name()
}
fn value_type() -> napi::ValueType {
bindgen_prelude::Object::value_type()
}
}
impl<'env> bindgen_prelude::FromNapiValue for $interface_name<'env> {
unsafe fn from_napi_value(
raw_env: napi_sys::napi_env,
napi_val: napi_sys::napi_value,
) -> Result<Self, napi::Error> {
let inner = unsafe { bindgen_prelude::Object::from_napi_value(raw_env, napi_val) }?;
Ok(Self { inner })
}
}
impl<'env> bindgen_prelude::ValidateNapiValue for $interface_name<'env> {
unsafe fn validate(
raw_env: napi_sys::napi_env,
raw_interface_value: napi_sys::napi_value,
) -> Result<napi_sys::napi_value, napi::Error> {
#[allow(unused)]
let interface = match unsafe {
<bindgen_prelude::Object as bindgen_prelude::ValidateNapiValue>::validate(raw_env, raw_interface_value)
} {
Ok(_validated_object) => bindgen_prelude::Object::from_raw(raw_env, raw_interface_value),
Err(error) => {
return Err(napi::Error::from_reason(format!(
"{} should be an Object: {}",
stringify!($interface_name),
error
)));
}
};
$(
let _property_value: $required_field_js_type = interface.get_named_property($required_field_js_name).map_err(|mut error| {
error.reason = format!(
"Error validating property {} of {}: {}",
$required_field_js_name,
stringify!($interface_name),
error.reason
);
error
})?;
)*
Ok(raw_interface_value)
}
}
};
}
pub(crate) use interface_builder;