use crate::actor::*; use crate::error::Error; use preserves::value::Map; use std::sync::Arc; use std::marker::PhantomData; pub struct During(Map>); pub type DuringRetractionHandler = Box ActorResult>; pub type DuringResult = Result>, Error>; pub struct DuringEntity where M: 'static + Send, E: 'static + Send, Fa: 'static + Send + FnMut(&mut E, &mut Activation, M) -> DuringResult, Fm: 'static + Send + FnMut(&mut E, &mut Activation, M) -> ActorResult, Fs: 'static + Send + FnMut(&mut E, &mut Activation) -> ActorResult, Fx: 'static + Send + FnMut(&mut E, &mut Activation, &Arc), { state: E, assertion_handler: Option, message_handler: Option, stop_handler: Option, exit_handler: Option, during: During, phantom: PhantomData, } impl During { pub fn new() -> Self { During(Map::new()) } pub fn await_retraction ActorResult>( &mut self, h: Handle, f: F, ) -> ActorResult { self.0.insert(h, Box::new(f)); Ok(()) } pub fn retract(&mut self, h: Handle) -> DuringRetractionHandler { self.0.remove(&h).unwrap_or_else(|| Box::new(|_, _| Ok(()))) } } pub fn entity( state: E ) -> DuringEntity DuringResult, fn (&mut E, &mut Activation, M) -> ActorResult, fn (&mut E, &mut Activation) -> ActorResult, fn (&mut E, &mut Activation, &Arc)> where E: 'static + Send, { DuringEntity::new(state, None, None, None, None) } impl DuringEntity where M: 'static + Send, E: 'static + Send, Fa: 'static + Send + FnMut(&mut E, &mut Activation, M) -> DuringResult, Fm: 'static + Send + FnMut(&mut E, &mut Activation, M) -> ActorResult, Fs: 'static + Send + FnMut(&mut E, &mut Activation) -> ActorResult, Fx: 'static + Send + FnMut(&mut E, &mut Activation, &Arc), { pub fn new( state: E, assertion_handler: Option, message_handler: Option, stop_handler: Option, exit_handler: Option, ) -> Self { DuringEntity { state, assertion_handler, message_handler, stop_handler, exit_handler, during: During::new(), phantom: PhantomData, } } pub fn on_asserted(self, assertion_handler: Fa1) -> DuringEntity where Fa1: 'static + Send + FnMut(&mut E, &mut Activation, M) -> DuringResult, { DuringEntity { state: self.state, assertion_handler: Some(assertion_handler), message_handler: self.message_handler, stop_handler: self.stop_handler, exit_handler: self.exit_handler, during: self.during, phantom: self.phantom, } } pub fn on_asserted_facet( self, mut assertion_handler: Fa1, ) -> DuringEntity DuringResult>, Fm, Fs, Fx> where Fa1: 'static + Send + FnMut(&mut E, &mut Activation, M) -> ActorResult { self.on_asserted(Box::new(move |state, t, a| { let facet_id = t.facet(|t| { // Prevent inertness check because we have a bounded lifetime anyway. This // allows e.g. facets containing Supervisors to Just Work (they go momentarily // inert when their supervisee exits). let _ = t.prevent_inert_check(); assertion_handler(state, t, a) })?; Ok(Some(Box::new(move |_state, t| Ok(t.stop_facet(facet_id))))) })) } pub fn on_message(self, message_handler: Fm1) -> DuringEntity where Fm1: 'static + Send + FnMut(&mut E, &mut Activation, M) -> ActorResult, { DuringEntity { state: self.state, assertion_handler: self.assertion_handler, message_handler: Some(message_handler), stop_handler: self.stop_handler, exit_handler: self.exit_handler, during: self.during, phantom: self.phantom, } } pub fn on_stop(self, stop_handler: Fs1) -> DuringEntity where Fs1: 'static + Send + FnMut(&mut E, &mut Activation) -> ActorResult, { DuringEntity { state: self.state, assertion_handler: self.assertion_handler, message_handler: self.message_handler, stop_handler: Some(stop_handler), exit_handler: self.exit_handler, during: self.during, phantom: self.phantom, } } pub fn on_exit(self, exit_handler: Fx1) -> DuringEntity where Fx1: 'static + Send + FnMut(&mut E, &mut Activation, &Arc), { DuringEntity { state: self.state, assertion_handler: self.assertion_handler, message_handler: self.message_handler, stop_handler: self.stop_handler, exit_handler: Some(exit_handler), during: self.during, phantom: self.phantom, } } pub fn create(self, t: &mut Activation) -> Arc> { let should_register_stop_action = self.stop_handler.is_some(); let should_register_exit_hook = self.exit_handler.is_some(); let r = t.create(self); if should_register_stop_action { t.on_stop_notify(&r); } if should_register_exit_hook { t.add_exit_hook(&r); } r } } impl DuringEntity where E: 'static + Send, Fa: 'static + Send + FnMut(&mut E, &mut Activation, AnyValue) -> DuringResult, Fm: 'static + Send + FnMut(&mut E, &mut Activation, AnyValue) -> ActorResult, Fs: 'static + Send + FnMut(&mut E, &mut Activation) -> ActorResult, Fx: 'static + Send + FnMut(&mut E, &mut Activation, &Arc), { pub fn create_cap(self, t: &mut Activation) -> Arc { Cap::new(&self.create(t)) } } impl Entity for DuringEntity where M: Send, E: 'static + Send, Fa: 'static + Send + FnMut(&mut E, &mut Activation, M) -> DuringResult, Fm: 'static + Send + FnMut(&mut E, &mut Activation, M) -> ActorResult, Fs: 'static + Send + FnMut(&mut E, &mut Activation) -> ActorResult, Fx: 'static + Send + FnMut(&mut E, &mut Activation, &Arc), { fn assert(&mut self, t: &mut Activation, a: M, h: Handle) -> ActorResult { match &mut self.assertion_handler { Some(handler) => match handler(&mut self.state, t, a)? { Some(f) => self.during.await_retraction(h, f), None => Ok(()) } None => Ok(()), } } fn retract(&mut self, t: &mut Activation, h: Handle) -> ActorResult { self.during.retract(h)(&mut self.state, t) } fn message(&mut self, t: &mut Activation, m: M) -> ActorResult { match &mut self.message_handler { Some(handler) => handler(&mut self.state, t, m), None => Ok(()), } } fn stop(&mut self, t: &mut Activation) -> ActorResult { match &mut self.stop_handler { Some(handler) => handler(&mut self.state, t), None => Ok(()), } } fn exit_hook(&mut self, t: &mut Activation, exit_status: &Arc) { if let Some(handler) = &mut self.exit_handler { handler(&mut self.state, t, exit_status); } } }