Where on_<event> setters are optional, but if used they should be passed arguments of type HandlerPtr<event_type>, e.g. the on_insert_block setter takes an argument of type HandlerPtr<InsertBlockEvent>, which is the same as Box<dyn Fn(&InsertBlockEvent) + Send>. Therefore, the argument must be a pointer to the closure, rather than the closure itself (the popinter can be created with Box::new(handler) where handler is a closure that implements Fn(&event_type)). This is because Fn(&T) is a trait which can be implemented by different types thus with size unknown at compile time, and so cannot be stored in a struct's field which should have a size known at compile time.
Note that even though we pass only one closure pointer per event, the closure can in fact be defined to combine multiple different closures. Hence, passing one closure can be equivalent to passing multiple closures.
However, internally the handlers for each event are stored as a vector Vec<HandlerPtr<event_type>> which can include (1) (optionally) a custom handler passed to the replica builder, and (2) (optionally, if log_events is set to true in configuration) a predefined log handler for the event (from logging.rs). This is to avoid combining the user-provided closure with the logging closure by dereferencing ("unboxing") the user-provided closure, just to "box" the resulting closure again after combing the functionalities of the two.
Other changes:
Modified tests to make them compatible with the ed25519-dalek update, event handlers and the builder pattern for replica (this required including the rand_core feature for ed25519-dalek in Cargo.toml, and adding rand_core to dependencies)
Minor fixes, switch to using log::info in all loggers in logging.rs
Implemented a builder pattern for replica, now a replica can be started as follows:
Where
on_<event>
setters are optional, but if used they should be passed arguments of typeHandlerPtr<event_type>
, e.g. theon_insert_block
setter takes an argument of typeHandlerPtr<InsertBlockEvent>
, which is the same asBox<dyn Fn(&InsertBlockEvent) + Send>
. Therefore, the argument must be a pointer to the closure, rather than the closure itself (the popinter can be created withBox::new(handler)
where handler is a closure that implementsFn(&event_type)
). This is becauseFn(&T)
is a trait which can be implemented by different types thus with size unknown at compile time, and so cannot be stored in a struct's field which should have a size known at compile time.Note that even though we pass only one closure pointer per event, the closure can in fact be defined to combine multiple different closures. Hence, passing one closure can be equivalent to passing multiple closures.
However, internally the handlers for each event are stored as a vector
Vec<HandlerPtr<event_type>>
which can include (1) (optionally) a custom handler passed to the replica builder, and (2) (optionally, iflog_events
is set totrue
in configuration) a predefined log handler for the event (fromlogging.rs
). This is to avoid combining the user-provided closure with the logging closure by dereferencing ("unboxing") the user-provided closure, just to "box" the resulting closure again after combing the functionalities of the two.Other changes:
ed25519-dalek
update, event handlers and the builder pattern for replica (this required including therand_core
feature fored25519-dalek
inCargo.toml
, and addingrand_core
to dependencies)log::info
in all loggers inlogging.rs