wef 0.6.0

Wef is a Rust library for embedding WebView functionality using Chromium Embedded Framework (CEF3) with offscreen rendering support.
use std::marker::PhantomData;

use futures_util::future::BoxFuture;
use serde_json::Value;

use crate::{AsyncFunctionType, Frame, FunctionType, query::QueryCallback};

pub(crate) trait DynFunctionType: Send + Sync {
    fn num_arguments(&self) -> usize;

    fn call(
        &self,
        spawner: Option<&(dyn Fn(BoxFuture<'static, ()>) + Send + Sync)>,
        frame: Frame,
        args: Vec<Value>,
        callback: QueryCallback,
    );
}

pub(crate) struct DynFunctionWrapper<F, S, R> {
    func: F,
    _mark: PhantomData<(S, R)>,
}

impl<F, S, R> DynFunctionWrapper<F, S, R> {
    #[inline]
    pub(crate) fn new(func: F) -> Self {
        Self {
            func,
            _mark: PhantomData,
        }
    }
}

impl<F, S, R> DynFunctionType for DynFunctionWrapper<F, S, R>
where
    F: FunctionType<S, R> + Send + Sync,
    S: Send + Sync,
    R: Send + Sync,
{
    #[inline]
    fn num_arguments(&self) -> usize {
        F::NUM_ARGUMENTS
    }

    #[inline]
    fn call(
        &self,
        _spawner: Option<&(dyn Fn(BoxFuture<'static, ()>) + Send + Sync)>,
        frame: Frame,
        args: Vec<Value>,
        callback: QueryCallback,
    ) {
        callback.result(self.func.call(frame, args))
    }
}

pub(crate) struct DynAsyncFunctionWrapper<F, S, R> {
    func: F,
    _mark: PhantomData<(S, R)>,
}

impl<F, S, R> DynAsyncFunctionWrapper<F, S, R> {
    #[inline]
    pub(crate) fn new(func: F) -> Self {
        Self {
            func,
            _mark: PhantomData,
        }
    }
}

impl<F, S, R> DynFunctionType for DynAsyncFunctionWrapper<F, S, R>
where
    F: AsyncFunctionType<S, R> + Send + Sync,
    S: Send + Sync,
    R: Send + Sync,
{
    #[inline]
    fn num_arguments(&self) -> usize {
        F::NUM_ARGUMENTS
    }

    #[inline]
    fn call(
        &self,
        spawner: Option<&(dyn Fn(BoxFuture<'static, ()>) + Send + Sync)>,
        frame: Frame,
        args: Vec<Value>,
        callback: QueryCallback,
    ) {
        let spawner = spawner.expect("BUG: spawner is None");
        let fut = self.func.call(frame, args);
        spawner(Box::pin(async move { callback.result(fut.await) }));
    }
}