forked from Orchid/orchid
task_local context over context objects
- interner impls logically separate from API in orchid-base (default host interner still in base for testing) - error reporting, logging, and a variety of other features passed down via context in extension, not yet in host to maintain library-ish profile, should consider options - no global spawn mechanic, the host has a spawn function but extensions only get a stash for enqueuing async work in sync callbacks which is then explicitly, manually, and with strict order popped and awaited - still deadlocks nondeterministically for some ungodly reason
This commit is contained in:
@@ -1,73 +1,48 @@
|
||||
use std::borrow::Borrow;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::rc::Rc;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use orchid_api_traits::Coding;
|
||||
use orchid_base::interner::{IStr, IStrHandle, IStrv, IStrvHandle};
|
||||
use futures::future::{LocalBoxFuture, join_all, ready};
|
||||
use itertools::Itertools;
|
||||
use orchid_base::interner::local_interner::{Int, StrBranch, StrvBranch};
|
||||
use orchid_base::interner::{IStr, IStrv, InternerSrv};
|
||||
|
||||
use crate::api;
|
||||
use crate::entrypoint::request;
|
||||
|
||||
trait Branch: 'static {
|
||||
type Token: Clone + Copy + Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Coding + 'static;
|
||||
type Data: 'static + Borrow<Self::Borrow>;
|
||||
type Borrow: ToOwned<Owned = Self::Data> + ?Sized;
|
||||
type Handle: AsRef<Self::Borrow>;
|
||||
type Interned: Clone;
|
||||
fn mk_interned(t: Self::Token, h: Rc<Self::Handle>) -> Self::Interned;
|
||||
#[derive(Default)]
|
||||
struct ExtInterner {
|
||||
str: Int<StrBranch>,
|
||||
strv: Int<StrvBranch>,
|
||||
}
|
||||
impl InternerSrv for ExtInterner {
|
||||
fn is<'a>(&'a self, v: &'a str) -> LocalBoxFuture<'a, IStr> {
|
||||
match self.str.i(v) {
|
||||
Ok(i) => Box::pin(ready(i)),
|
||||
Err(e) => Box::pin(async { e.set_if_empty(request(api::InternStr(v.to_owned())).await) }),
|
||||
}
|
||||
}
|
||||
fn es(&self, t: api::TStr) -> LocalBoxFuture<'_, IStr> {
|
||||
match self.str.e(t) {
|
||||
Ok(i) => Box::pin(ready(i)),
|
||||
Err(e) => Box::pin(async move { e.set_if_empty(Rc::new(request(api::ExternStr(t)).await)) }),
|
||||
}
|
||||
}
|
||||
fn iv<'a>(&'a self, v: &'a [IStr]) -> LocalBoxFuture<'a, IStrv> {
|
||||
match self.strv.i(v) {
|
||||
Ok(i) => Box::pin(ready(i)),
|
||||
Err(e) => Box::pin(async {
|
||||
e.set_if_empty(request(api::InternStrv(v.iter().map(|is| is.to_api()).collect_vec())).await)
|
||||
}),
|
||||
}
|
||||
}
|
||||
fn ev(&self, t: orchid_api::TStrv) -> LocalBoxFuture<'_, IStrv> {
|
||||
match self.strv.e(t) {
|
||||
Ok(i) => Box::pin(ready(i)),
|
||||
Err(e) => Box::pin(async move {
|
||||
let tstr_v = request(api::ExternStrv(t)).await;
|
||||
e.set_if_empty(Rc::new(join_all(tstr_v.into_iter().map(|t| self.es(t))).await))
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct StrBranch;
|
||||
impl Branch for StrBranch {
|
||||
type Data = String;
|
||||
type Token = api::TStr;
|
||||
type Borrow = str;
|
||||
type Handle = Handle<Self>;
|
||||
type Interned = IStr;
|
||||
fn mk_interned(t: Self::Token, h: Rc<Self::Handle>) -> Self::Interned { IStr(t, h) }
|
||||
}
|
||||
struct StrvBranch;
|
||||
impl Branch for StrvBranch {
|
||||
type Data = Vec<IStr>;
|
||||
type Token = api::TStrv;
|
||||
type Borrow = [IStr];
|
||||
type Handle = Handle<Self>;
|
||||
type Interned = IStrv;
|
||||
fn mk_interned(t: Self::Token, h: Rc<Self::Handle>) -> Self::Interned { IStrv(t, h) }
|
||||
}
|
||||
|
||||
struct Data<B: Branch> {
|
||||
token: B::Token,
|
||||
data: Rc<B::Data>,
|
||||
}
|
||||
|
||||
struct Handle<B: Branch> {
|
||||
data: Rc<Data<B>>,
|
||||
parent: Weak<RefCell<IntData<B>>>,
|
||||
}
|
||||
impl IStrHandle for Handle<StrBranch> {}
|
||||
impl AsRef<str> for Handle<StrBranch> {
|
||||
fn as_ref(&self) -> &str { self.data.data.as_ref().as_ref() }
|
||||
}
|
||||
impl IStrvHandle for Handle<StrvBranch> {}
|
||||
impl AsRef<[IStr]> for Handle<StrvBranch> {
|
||||
fn as_ref(&self) -> &[IStr] { self.data.data.as_ref().as_ref() }
|
||||
}
|
||||
|
||||
struct Rec<B: Branch> {
|
||||
handle: Weak<B::Handle>,
|
||||
data: Rc<Data<B>>,
|
||||
}
|
||||
|
||||
struct IntData<B: Branch> {
|
||||
by_tok: HashMap<B::Token, Rec<B>>,
|
||||
by_data: HashMap<Rc<B::Data>, Rec<B>>,
|
||||
}
|
||||
impl<B: Branch> IntData<B> {
|
||||
async fn i(&mut self, q: &B::Borrow) -> B::Interned { todo!() }
|
||||
async fn e(&mut self, q: &B::Token) -> B::Interned { todo!() }
|
||||
}
|
||||
|
||||
struct Int<B: Branch>(Rc<RefCell<IntData<B>>>);
|
||||
pub fn new_interner() -> Rc<dyn InternerSrv> { Rc::<ExtInterner>::default() }
|
||||
|
||||
Reference in New Issue
Block a user