Files
orchid/orchid-std/src/std/option.rs
Lawrence Bethlenfalvy 0909524dee
Some checks failed
Rust / build (push) Failing after 3m52s
Compiles again after command subsystem
terrified to start testing
2026-03-27 23:50:58 +01:00

72 lines
2.2 KiB
Rust

use std::borrow::Cow;
use std::pin::Pin;
use futures::AsyncWrite;
use orchid_api_traits::Encode;
use orchid_base::{is, mk_errv, sym};
use orchid_extension::{ToExpr, TryFromExpr};
use orchid_extension::{Expr, ExprHandle};
use orchid_extension::gen_expr::{call, new_atom};
use orchid_extension::tree::{GenMember, cnst, fun, prefix};
use orchid_extension::{Atomic, DeserializeCtx, ForeignAtom, OwnedAtom, OwnedVariant, TAtom};
use crate::{OrcString, api};
#[derive(Clone)]
pub struct OptAtom(Option<Expr>);
impl Atomic for OptAtom {
type Data = Option<api::ExprTicket>;
type Variant = OwnedVariant;
}
impl OwnedAtom for OptAtom {
type Refs = Vec<Expr>;
async fn val(&self) -> Cow<'_, Self::Data> {
Cow::Owned(self.0.as_ref().map(|ex| ex.handle().ticket()))
}
async fn deserialize(mut ctx: impl DeserializeCtx, refs: Self::Refs) -> Self {
Self(ctx.read::<bool>().await.then(|| refs.into_iter().next().unwrap()))
}
async fn serialize(&self, write: Pin<&mut (impl AsyncWrite + ?Sized)>) -> Self::Refs {
self.0.is_some().encode(write).await.unwrap();
self.0.iter().cloned().collect()
}
}
pub struct OrcOpt<T>(pub Option<T>);
impl<T: TryFromExpr> TryFromExpr for OrcOpt<T> {
async fn try_from_expr(expr: Expr) -> orchid_base::OrcRes<Self> {
let atom = TAtom::<OptAtom>::try_from_expr(expr).await?;
match atom.value {
None => Ok(OrcOpt(None)),
Some(tk) => Ok(OrcOpt(Some(
T::try_from_expr(Expr::from_handle(ExprHandle::from_ticket(tk).await)).await?,
))),
}
}
}
impl<T: ToExpr + 'static> ToExpr for OrcOpt<T> {
async fn to_gen(self) -> orchid_extension::gen_expr::GExpr {
if let Some(val) = self.0 {
call(sym!(std::option::some), val).await
} else {
sym!(std::option::none).to_gen().await
}
}
}
pub fn gen_option_lib() -> Vec<GenMember> {
prefix("std::option", [
cnst(true, "none", new_atom(OptAtom(None))),
fun(true, "some", async |ex: Expr| new_atom(OptAtom(Some(ex)))),
fun(true, "expect", async |opt: ForeignAtom, msg: OrcString| {
match OrcOpt::try_from_expr(opt.clone().ex()).await? {
OrcOpt(Some(ex)) => Ok::<Expr, _>(ex),
OrcOpt(None) =>
Err(mk_errv(is("Unwrapped std::option::none").await, msg.get_string().await.as_str(), [
opt.pos(),
])),
}
}),
])
}