use std::{marker::PhantomData, time::Duration};
use dart_sys::{Dart_Handle, Dart_PersistentHandle};
use medea_macro::dart_bridge;
use crate::{
api::{DartValue, Error as DartError},
platform::dart::utils::{dart_api, dart_future::FutureFromDart},
};
#[dart_bridge("flutter/lib/src/native/ffi/completer.g.dart")]
mod completer {
use dart_sys::Dart_Handle;
use crate::{
api::{DartValue, Error as DartError},
platform::Error,
};
extern "C" {
pub fn init() -> Result<Dart_Handle, Error>;
pub fn complete(fut: Dart_Handle, val: DartValue) -> Result<(), Error>;
pub fn complete_error(
fut: Dart_Handle,
val: DartError,
) -> Result<(), Error>;
pub fn future(fut: Dart_Handle) -> Result<Dart_Handle, Error>;
pub fn delayed(delay_ms: i32) -> Result<Dart_Handle, Error>;
}
}
pub async fn delay_for(delay: Duration) {
#[expect( // overflow is unexpected
clippy::cast_possible_truncation,
reason = "overflow is unexpected",
)]
let delay = delay.as_millis() as i32;
let delayed = unsafe { completer::delayed(delay) }.unwrap();
let delayed_fut = unsafe { FutureFromDart::execute::<()>(delayed) };
delayed_fut.await.unwrap();
}
#[derive(Debug)]
pub struct Completer<T, E> {
handle: Dart_PersistentHandle,
_success_kind: PhantomData<*const T>,
_error_kind: PhantomData<*const E>,
}
impl<T, E> Completer<T, E> {
#[must_use]
pub fn new() -> Self {
let completer = unsafe { completer::init() }.unwrap();
let handle = unsafe { dart_api::new_persistent_handle(completer) };
Self { handle, _success_kind: PhantomData, _error_kind: PhantomData }
}
#[must_use]
pub fn future(&self) -> Dart_Handle {
let handle = unsafe { dart_api::handle_from_persistent(self.handle) };
unsafe { completer::future(handle) }.unwrap()
}
}
impl<T, E> Default for Completer<T, E> {
fn default() -> Self {
Self::new()
}
}
impl<T: Into<DartValue>, E> Completer<T, E> {
pub fn complete(&self, arg: T) {
let handle = unsafe { dart_api::handle_from_persistent(self.handle) };
unsafe { completer::complete(handle, arg.into()) }.unwrap();
}
}
impl<T> Completer<T, DartError> {
pub fn complete_error(&self, e: DartError) {
let handle = unsafe { dart_api::handle_from_persistent(self.handle) };
unsafe { completer::complete_error(handle, e) }.unwrap();
}
}