use std::any::Any;
use std::collections::VecDeque;
use std::sync::Arc;
use crate::{Event, EventSchedule};
use crate::event::EventOnce;
#[derive(Debug,Default)]
pub struct Context{
input: Option<Box<dyn Any + Send + Sync + 'static>>,
events:VecDeque<Arc<dyn Event+Send+'static>>,
once_events:VecDeque<Box<dyn EventOnce+Send+'static>>,
is_abort:bool,
}
impl Context {
pub async fn new<T>(input:T,trigger:&[u8],schedule:&EventSchedule)->Self
where
T:Send+Sync+'static,
{
let mut this = Self{
input:Some(Box::new(input)),
events:VecDeque::new(),
once_events:VecDeque::new(),
is_abort:false,
};
this.init(trigger,schedule).await;
this
}
pub fn set_input<T:Send+Sync+'static>(&mut self,input:T){
self.input = Some(Box::new(input));
}
pub async fn init(&mut self,trigger:&[u8],schedule:&EventSchedule){
self.events = schedule.raw_load_events(trigger).await.into();
self.once_events = schedule.raw_load_once_events(trigger).into();
}
pub fn try_into_inner<T:'static>(&mut self)->Option<T>
{
let input = if let Some(ref input) = self.input{
if input.downcast_ref::<T>().is_some() {
self.input.take().unwrap()
}else{
return None
}
}else{
return None
};
Some(*input.downcast::<T>().unwrap())
}
pub async fn raw_next(&mut self)->anyhow::Result<()>{
loop {
if self.is_abort {
return Ok(())
}
if let Some(event) = self.events.pop_front() {
event.call(self).await?;
}else if let Some(event) = self.once_events.pop_front() {
event.call(self).await?;
}else{
break;
}
}
Ok(())
}
pub async fn next<T:Send+Sync+'static>(&mut self,input:T)->anyhow::Result<()>{
self.set_input(input);
self.raw_next().await
}
pub fn deref_fn<T:Any,Out>(&self,handle:impl FnOnce(Option<&T>)->Out)->Out{
if let Some(ref input) = self.input{
if let Some(input) = input.downcast_ref::<T>() {
return handle(Some(input))
}
}
handle(None)
}
pub fn deref_fn_mut<T:Any,Out>(&mut self,handle:impl FnOnce(Option<&mut T>)->Out)->Out{
if let Some(ref mut input) = self.input{
if let Some(input) = input.downcast_mut::<T>() {
return handle(Some(input))
}
}
handle(None)
}
}