use alloc::boxed::Box;
use core::future::{Future};
use core::pin::{Pin};
use core::marker::{PhantomData, Unpin};
use core::task::Poll;
#[cfg(feature = "rpc_try")]
use core::ops::Try;
use crate::{any_pointer, Error, MessageSize};
use crate::traits::{Pipelined, Owned};
use crate::private::capability::{ClientHook, ParamsHook, RequestHook, ResponseHook, ResultsHook};
#[must_use = "futures do nothing unless polled"]
pub struct Promise<T, E> {
inner: PromiseInner<T, E>,
}
enum PromiseInner<T, E> {
Immediate(Result<T,E>),
Deferred(Pin<Box<dyn Future<Output=core::result::Result<T,E>> + 'static>>),
Empty,
}
impl <T, E> Unpin for PromiseInner<T,E> {}
impl <T, E> Promise<T, E> {
pub fn ok(value: T) -> Promise<T, E> {
Promise { inner: PromiseInner::Immediate(Ok(value)) }
}
pub fn err(error: E) -> Promise<T, E> {
Promise { inner: PromiseInner::Immediate(Err(error)) }
}
pub fn from_future<F>(f: F) -> Promise<T, E>
where F: Future<Output=core::result::Result<T,E>> + 'static
{
Promise { inner: PromiseInner::Deferred(Box::pin(f)) }
}
}
impl <T, E> Future for Promise<T, E>
{
type Output = core::result::Result<T,E>;
fn poll(self: Pin<&mut Self>, cx: &mut ::core::task::Context) -> Poll<Self::Output> {
match self.get_mut().inner {
PromiseInner::Empty => panic!("Promise polled after done."),
ref mut imm @ PromiseInner::Immediate(_) => {
match core::mem::replace(imm, PromiseInner::Empty) {
PromiseInner::Immediate(r) => Poll::Ready(r),
_ => unreachable!(),
}
}
PromiseInner::Deferred(ref mut f) => f.as_mut().poll(cx),
}
}
}
#[cfg(feature = "rpc_try")]
impl<T> std::ops::Try for Promise<T, crate::Error> {
type Output = Promise<T, crate::Error>;
type Residual = Result<std::convert::Infallible, crate::Error>;
fn from_output(output: Self::Output) -> Self {
output
}
fn branch(self) -> std::ops::ControlFlow<Self::Residual, Self::Output> {
unimplemented!();
}
}
#[cfg(feature = "rpc_try")]
impl<T> std::ops::FromResidual for Promise<T, crate::Error> {
fn from_residual(residual: <Self as Try>::Residual) -> Self {
match residual {
Ok(_) => unimplemented!(),
Err(e) => Promise::err(e),
}
}
}
#[must_use]
pub struct RemotePromise<Results> where Results: Pipelined + for<'a> Owned<'a> + 'static {
pub promise: Promise<Response<Results>, crate::Error>,
pub pipeline: Results::Pipeline,
}
pub struct Response<Results> {
pub marker: PhantomData<Results>,
pub hook: Box<dyn ResponseHook>,
}
impl <Results> Response<Results>
where Results: Pipelined + for<'a> Owned<'a>
{
pub fn new(hook: Box<dyn ResponseHook>) -> Response<Results> {
Response { marker: PhantomData, hook }
}
pub fn get(&self) -> crate::Result<<Results as Owned<'_>>::Reader> {
self.hook.get()?.get_as()
}
}
pub struct Request<Params, Results> {
pub marker: PhantomData<(Params, Results)>,
pub hook: Box<dyn RequestHook>
}
impl <Params, Results> Request<Params, Results>
where Params: for<'a> Owned<'a>
{
pub fn new(hook: Box<dyn RequestHook>) -> Request <Params, Results> {
Request { hook, marker: PhantomData }
}
pub fn get(&mut self) -> <Params as Owned<'_>>::Builder {
self.hook.get().get_as().unwrap()
}
pub fn set(&mut self, from: <Params as Owned>::Reader) -> crate::Result<()> {
self.hook.get().set_as(from)
}
}
impl <Params, Results> Request <Params, Results>
where Results: Pipelined + for<'a> Owned<'a> + 'static + Unpin,
<Results as Pipelined>::Pipeline: FromTypelessPipeline
{
pub fn send(self) -> RemotePromise<Results> {
let RemotePromise {promise, pipeline, ..} = self.hook.send();
let typed_promise = Promise::from_future(
async move {
Ok(Response {hook: promise.await?.hook,
marker: PhantomData})
});
RemotePromise { promise: typed_promise,
pipeline: FromTypelessPipeline::new(pipeline)
}
}
}
pub struct Params<T> {
pub marker: PhantomData<T>,
pub hook: Box<dyn ParamsHook>,
}
impl <T> Params <T> {
pub fn new(hook: Box<dyn ParamsHook>) -> Params<T> {
Params { marker: PhantomData, hook }
}
pub fn get<'a>(&'a self) -> crate::Result<<T as Owned<'a>>::Reader>
where T: Owned<'a>
{
self.hook.get()?.get_as()
}
}
pub struct Results<T> {
pub marker: PhantomData<T>,
pub hook: Box<dyn ResultsHook>,
}
impl <T> Results<T>
where T: for<'a> Owned<'a>
{
pub fn new(hook: Box<dyn ResultsHook>) -> Results<T> {
Results { marker: PhantomData, hook }
}
pub fn get(&mut self) -> <T as Owned<'_>>::Builder {
self.hook.get().unwrap().get_as().unwrap()
}
pub fn set(&mut self, other: <T as Owned>::Reader) -> crate::Result<()>
{
self.hook.get().unwrap().set_as(other)
}
}
pub trait FromTypelessPipeline {
fn new (typeless: any_pointer::Pipeline) -> Self;
}
pub trait FromClientHook {
fn new(hook: Box<dyn ClientHook>) -> Self;
}
pub struct Client {
pub hook: Box<dyn ClientHook>
}
impl Client {
pub fn new(hook: Box<dyn ClientHook>) -> Client {
Client { hook }
}
pub fn new_call<Params, Results>(&self,
interface_id : u64,
method_id : u16,
size_hint : Option<MessageSize>)
-> Request<Params, Results> {
let typeless = self.hook.new_call(interface_id, method_id, size_hint);
Request { hook: typeless.hook, marker: PhantomData }
}
pub fn when_resolved(&self) -> Promise<(), Error> {
self.hook.when_resolved()
}
}
pub trait Server {
fn dispatch_call(&mut self, interface_id: u64, method_id: u16,
params: Params<any_pointer::Owned>,
results: Results<any_pointer::Owned>)
-> Promise<(), Error>;
}
pub trait FromServer<S> : FromClientHook {
type Dispatch: Server + 'static + core::ops::DerefMut<Target=S>;
fn from_server(s: S) -> Self::Dispatch;
}