diff --git a/crown/src/drivers/mod.rs b/crown/src/drivers/mod.rs index 97b66ee..c8d60fe 100644 --- a/crown/src/drivers/mod.rs +++ b/crown/src/drivers/mod.rs @@ -4,3 +4,4 @@ pub mod http; pub mod markdown; pub mod npc; pub mod one_punch; +pub mod timer; diff --git a/crown/src/drivers/timer.rs b/crown/src/drivers/timer.rs new file mode 100644 index 0000000..5d01a35 --- /dev/null +++ b/crown/src/drivers/timer.rs @@ -0,0 +1,24 @@ +use crate::nockapp::driver::*; +use crate::noun::slab::NounSlab; +use crate::utils::make_tas; +use std::time::Duration; +use sword::noun::{D, T}; +use tokio::time; + +pub fn make_timer_driver(interval_secs: u64) -> IODriverFn { + make_driver(move |handle| async move { + let mut timer_interval = time::interval(Duration::from_secs(interval_secs)); + + loop { + tokio::select! { + _ = timer_interval.tick() => { + let mut timer_slab = NounSlab::new(); + let timer_tas = make_tas(&mut timer_slab, "timer").as_noun(); + let timer_noun = T(&mut timer_slab, &[timer_tas, D(0)]); + timer_slab.set_root(timer_noun); + handle.poke(timer_slab).await?; + } + } + } + }) +} diff --git a/crown/src/lib.rs b/crown/src/lib.rs index 7332b93..fe97830 100644 --- a/crown/src/lib.rs +++ b/crown/src/lib.rs @@ -30,6 +30,7 @@ pub use drivers::http::http as http_driver; pub use drivers::markdown::markdown as markdown_driver; pub use drivers::npc::{npc_client as npc_client_driver, npc_listener as npc_listener_driver}; pub use drivers::one_punch::one_punch_man as one_punch_driver; +pub use drivers::timer::make_timer_driver as timer_driver; use std::path::PathBuf; diff --git a/crown/src/utils/mod.rs b/crown/src/utils/mod.rs index e6393b1..e8419a9 100644 --- a/crown/src/utils/mod.rs +++ b/crown/src/utils/mod.rs @@ -1,5 +1,6 @@ pub mod bytes; pub mod error; +pub mod scry; pub mod slogger; use byteorder::{LittleEndian, ReadBytesExt}; diff --git a/crown/src/utils/scry.rs b/crown/src/utils/scry.rs new file mode 100644 index 0000000..b5ee59a --- /dev/null +++ b/crown/src/utils/scry.rs @@ -0,0 +1,50 @@ +use either::{Left, Right}; +use sword::noun::Noun; + +pub enum ScryResult { + BadPath, // ~ + Nothing, // [~ ~] + Some(Noun), // [~ ~ foo] + Invalid, // anything that isn't one of the above +} + +impl From<&Noun> for ScryResult { + fn from(noun: &Noun) -> ScryResult { + match noun.as_either_atom_cell() { + Left(atom) => { + let Ok(direct) = atom.as_direct() else { + return ScryResult::Invalid; + }; + if direct.data() == 0 { + return ScryResult::BadPath; + } + } + Right(cell) => { + let Ok(head) = cell.head().as_direct() else { + return ScryResult::Invalid; + }; + if head.data() == 0 { + match cell.tail().as_either_atom_cell() { + Left(atom) => { + let Ok(direct) = atom.as_direct() else { + return ScryResult::Invalid; + }; + if direct.data() == 0 { + return ScryResult::Nothing; + } + } + Right(tail) => { + let Ok(tail_head) = tail.head().as_direct() else { + return ScryResult::Invalid; + }; + if tail_head.data() == 0 { + return ScryResult::Some(tail.tail()); + } + } + } + } + } + } + ScryResult::Invalid + } +}