Files
orchid/orchid-std/src/std/time.rs
2026-03-27 23:50:58 +01:00

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))),
])
}