use {
crate::{error::Error, ext, string::ToStringValue},
js_sys::{ArrayBuffer, Uint8Array},
std::{
pin::Pin,
task::{Context, Poll},
},
wasm_bindgen::prelude::*,
wasm_bindgen_futures::JsFuture,
};
pub(crate) mod api {
use super::*;
#[inline]
pub fn invoke<C>(cmd: C) -> Invoke<C::Js>
where
C: ToStringValue,
{
let cmd = cmd.to_string_value();
let args = JsValue::UNDEFINED;
let opts = Options::empty();
Invoke { cmd, args, opts }
}
}
pub struct Invoke<C, A = JsValue> {
cmd: C,
args: A,
opts: Options,
}
impl<C, A> Invoke<C, A> {
#[cfg_attr(feature = "serde", doc = "```")]
#[cfg_attr(not(feature = "serde"), doc = "```ignore")]
#[inline]
pub fn with_args<T>(self, args: T) -> Invoke<C, T::Js>
where
T: ToArgs,
{
let cmd = self.cmd;
let args = args.to_args();
let opts = self.opts;
Invoke { cmd, args, opts }
}
#[cfg_attr(feature = "serde", doc = "```")]
#[cfg_attr(not(feature = "serde"), doc = "```ignore")]
#[inline]
pub fn with_options(self, opts: Options) -> Self {
Self { opts, ..self }
}
}
pub struct InvokeFuture(JsFuture);
impl InvokeFuture {
#[inline]
pub fn into_future(self) -> JsFuture {
self.0
}
}
impl Future for InvokeFuture {
type Output = Result<JsValue, Error>;
#[inline]
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let me = self.get_mut();
Pin::new(&mut me.0).poll(cx).map_err(Error)
}
}
impl<C, A> IntoFuture for Invoke<C, A>
where
C: AsRef<JsValue>,
A: AsRef<JsValue>,
{
type Output = Result<JsValue, Error>;
type IntoFuture = InvokeFuture;
#[inline]
fn into_future(self) -> Self::IntoFuture {
let promise = ext::invoke(self.cmd.as_ref(), self.args.as_ref(), self.opts);
InvokeFuture(JsFuture::from(promise))
}
}
pub trait ToArgs {
type Js: AsRef<JsValue>;
fn to_args(self) -> Self::Js;
}
impl ToArgs for ArrayBuffer {
type Js = JsValue;
#[inline]
fn to_args(self) -> Self::Js {
JsValue::from(self)
}
}
impl<'arr> ToArgs for &'arr ArrayBuffer {
type Js = &'arr JsValue;
#[inline]
fn to_args(self) -> Self::Js {
self
}
}
impl ToArgs for Uint8Array {
type Js = JsValue;
#[inline]
fn to_args(self) -> Self::Js {
JsValue::from(self)
}
}
impl<'arr> ToArgs for &'arr Uint8Array {
type Js = &'arr JsValue;
#[inline]
fn to_args(self) -> Self::Js {
self
}
}
impl ToArgs for &[u8] {
type Js = JsValue;
#[inline]
fn to_args(self) -> Self::Js {
Uint8Array::from(self).to_args()
}
}
impl<const N: usize> ToArgs for &[u8; N] {
type Js = JsValue;
#[inline]
fn to_args(self) -> Self::Js {
self.as_slice().to_args()
}
}
#[wasm_bindgen]
pub struct Options {
pub(crate) headers: JsValue,
}
impl Options {
pub(crate) const fn empty() -> Self {
let headers = JsValue::UNDEFINED;
Self { headers }
}
}
#[wasm_bindgen]
impl Options {
#[inline]
#[wasm_bindgen(getter)]
pub fn headers(self) -> JsValue {
self.headers
}
}
pub trait IntoHeaders {
fn into_headers(self) -> Result<JsValue, Error>;
#[inline]
fn into_options(self) -> Result<Options, Error>
where
Self: Sized,
{
let headers = self.into_headers()?;
Ok(Options { headers })
}
}