forked from Orchid/orchid
196 lines
5.6 KiB
Rust
196 lines
5.6 KiB
Rust
use std::borrow::Cow;
|
|
use std::io;
|
|
use std::ops::Deref;
|
|
use std::pin::Pin;
|
|
use std::rc::Rc;
|
|
|
|
use futures::AsyncWrite;
|
|
use orchid_api_derive::{Coding, Hierarchy};
|
|
use orchid_api_traits::{Encode, Request};
|
|
use orchid_base::error::{OrcRes, mk_errv};
|
|
use orchid_base::format::{FmtCtx, FmtUnit};
|
|
use orchid_base::interner::{IStr, es, is};
|
|
use orchid_base::name::Sym;
|
|
use orchid_base::reqnot::{Receipt, ReqHandle, ReqHandleExt};
|
|
use orchid_base::sym;
|
|
use orchid_extension::atom::{AtomMethod, Atomic, MethodSetBuilder, Supports, TAtom};
|
|
use orchid_extension::atom_owned::{DeserializeCtx, OwnedAtom, OwnedVariant};
|
|
use orchid_extension::conv::TryFromExpr;
|
|
use orchid_extension::expr::Expr;
|
|
use orchid_extension::gen_expr::sym_ref;
|
|
|
|
use crate::std::protocol::types::{GetImpl, ProtocolMethod};
|
|
use crate::std::string::to_string::ToStringMethod;
|
|
|
|
#[derive(Copy, Clone, Debug, Coding, Hierarchy)]
|
|
pub struct StringGetValMethod;
|
|
impl Request for StringGetValMethod {
|
|
type Response = Rc<String>;
|
|
}
|
|
impl AtomMethod for StringGetValMethod {
|
|
const NAME: &str = "std::string_get_val";
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct StrAtom(Rc<String>);
|
|
impl Atomic for StrAtom {
|
|
type Variant = OwnedVariant;
|
|
type Data = ();
|
|
fn reg_reqs() -> MethodSetBuilder<Self> {
|
|
MethodSetBuilder::new()
|
|
.handle::<StringGetValMethod>()
|
|
.handle::<ToStringMethod>()
|
|
.handle::<ProtocolMethod>()
|
|
}
|
|
}
|
|
impl StrAtom {
|
|
pub fn new(str: Rc<String>) -> Self { Self(str) }
|
|
}
|
|
impl Deref for StrAtom {
|
|
type Target = str;
|
|
fn deref(&self) -> &Self::Target { &self.0 }
|
|
}
|
|
impl OwnedAtom for StrAtom {
|
|
type Refs = ();
|
|
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
|
async fn serialize(&self, sink: Pin<&mut (impl AsyncWrite + ?Sized)>) -> Self::Refs {
|
|
self.deref().encode(sink).await.unwrap()
|
|
}
|
|
async fn print_atom<'a>(&'a self, _: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
|
|
format!("{:?}", &*self.0).into()
|
|
}
|
|
async fn deserialize(mut ctx: impl DeserializeCtx, _: Self::Refs) -> Self {
|
|
Self::new(Rc::new(ctx.read::<String>().await))
|
|
}
|
|
}
|
|
impl Supports<StringGetValMethod> for StrAtom {
|
|
async fn handle<'a>(
|
|
&self,
|
|
hand: Box<dyn ReqHandle<'a> + '_>,
|
|
req: StringGetValMethod,
|
|
) -> io::Result<Receipt<'a>> {
|
|
hand.reply(&req, &self.0).await
|
|
}
|
|
}
|
|
impl Supports<ToStringMethod> for StrAtom {
|
|
async fn handle<'a>(
|
|
&self,
|
|
hand: Box<dyn ReqHandle<'a> + '_>,
|
|
req: ToStringMethod,
|
|
) -> io::Result<Receipt<'a>> {
|
|
hand.reply(&req, &self.0).await
|
|
}
|
|
}
|
|
impl Supports<ProtocolMethod> for StrAtom {
|
|
async fn handle<'a>(
|
|
&self,
|
|
hand: Box<dyn ReqHandle<'a> + '_>,
|
|
req: ProtocolMethod,
|
|
) -> io::Result<Receipt<'a>> {
|
|
match req {
|
|
ProtocolMethod::GetTagId(req) => hand.reply(&req, &sym!(std::string::StrAtom).to_api()).await,
|
|
ProtocolMethod::GetImpl(ref req @ GetImpl(key)) => {
|
|
let name = Sym::from_api(key).await;
|
|
let val = if name == sym!(std::ops::add) {
|
|
sym_ref(sym!(std::string::concat))
|
|
} else {
|
|
return hand.reply(req, &None).await;
|
|
};
|
|
hand.reply(req, &Some(val.create().await.serialize().await)).await
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct IntStrAtom(pub(crate) IStr);
|
|
impl Atomic for IntStrAtom {
|
|
type Variant = OwnedVariant;
|
|
type Data = orchid_api::TStr;
|
|
fn reg_reqs() -> MethodSetBuilder<Self> {
|
|
MethodSetBuilder::new().handle::<ProtocolMethod>().handle::<ToStringMethod>()
|
|
}
|
|
}
|
|
impl From<IStr> for IntStrAtom {
|
|
fn from(value: IStr) -> Self { Self(value) }
|
|
}
|
|
impl OwnedAtom for IntStrAtom {
|
|
type Refs = ();
|
|
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(self.0.to_api()) }
|
|
async fn print_atom<'a>(&'a self, _: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
|
|
format!("{:?}i", &*self.0).into()
|
|
}
|
|
async fn serialize(&self, write: Pin<&mut (impl AsyncWrite + ?Sized)>) {
|
|
self.0.encode(write).await.unwrap()
|
|
}
|
|
async fn deserialize(mut dctx: impl DeserializeCtx, _: ()) -> Self {
|
|
let s = dctx.decode::<String>().await;
|
|
Self(is(&s).await)
|
|
}
|
|
}
|
|
impl TryFromExpr for IntStrAtom {
|
|
async fn try_from_expr(expr: Expr) -> OrcRes<Self> {
|
|
Ok(IntStrAtom(es(TAtom::<IntStrAtom>::try_from_expr(expr).await?.value).await))
|
|
}
|
|
}
|
|
impl Supports<ToStringMethod> for IntStrAtom {
|
|
async fn handle<'a>(
|
|
&self,
|
|
hand: Box<dyn ReqHandle<'a> + '_>,
|
|
req: ToStringMethod,
|
|
) -> io::Result<Receipt<'a>> {
|
|
hand.reply(&req, &self.0.rc()).await
|
|
}
|
|
}
|
|
impl Supports<ProtocolMethod> for IntStrAtom {
|
|
async fn handle<'a>(
|
|
&self,
|
|
hand: Box<dyn ReqHandle<'a> + '_>,
|
|
req: ProtocolMethod,
|
|
) -> io::Result<Receipt<'a>> {
|
|
match req {
|
|
ProtocolMethod::GetTagId(req) =>
|
|
hand.reply(&req, &sym!(std::string::IntStrAtom).to_api()).await,
|
|
ProtocolMethod::GetImpl(ref req @ GetImpl(key)) => {
|
|
let name = Sym::from_api(key).await;
|
|
let val = if name == sym!(std::ops::add) {
|
|
sym_ref(sym!(std::string::concat))
|
|
} else {
|
|
return hand.reply(req, &None).await;
|
|
};
|
|
hand.reply(req, &Some(val.create().await.serialize().await)).await
|
|
},
|
|
}
|
|
}
|
|
}
|
|
#[derive(Clone)]
|
|
pub struct OrcString {
|
|
kind: OrcStringKind,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub enum OrcStringKind {
|
|
Val(TAtom<StrAtom>),
|
|
Int(TAtom<IntStrAtom>),
|
|
}
|
|
impl OrcString {
|
|
pub async fn get_string(&self) -> Rc<String> {
|
|
match &self.kind {
|
|
OrcStringKind::Int(tok) => es(**tok).await.rc(),
|
|
OrcStringKind::Val(atom) => atom.request(StringGetValMethod).await,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TryFromExpr for OrcString {
|
|
async fn try_from_expr(expr: Expr) -> OrcRes<OrcString> {
|
|
if let Ok(v) = TAtom::<StrAtom>::try_from_expr(expr.clone()).await {
|
|
return Ok(OrcString { kind: OrcStringKind::Val(v) });
|
|
}
|
|
match TAtom::<IntStrAtom>::try_from_expr(expr).await {
|
|
Ok(t) => Ok(OrcString { kind: OrcStringKind::Int(t) }),
|
|
Err(e) => Err(mk_errv(is("A string was expected").await, "", e.pos_iter())),
|
|
}
|
|
}
|
|
}
|