forked from Orchid/orchid
118 lines
4.0 KiB
Rust
118 lines
4.0 KiB
Rust
use std::borrow::Cow;
|
|
use std::io;
|
|
use std::time::Instant;
|
|
|
|
use chrono::TimeDelta;
|
|
use never::Never;
|
|
use orchid_api::ExprTicket;
|
|
use orchid_api_derive::{Coding, Hierarchy};
|
|
use orchid_api_traits::Request;
|
|
use orchid_base::{Numeric, OrcRes, Receipt, ReqHandle, ReqHandleExt};
|
|
use orchid_extension::gen_expr::{GExpr, call, new_atom};
|
|
use orchid_extension::std_reqs::{AsDuration, RunCommand};
|
|
use orchid_extension::tree::{GenMember, fun, prefix};
|
|
use orchid_extension::{
|
|
Atomic, Expr, MethodSetBuilder, OwnedAtom, OwnedVariant, Supports, TAtom, ThinAtom, ThinVariant,
|
|
ToExpr, TryFromExpr, sys_req,
|
|
};
|
|
use ordered_float::NotNan;
|
|
|
|
use crate::std::std_system::StdReq;
|
|
use crate::{Float, Int, Num, StdSystem};
|
|
|
|
#[derive(Clone, Copy, Debug, Coding, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Hierarchy)]
|
|
#[extends(StdReq)]
|
|
pub struct CreateDT(pub OrcDT);
|
|
impl Request for CreateDT {
|
|
type Response = ExprTicket;
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Coding, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub struct OrcDT(pub TimeDelta);
|
|
impl Atomic for OrcDT {
|
|
type Variant = ThinVariant;
|
|
type Data = Self;
|
|
}
|
|
impl ThinAtom for OrcDT {}
|
|
impl ToExpr for OrcDT {
|
|
async fn to_gen(self) -> GExpr {
|
|
Expr::deserialize(sys_req::<StdSystem, _>(CreateDT(self)).await).await.to_gen().await
|
|
}
|
|
}
|
|
impl TryFromExpr for OrcDT {
|
|
async fn try_from_expr(expr: Expr) -> OrcRes<Self> {
|
|
Ok(TAtom::<OrcDT>::try_from_expr(expr).await?.value)
|
|
}
|
|
}
|
|
impl Supports<AsDuration> for OrcDT {
|
|
async fn handle<'a>(
|
|
&self,
|
|
hand: Box<dyn ReqHandle<'a> + '_>,
|
|
req: AsDuration,
|
|
) -> std::io::Result<Receipt<'a>> {
|
|
hand.reply(&req, &self.0.to_std().unwrap()).await
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct InstantAtom(Instant);
|
|
impl Atomic for InstantAtom {
|
|
type Variant = OwnedVariant;
|
|
type Data = ();
|
|
}
|
|
impl OwnedAtom for InstantAtom {
|
|
type Refs = Never;
|
|
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
struct Now(Expr);
|
|
impl Atomic for Now {
|
|
type Variant = OwnedVariant;
|
|
type Data = ();
|
|
fn reg_methods() -> MethodSetBuilder<Self> { MethodSetBuilder::new().handle::<RunCommand>() }
|
|
}
|
|
impl OwnedAtom for Now {
|
|
type Refs = Never;
|
|
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
|
}
|
|
impl Supports<RunCommand> for Now {
|
|
async fn handle<'a>(
|
|
&self,
|
|
hand: Box<dyn ReqHandle<'a> + '_>,
|
|
req: RunCommand,
|
|
) -> io::Result<Receipt<'a>> {
|
|
let cont = call(self.0.clone(), new_atom(InstantAtom(Instant::now()))).await.serialize().await;
|
|
hand.reply(&req, &Some(cont)).await
|
|
}
|
|
}
|
|
|
|
pub fn gen_time_lib() -> Vec<GenMember> {
|
|
prefix("std::time", [
|
|
fun(true, "weeks", async |amount: Int| new_atom(OrcDT(TimeDelta::weeks(amount.0)))),
|
|
fun(true, "num_weeks", async |amount: TAtom<OrcDT>| Int(amount.0.num_weeks())),
|
|
fun(true, "days", async |amount: Int| new_atom(OrcDT(TimeDelta::days(amount.0)))),
|
|
fun(true, "num_days", async |amount: TAtom<OrcDT>| Int(amount.0.num_days())),
|
|
fun(true, "hours", async |amount: Int| new_atom(OrcDT(TimeDelta::hours(amount.0)))),
|
|
fun(true, "num_hours", async |amount: TAtom<OrcDT>| Int(amount.0.num_hours())),
|
|
fun(true, "minutes", async |amount: Int| new_atom(OrcDT(TimeDelta::minutes(amount.0)))),
|
|
fun(true, "num_minutes", async |amount: TAtom<OrcDT>| Int(amount.0.num_minutes())),
|
|
fun(true, "secs", async |amount: Num| {
|
|
new_atom(OrcDT(match amount.0 {
|
|
Numeric::Int(i) => TimeDelta::seconds(i),
|
|
Numeric::Float(f) =>
|
|
TimeDelta::new(f.floor() as i64, (f.fract() * 1_000_000_000_f64).floor() as u32).unwrap(),
|
|
}))
|
|
}),
|
|
fun(true, "num_secs", async |amount: TAtom<OrcDT>| Int(amount.0.num_seconds())),
|
|
fun(true, "as_secs", async |amount: TAtom<OrcDT>| {
|
|
Float(NotNan::new(amount.0.as_seconds_f64()).unwrap())
|
|
}),
|
|
fun(true, "milis", async |amount: Int| new_atom(OrcDT(TimeDelta::milliseconds(amount.0)))),
|
|
fun(true, "num_millis", async |amount: TAtom<OrcDT>| Int(amount.0.num_milliseconds())),
|
|
fun(true, "nanos", async |amount: Int| new_atom(OrcDT(TimeDelta::nanoseconds(amount.0)))),
|
|
fun(true, "num_nanos", async |amount: TAtom<OrcDT>| Int(amount.0.num_nanoseconds().unwrap())),
|
|
fun(true, "now", async |cb: Expr| new_atom(Now(cb))),
|
|
])
|
|
}
|