pub mod timebinimpl; use crate::collect_s::CollectableDyn; use crate::collect_s::CollectorDyn; use crate::collect_s::ToJsonResult; use crate::container::ByteEstimate; use crate::overlap::RangeOverlapInfo; use crate::vecpreview::PreviewRange; use crate::AsAnyMut; use crate::AsAnyRef; use crate::Empty; use crate::Events; use crate::Resettable; use crate::TypeName; use crate::WithLen; use err::thiserror; use err::Error; use err::ThisError; use netpod::log::*; use netpod::range::evrange::SeriesRange; use netpod::BinnedRange; use netpod::BinnedRangeEnum; use netpod::TsNano; use serde::Deserialize; use serde::Serialize; use std::any::Any; use std::fmt; use std::ops::Range; // TODO can probably be removed. pub trait TimeBins { fn ts_min(&self) -> Option; fn ts_max(&self) -> Option; fn ts_min_max(&self) -> Option<(u64, u64)>; } pub trait TimeBinnerTy: fmt::Debug + Send + Unpin { type Input: fmt::Debug; type Output: fmt::Debug; fn ingest(&mut self, item: &mut Self::Input); fn set_range_complete(&mut self); fn bins_ready_count(&self) -> usize; fn bins_ready(&mut self) -> Option; /// If there is a bin in progress with non-zero count, push it to the result set. /// With push_empty == true, a bin in progress is pushed even if it contains no counts. fn push_in_progress(&mut self, push_empty: bool); /// Implies `Self::push_in_progress` but in addition, pushes a zero-count bin if the call /// to `push_in_progress` did not change the result count, as long as edges are left. /// The next call to `Self::bins_ready_count` must return one higher count than before. fn cycle(&mut self); fn empty(&self) -> Option; fn append_empty_until_end(&mut self); } pub trait TimeBinnableTy: fmt::Debug + WithLen + Send + Sized { type TimeBinner: TimeBinnerTy; fn time_binner_new( &self, binrange: BinnedRangeEnum, do_time_weight: bool, emit_empty_bins: bool, ) -> Self::TimeBinner; } // #[derive(Debug, ThisError)] // #[cstm(name = "Binninggg")] pub enum BinningggError { Dyn(Box), TypeMismatch { have: String, expect: String }, } impl fmt::Display for BinningggError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match self { BinningggError::Dyn(e) => write!(fmt, "{e}"), BinningggError::TypeMismatch { have, expect } => { write!(fmt, "TypeMismatch(have: {have}, expect: {expect})") } } } } impl From for BinningggError where E: std::error::Error + 'static, { fn from(value: E) -> Self { Self::Dyn(Box::new(value)) } } pub trait BinningggContainerEventsDyn: fmt::Debug + Send { fn type_name(&self) -> &'static str; fn binned_events_timeweight_traitobj(&self, range: BinnedRange) -> Box; fn to_anybox(&mut self) -> Box; } pub trait BinningggContainerBinsDyn: fmt::Debug + Send + fmt::Display + WithLen + AsAnyMut + CollectableDyn { fn type_name(&self) -> &'static str; fn empty(&self) -> BinsBoxed; fn clone(&self) -> BinsBoxed; fn edges_iter( &self, ) -> std::iter::Zip, std::collections::vec_deque::Iter>; fn drain_into(&mut self, dst: &mut dyn BinningggContainerBinsDyn, range: Range); fn to_old_time_binned(&self) -> Box; } pub type BinsBoxed = Box; pub type EventsBoxed = Box; pub trait BinningggBinnerTy: fmt::Debug + Send { type Input: fmt::Debug; type Output: fmt::Debug; fn ingest(&mut self, item: &mut Self::Input); fn range_final(&mut self); fn bins_ready_count(&self) -> usize; fn bins_ready(&mut self) -> Option; } pub trait BinningggBinnableTy: fmt::Debug + WithLen + Send { type Binner: BinningggBinnerTy; fn binner_new(range: BinnedRange) -> Self::Binner; } pub trait BinningggBinnerDyn: fmt::Debug + Send { fn input_done_range_final(&mut self) -> Result<(), BinningggError>; fn input_done_range_open(&mut self) -> Result<(), BinningggError>; } pub trait BinnedEventsTimeweightTrait: fmt::Debug + Send { fn ingest(&mut self, evs_all: EventsBoxed) -> Result<(), BinningggError>; fn input_done_range_final(&mut self) -> Result<(), BinningggError>; fn input_done_range_open(&mut self) -> Result<(), BinningggError>; fn output(&mut self) -> Result, BinningggError>; } /// Data in time-binned form. pub trait TimeBinned: Any + TypeName + TimeBinnable + Resettable + CollectableDyn + erased_serde::Serialize { fn clone_box_time_binned(&self) -> Box; fn as_time_binnable_ref(&self) -> &dyn TimeBinnable; fn as_time_binnable_mut(&mut self) -> &mut dyn TimeBinnable; fn as_collectable_mut(&mut self) -> &mut dyn CollectableDyn; fn edges_slice(&self) -> (&[u64], &[u64]); fn counts(&self) -> &[u64]; fn mins(&self) -> Vec; fn maxs(&self) -> Vec; fn avgs(&self) -> Vec; fn validate(&self) -> Result<(), String>; fn empty_like_self_box_time_binned(&self) -> Box; fn to_simple_bins_f32(&mut self) -> Box; fn drain_into_tb(&mut self, dst: &mut dyn TimeBinned, range: Range) -> Result<(), Error>; } impl Clone for Box { fn clone(&self) -> Self { self.clone_box_time_binned() } } impl RangeOverlapInfo for Box { fn ends_before(&self, range: &SeriesRange) -> bool { todo!() } fn ends_after(&self, range: &SeriesRange) -> bool { todo!() } fn starts_after(&self, range: &SeriesRange) -> bool { todo!() } } impl TimeBinnable for Box { fn time_binner_new( &self, binrange: BinnedRangeEnum, do_time_weight: bool, emit_empty_bins: bool, ) -> Box { self.as_ref().time_binner_new(binrange, do_time_weight, emit_empty_bins) } fn to_box_to_json_result(&self) -> Box { self.as_ref().to_box_to_json_result() } fn to_container_bins(&self) -> Box { self.as_ref().to_container_bins() } } pub trait TimeBinner: fmt::Debug + Send { fn ingest(&mut self, item: &mut dyn TimeBinnable); fn bins_ready_count(&self) -> usize; fn bins_ready(&mut self) -> Option>; /// If there is a bin in progress with non-zero count, push it to the result set. /// With push_empty == true, a bin in progress is pushed even if it contains no counts. fn push_in_progress(&mut self, push_empty: bool); /// Implies `Self::push_in_progress` but in addition, pushes a zero-count bin if the call /// to `push_in_progress` did not change the result count, as long as edges are left. /// The next call to `Self::bins_ready_count` must return one higher count than before. fn cycle(&mut self); fn set_range_complete(&mut self); fn empty(&self) -> Box; fn append_empty_until_end(&mut self); } // TODO remove the Any bound. Factor out into custom AsAny trait. /// Provides a time-binned representation of the implementing type. /// In contrast to `TimeBinnableType` this is meant for trait objects. pub trait TimeBinnable: fmt::Debug + WithLen + RangeOverlapInfo + CollectableDyn + Any + AsAnyRef + AsAnyMut + Send { // TODO implementors may fail if edges contain not at least 2 entries. fn time_binner_new( &self, binrange: BinnedRangeEnum, do_time_weight: bool, emit_empty_bins: bool, ) -> Box; // TODO just a helper for the empty result. fn to_box_to_json_result(&self) -> Box; // TODO temporary converter fn to_container_bins(&self) -> Box; } impl WithLen for Box { fn len(&self) -> usize { WithLen::len(self.as_ref()) } } #[allow(unused)] impl RangeOverlapInfo for Box { fn ends_before(&self, range: &SeriesRange) -> bool { todo!() } fn ends_after(&self, range: &SeriesRange) -> bool { todo!() } fn starts_after(&self, range: &SeriesRange) -> bool { todo!() } } impl TimeBinnable for Box { fn time_binner_new( &self, binrange: BinnedRangeEnum, do_time_weight: bool, emit_empty_bins: bool, ) -> Box { self.as_ref().time_binner_new(binrange, do_time_weight, emit_empty_bins) } fn to_box_to_json_result(&self) -> Box { todo!() } fn to_container_bins(&self) -> Box { self.as_ref().to_container_bins() } } impl RangeOverlapInfo for Box { fn ends_before(&self, range: &SeriesRange) -> bool { RangeOverlapInfo::ends_before(self.as_ref(), range) } fn ends_after(&self, range: &SeriesRange) -> bool { RangeOverlapInfo::ends_after(self.as_ref(), range) } fn starts_after(&self, range: &SeriesRange) -> bool { RangeOverlapInfo::starts_after(self.as_ref(), range) } } impl TimeBinnable for Box { fn time_binner_new( &self, binrange: BinnedRangeEnum, do_time_weight: bool, emit_empty_bins: bool, ) -> Box { TimeBinnable::time_binner_new(self.as_ref(), binrange, do_time_weight, emit_empty_bins) } fn to_box_to_json_result(&self) -> Box { TimeBinnable::to_box_to_json_result(self.as_ref()) } fn to_container_bins(&self) -> Box { panic!("logic error this converter must not get used on events") } } impl TypeName for Box { fn type_name(&self) -> String { format!("Box TODO TypeName for Box") } } impl CollectableDyn for Box { fn new_collector(&self) -> Box { self.as_ref().new_collector() } } #[derive(Debug)] pub struct TimeBinnerDynStruct { binrange: BinnedRangeEnum, do_time_weight: bool, binner: Option>, emit_empty_bins: bool, } impl TimeBinnerDynStruct { pub fn type_name() -> &'static str { std::any::type_name::() } pub fn new( binrange: BinnedRangeEnum, do_time_weight: bool, emit_empty_bins: bool, binner: Box, ) -> Self { Self { binrange, do_time_weight, binner: Some(binner), emit_empty_bins, } } } impl TimeBinnerTy for TimeBinnerDynStruct { type Input = Box; type Output = Box; fn ingest(&mut self, item: &mut Self::Input) { trace!("{} INGEST {:?}", Self::type_name(), item); if self.binner.is_none() { self.binner = Some(Box::new(TimeBinnableTy::time_binner_new( item, self.binrange.clone(), self.do_time_weight, self.emit_empty_bins, ))); } self.binner.as_mut().unwrap().as_mut().ingest(item.as_mut()) } fn set_range_complete(&mut self) { if let Some(k) = self.binner.as_mut() { k.set_range_complete() } } fn bins_ready_count(&self) -> usize { if let Some(k) = self.binner.as_ref() { k.bins_ready_count() } else { 0 } } fn bins_ready(&mut self) -> Option { if let Some(k) = self.binner.as_mut() { k.bins_ready() } else { None } } fn push_in_progress(&mut self, push_empty: bool) { if let Some(k) = self.binner.as_mut() { k.push_in_progress(push_empty) } } fn cycle(&mut self) { if let Some(k) = self.binner.as_mut() { k.cycle() } } fn empty(&self) -> Option { if let Some(k) = self.binner.as_ref() { Some(k.empty()) } else { warn!("TimeBinnerDynStruct::empty called with binner None"); None } } fn append_empty_until_end(&mut self) { todo!() } } impl TimeBinner for TimeBinnerDynStruct { fn ingest(&mut self, item: &mut dyn TimeBinnable) { todo!() } fn bins_ready_count(&self) -> usize { todo!() } fn bins_ready(&mut self) -> Option> { todo!() } fn push_in_progress(&mut self, push_empty: bool) { todo!() } fn cycle(&mut self) { todo!() } fn set_range_complete(&mut self) { todo!() } fn empty(&self) -> Box { todo!() } fn append_empty_until_end(&mut self) { todo!() } } #[derive(Debug)] pub struct TimeBinnerDynStruct2 { binrange: BinnedRangeEnum, do_time_weight: bool, emit_empty_bins: bool, binner: Option>, } impl TimeBinnerDynStruct2 { pub fn type_name() -> &'static str { std::any::type_name::() } pub fn new( binrange: BinnedRangeEnum, do_time_weight: bool, emit_empty_bins: bool, binner: Box, ) -> Self { Self { binrange, do_time_weight, emit_empty_bins, binner: Some(binner), } } } impl TimeBinnerTy for TimeBinnerDynStruct2 { type Input = Box; type Output = Box; fn ingest(&mut self, item: &mut Self::Input) { trace!("{} INGEST {:?}", Self::type_name(), item); if self.binner.is_none() { self.binner = Some(Box::new(TimeBinnableTy::time_binner_new( item, self.binrange.clone(), self.do_time_weight, self.emit_empty_bins, ))); } self.binner .as_mut() .unwrap() .as_mut() .ingest(item.as_time_binnable_mut()) } fn set_range_complete(&mut self) { if let Some(k) = self.binner.as_mut() { k.set_range_complete() } } fn bins_ready_count(&self) -> usize { if let Some(k) = self.binner.as_ref() { k.bins_ready_count() } else { 0 } } fn bins_ready(&mut self) -> Option { if let Some(k) = self.binner.as_mut() { k.bins_ready() } else { None } } fn push_in_progress(&mut self, push_empty: bool) { if let Some(k) = self.binner.as_mut() { k.push_in_progress(push_empty) } } fn cycle(&mut self) { if let Some(k) = self.binner.as_mut() { k.cycle() } } fn empty(&self) -> Option { if let Some(k) = self.binner.as_ref() { Some(k.empty()) } else { warn!("TimeBinnerDynStruct::empty called with binner None"); None } } fn append_empty_until_end(&mut self) { todo!() } } #[allow(unused)] impl TimeBinner for TimeBinnerDynStruct2 { fn ingest(&mut self, item: &mut dyn TimeBinnable) { todo!() } fn bins_ready_count(&self) -> usize { todo!() } fn bins_ready(&mut self) -> Option> { todo!() } fn push_in_progress(&mut self, push_empty: bool) { todo!() } fn cycle(&mut self) { todo!() } fn set_range_complete(&mut self) { todo!() } fn empty(&self) -> Box { todo!() } fn append_empty_until_end(&mut self) { todo!() } } impl TimeBinnableTy for Box { type TimeBinner = TimeBinnerDynStruct; fn time_binner_new( &self, binrange: BinnedRangeEnum, do_time_weight: bool, emit_empty_bins: bool, ) -> Self::TimeBinner { let binner = self .as_ref() .time_binner_new(binrange.clone(), do_time_weight, emit_empty_bins); TimeBinnerDynStruct::new(binrange, do_time_weight, emit_empty_bins, binner) } } impl TimeBinnableTy for Box { type TimeBinner = TimeBinnerDynStruct2; fn time_binner_new( &self, binrange: BinnedRangeEnum, do_time_weight: bool, emit_empty_bins: bool, ) -> Self::TimeBinner { let binner = self .as_time_binnable_ref() .time_binner_new(binrange.clone(), do_time_weight, emit_empty_bins); TimeBinnerDynStruct2::new(binrange, do_time_weight, emit_empty_bins, binner) } } pub trait TimeBinnerIngest: fmt::Debug + TypeName + Send { fn ingest_inrange(&mut self, item: &mut dyn TimeBinnable) -> Result<(), Error>; }