macro_rules! object_reference {
    ($reference_name:ident: $owned_name:ident) => {
        pub struct $reference_name {
            inner: bindgen_prelude::ObjectRef,
        }

        impl $reference_name {
            pub fn get_inner<'env>(
                &self,
                env: &'env napi::Env,
            ) -> Result<$owned_name<'env>, napi::Error> {
                let inner = self.inner.get_value(env)?;

                Ok($owned_name { inner })
            }
        }

        impl<'env> $owned_name<'env> {
            pub fn create_ref(&self) -> Result<$reference_name, napi::Error> {
                let inner = self.inner.create_ref()?;

                Ok($reference_name { inner })
            }
        }

        impl bindgen_prelude::ToNapiValue for $reference_name {
            unsafe fn to_napi_value(
                raw_env: napi_sys::napi_env,
                value: Self,
            ) -> Result<napi_sys::napi_value, napi::Error> {
                unsafe { bindgen_prelude::ObjectRef::to_napi_value(raw_env, value.inner) }
            }
        }

        impl bindgen_prelude::FromNapiValue for $reference_name {
            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::ObjectRef::from_napi_value(raw_env, napi_val) }?;

                Ok(Self { inner })
            }
        }
    };
}

pub(crate) use object_reference;