use crate::AsAnyMut; use crate::AsAnyRef; use crate::Events; use crate::WithLen; use err::Error; use netpod::log::*; use netpod::BinnedRangeEnum; use netpod::SeriesRange; use serde::Serialize; use std::any::Any; use std::fmt; // TODO check usage of this trait pub trait ToJsonBytes { fn to_json_bytes(&self) -> Result, Error>; } // TODO check usage of this trait pub trait ToJsonResult: erased_serde::Serialize + fmt::Debug + AsAnyRef + AsAnyMut + Send { fn to_json_result(&self) -> Result, Error>; } erased_serde::serialize_trait_object!(ToJsonResult); impl AsAnyRef for serde_json::Value { fn as_any_ref(&self) -> &dyn Any { self } } impl AsAnyMut for serde_json::Value { fn as_any_mut(&mut self) -> &mut dyn Any { self } } impl ToJsonResult for serde_json::Value { fn to_json_result(&self) -> Result, Error> { Ok(Box::new(self.clone())) } } impl ToJsonBytes for serde_json::Value { fn to_json_bytes(&self) -> Result, Error> { Ok(serde_json::to_vec(self)?) } } pub trait Collected: fmt::Debug + ToJsonResult + AsAnyRef + Send {} erased_serde::serialize_trait_object!(Collected); impl ToJsonResult for Box { fn to_json_result(&self) -> Result, Error> { self.as_ref().to_json_result() } } impl Collected for Box {} // TODO rename to `Typed` pub trait CollectorType: fmt::Debug + Send + Unpin + WithLen { type Input: Collectable; type Output: Collected + ToJsonResult + Serialize; fn ingest(&mut self, src: &mut Self::Input); fn set_range_complete(&mut self); fn set_timed_out(&mut self); // TODO use this crate's Error instead: fn result(&mut self, range: Option, binrange: Option) -> Result; } pub trait Collector: fmt::Debug + Send + Unpin + WithLen { fn ingest(&mut self, src: &mut dyn Collectable); fn set_range_complete(&mut self); fn set_timed_out(&mut self); // TODO factor the required parameters into new struct? Generic over events or binned? fn result( &mut self, range: Option, binrange: Option, ) -> Result, Error>; } impl Collector for T where T: fmt::Debug + CollectorType + 'static, { fn ingest(&mut self, src: &mut dyn Collectable) { let x = src.as_any_mut().downcast_mut(); if x.is_none() { warn!("TODO handle the case of incoming Box"); } let src: &mut ::Input = x.expect("can not downcast"); T::ingest(self, src) } fn set_range_complete(&mut self) { T::set_range_complete(self) } fn set_timed_out(&mut self) { T::set_timed_out(self) } fn result( &mut self, range: Option, binrange: Option, ) -> Result, Error> { let ret = T::result(self, range, binrange)?; Ok(Box::new(ret)) } } // TODO rename to `Typed` pub trait CollectableType: fmt::Debug + AsAnyRef + AsAnyMut { type Collector: CollectorType; fn new_collector() -> Self::Collector; } pub trait Collectable: fmt::Debug + AsAnyRef + AsAnyMut { fn new_collector(&self) -> Box; } impl Collectable for Box { fn new_collector(&self) -> Box { self.as_ref().new_collector() } } impl Collectable for T where T: CollectableType + 'static, { fn new_collector(&self) -> Box { Box::new(T::new_collector()) } } // TODO do this with some blanket impl: impl Collectable for Box { fn new_collector(&self) -> Box { Collectable::new_collector(self.as_ref()) } } impl WithLen for Box { fn len(&self) -> usize { self.as_ref().len() } } impl Collectable for Box { fn new_collector(&self) -> Box { self.as_ref().new_collector() } }