use std::marker::PhantomData;
use dart_sys::Dart_PersistentHandle;
use flutter_rust_bridge::DartOpaque;
use medea_macro::dart_bridge;
use crate::{
api::DartValue,
platform::{Callback, utils::dart_api},
};
#[dart_bridge("flutter/lib/src/native/ffi/function.g.dart")]
mod function {
use dart_sys::Dart_Handle;
use crate::{api::DartValue, platform::Error};
extern "C" {
pub fn caller(f: Dart_Handle, val: DartValue) -> Result<(), Error>;
}
}
impl<A: Into<DartValue>> Callback<A> {
pub fn call1<T: Into<A>>(&self, arg: T) {
if let Some(f) = self.0.borrow().as_ref() {
f.call1(arg.into());
}
}
}
#[derive(Debug)]
pub struct Function<T> {
dart_fn: Dart_PersistentHandle,
_arg: PhantomData<*const T>,
}
impl<T> Function<T> {
#[must_use]
pub fn new(cb: DartOpaque) -> Self {
let opaque = cb.into_inner().unwrap();
let ptr = opaque.create_dart_handle();
let dart_fn = unsafe { dart_api::new_persistent_handle(ptr.cast()) };
Self { dart_fn, _arg: PhantomData }
}
}
impl Function<()> {
pub fn call0(&self) {
self.call1(());
}
}
impl<T: Into<DartValue>> Function<T> {
pub fn call1(&self, arg: T) {
let fn_handle =
unsafe { dart_api::handle_from_persistent(self.dart_fn) };
unsafe { function::caller(fn_handle, arg.into()) }.unwrap();
}
}
impl<T> Drop for Function<T> {
fn drop(&mut self) {
unsafe {
dart_api::delete_persistent_handle(self.dart_fn);
}
}
}