forked from Orchid/orchid
Method refactor now compiles
This commit is contained in:
@@ -2,6 +2,8 @@ use std::any::{Any, TypeId, type_name};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{self, Debug};
|
||||
use std::future::Future;
|
||||
use std::io;
|
||||
use std::marker::PhantomData;
|
||||
use std::num::NonZeroU32;
|
||||
use std::ops::Deref;
|
||||
use std::pin::Pin;
|
||||
@@ -9,14 +11,15 @@ use std::rc::Rc;
|
||||
|
||||
use dyn_clone::{DynClone, clone_box};
|
||||
use futures::future::LocalBoxFuture;
|
||||
use futures::{AsyncRead, AsyncWrite, FutureExt, StreamExt, stream};
|
||||
use futures::{AsyncWrite, FutureExt, StreamExt, stream};
|
||||
use orchid_api_derive::Coding;
|
||||
use orchid_api_traits::{Coding, Decode, Encode, Request, enc_vec};
|
||||
use orchid_api_traits::{Coding, Decode, InHierarchy, Request, UnderRoot, enc_vec};
|
||||
use orchid_base::error::{OrcErrv, OrcRes, mk_errv, mk_errv_floating};
|
||||
use orchid_base::format::{FmtCtx, FmtUnit, Format, fmt, take_first};
|
||||
use orchid_base::interner::is;
|
||||
use orchid_base::location::Pos;
|
||||
use orchid_base::name::Sym;
|
||||
use orchid_base::reqnot::{Receipt, ReqHandle, ReqReader, ReqReaderExt};
|
||||
use trait_set::trait_set;
|
||||
|
||||
use crate::api;
|
||||
@@ -98,14 +101,17 @@ impl ForeignAtom {
|
||||
pub(crate) fn new(handle: Rc<ExprHandle>, atom: api::Atom, pos: Pos) -> Self {
|
||||
ForeignAtom { atom, expr: handle, pos }
|
||||
}
|
||||
pub async fn request<M: AtomMethod>(&self, m: M) -> Option<M::Response> {
|
||||
pub async fn request<R: Request + UnderRoot<Root: AtomMethod>>(
|
||||
&self,
|
||||
r: R,
|
||||
) -> Option<R::Response> {
|
||||
let rep = (request(api::Fwd(
|
||||
self.atom.clone(),
|
||||
Sym::parse(M::NAME).await.unwrap().tok().to_api(),
|
||||
enc_vec(&m),
|
||||
Sym::parse(<R as UnderRoot>::Root::NAME).await.unwrap().tok().to_api(),
|
||||
enc_vec(&r.into_root()),
|
||||
)))
|
||||
.await?;
|
||||
Some(M::Response::decode_slice(&mut &rep[..]))
|
||||
Some(R::Response::decode_slice(&mut &rep[..]))
|
||||
}
|
||||
pub async fn downcast<T: AtomicFeatures>(self) -> Result<TAtom<T>, NotTypAtom> {
|
||||
TAtom::downcast(self.ex().handle()).await
|
||||
@@ -154,23 +160,40 @@ impl Debug for NotTypAtom {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AtomMethod: Request + Coding {
|
||||
pub trait AtomMethod: Coding + InHierarchy {
|
||||
const NAME: &str;
|
||||
}
|
||||
pub trait Supports<M: AtomMethod>: AtomCard {
|
||||
fn handle(&self, req: M) -> impl Future<Output = <M as Request>::Response>;
|
||||
fn handle<'a>(
|
||||
&self,
|
||||
hand: Box<dyn ReqHandle<'a> + '_>,
|
||||
req: M,
|
||||
) -> impl Future<Output = io::Result<Receipt<'a>>>;
|
||||
}
|
||||
|
||||
trait_set! {
|
||||
trait AtomReqCb<A> = for<'a> Fn(
|
||||
&'a A,
|
||||
Pin<&'a mut dyn AsyncRead>,
|
||||
Pin<&'a mut dyn AsyncWrite>,
|
||||
) -> LocalBoxFuture<'a, ()>
|
||||
trait HandleAtomMethod<A> {
|
||||
fn handle<'a, 'b: 'a>(
|
||||
&'a self,
|
||||
atom: &'a A,
|
||||
req: Box<dyn ReqReader<'b> + 'a>,
|
||||
) -> LocalBoxFuture<'a, ()>;
|
||||
}
|
||||
struct AtomMethodHandler<M, A>(PhantomData<M>, PhantomData<A>);
|
||||
impl<M: AtomMethod, A: Supports<M>> HandleAtomMethod<A> for AtomMethodHandler<M, A> {
|
||||
fn handle<'a, 'b: 'a>(
|
||||
&'a self,
|
||||
a: &'a A,
|
||||
mut reader: Box<dyn ReqReader<'b> + 'a>,
|
||||
) -> LocalBoxFuture<'a, ()> {
|
||||
Box::pin(async {
|
||||
let req = reader.read_req::<M>().await.unwrap();
|
||||
let _ = Supports::<M>::handle(a, reader.finish().await, req).await.unwrap();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MethodSetBuilder<A: AtomCard> {
|
||||
handlers: Vec<(&'static str, Rc<dyn AtomReqCb<A>>)>,
|
||||
handlers: Vec<(&'static str, Rc<dyn HandleAtomMethod<A>>)>,
|
||||
}
|
||||
impl<A: AtomCard> MethodSetBuilder<A> {
|
||||
pub fn new() -> Self { Self { handlers: vec![] } }
|
||||
@@ -178,15 +201,7 @@ impl<A: AtomCard> MethodSetBuilder<A> {
|
||||
pub fn handle<M: AtomMethod>(mut self) -> Self
|
||||
where A: Supports<M> {
|
||||
assert!(!M::NAME.is_empty(), "AtomMethod::NAME cannoot be empty");
|
||||
self.handlers.push((
|
||||
M::NAME,
|
||||
Rc::new(move |a: &A, req: Pin<&mut dyn AsyncRead>, rep: Pin<&mut dyn AsyncWrite>| {
|
||||
async {
|
||||
Supports::<M>::handle(a, M::decode(req).await.unwrap()).await.encode(rep).await.unwrap()
|
||||
}
|
||||
.boxed_local()
|
||||
}),
|
||||
));
|
||||
self.handlers.push((M::NAME, Rc::new(AtomMethodHandler::<M, A>(PhantomData, PhantomData))));
|
||||
self
|
||||
}
|
||||
|
||||
@@ -201,20 +216,19 @@ impl<A: AtomCard> MethodSetBuilder<A> {
|
||||
}
|
||||
|
||||
pub struct MethodSet<A: AtomCard> {
|
||||
handlers: HashMap<Sym, Rc<dyn AtomReqCb<A>>>,
|
||||
handlers: HashMap<Sym, Rc<dyn HandleAtomMethod<A>>>,
|
||||
}
|
||||
impl<A: AtomCard> MethodSet<A> {
|
||||
pub(crate) async fn dispatch<'a>(
|
||||
&'a self,
|
||||
atom: &'a A,
|
||||
&self,
|
||||
atom: &'_ A,
|
||||
key: Sym,
|
||||
req: Pin<&'a mut dyn AsyncRead>,
|
||||
rep: Pin<&'a mut dyn AsyncWrite>,
|
||||
req: Box<dyn ReqReader<'a> + 'a>,
|
||||
) -> bool {
|
||||
match self.handlers.get(&key) {
|
||||
None => false,
|
||||
Some(handler) => {
|
||||
handler(atom, req, rep).await;
|
||||
handler.handle(atom, req).await;
|
||||
true
|
||||
},
|
||||
}
|
||||
@@ -243,13 +257,13 @@ impl<A: AtomicFeatures> TAtom<A> {
|
||||
},
|
||||
}
|
||||
}
|
||||
pub async fn request<M: AtomMethod>(&self, req: M) -> M::Response
|
||||
where A: Supports<M> {
|
||||
M::Response::decode_slice(
|
||||
pub async fn request<R: Request + UnderRoot<Root: AtomMethod>>(&self, req: R) -> R::Response
|
||||
where A: Supports<<R as UnderRoot>::Root> {
|
||||
R::Response::decode_slice(
|
||||
&mut &(request(api::Fwd(
|
||||
self.untyped.atom.clone(),
|
||||
Sym::parse(M::NAME).await.unwrap().tok().to_api(),
|
||||
enc_vec(&req),
|
||||
Sym::parse(<R as UnderRoot>::Root::NAME).await.unwrap().tok().to_api(),
|
||||
enc_vec(&req.into_root()),
|
||||
)))
|
||||
.await
|
||||
.unwrap()[..],
|
||||
@@ -278,12 +292,11 @@ pub trait AtomDynfo: 'static {
|
||||
fn call<'a>(&'a self, ctx: AtomCtx<'a>, arg: Expr) -> LocalBoxFuture<'a, GExpr>;
|
||||
fn call_ref<'a>(&'a self, ctx: AtomCtx<'a>, arg: Expr) -> LocalBoxFuture<'a, GExpr>;
|
||||
fn print<'a>(&'a self, ctx: AtomCtx<'a>) -> LocalBoxFuture<'a, FmtUnit>;
|
||||
fn handle_req<'a, 'b: 'a, 'c: 'a>(
|
||||
fn handle_req<'a>(
|
||||
&'a self,
|
||||
ctx: AtomCtx<'a>,
|
||||
key: Sym,
|
||||
req: Pin<&'b mut dyn AsyncRead>,
|
||||
rep: Pin<&'c mut dyn AsyncWrite>,
|
||||
req: Box<dyn ReqReader<'a> + 'a>,
|
||||
) -> LocalBoxFuture<'a, bool>;
|
||||
fn command<'a>(&'a self, ctx: AtomCtx<'a>) -> LocalBoxFuture<'a, OrcRes<Option<GExpr>>>;
|
||||
fn serialize<'a, 'b: 'a>(
|
||||
|
||||
Reference in New Issue
Block a user