use super::aggregator::AggTimeWeightOutputAvg; use super::aggregator::AggregatorNumeric; use super::aggregator::AggregatorPulsedNumeric; use super::aggregator::AggregatorTimeWeight; use super::aggregator::AggregatorVecNumeric; use super::timeweight::timeweight_events_dyn::BinnedEventsTimeweightDynbox; use crate::apitypes::ContainerEventsApi; use crate::log::*; use crate::offsets::pulse_offs_from_abs; use core::fmt; use core::ops::Range; use daqbuf_err as err; use err::thiserror; use err::ThisError; use items_0::apitypes::ToUserFacingApiType; use items_0::apitypes::UserApiType; use items_0::collect_s::CollectableDyn; use items_0::collect_s::CollectedDyn; use items_0::collect_s::CollectorDyn; use items_0::collect_s::CollectorTy; use items_0::container::ByteEstimate; use items_0::merge::DrainIntoDstResult; use items_0::merge::DrainIntoNewDynResult; use items_0::merge::DrainIntoNewResult; use items_0::merge::MergeableDyn; use items_0::merge::MergeableTy; use items_0::subfr::SubFrId; use items_0::timebin::BinningggContainerEventsDyn; use items_0::vecpreview::PreviewRange; use items_0::vecpreview::VecPreview; use items_0::Appendable; use items_0::AsAnyMut; use items_0::AsAnyRef; use items_0::Empty; use items_0::TypeName; use items_0::WithLen; use netpod::BinnedRange; use netpod::EnumVariant; use netpod::TsNano; use serde::Deserialize; use serde::Serialize; use std::any; use std::collections::VecDeque; macro_rules! trace_init { ($($arg:tt)*) => ( if false { trace!($($arg)*); }) } #[derive(Debug, ThisError)] #[cstm(name = "ValueContainerError")] pub enum ValueContainerError {} pub trait Container: fmt::Debug + Send + Unpin + Clone + PreviewRange + Serialize + for<'a> Deserialize<'a> where EVT: EventValueType, { fn new() -> Self; fn len(&self) -> usize; fn push_back(&mut self, val: EVT); fn get_iter_ty_1(&self, pos: usize) -> Option>; fn iter_ty_1(&self) -> impl Iterator>; fn drain_into(&mut self, dst: &mut Self, range: Range); fn into_user_facing_fields(self) -> Vec<(String, Box)>; fn into_user_facing_fields_json(self) -> Vec<(String, Box)>; } pub trait PartialOrdEvtA { fn cmp_a(&self, other: &EVT) -> Option; } pub trait EventValueType: fmt::Debug + Clone + PartialOrd + Send + Unpin + 'static + Serialize + for<'a> Deserialize<'a> { type Container: Container; type AggregatorTimeWeight: AggregatorTimeWeight; type AggTimeWeightOutputAvg: AggTimeWeightOutputAvg; type IterTy1<'a>: fmt::Debug + Clone + PartialOrdEvtA + Into; const SERDE_ID: u32; const BYTE_ESTIMATE_V00: u32; } impl Container for VecDeque where EVT: for<'a> EventValueType = EVT> + Serialize + for<'a> Deserialize<'a>, { fn new() -> Self { trace_init!("{} as trait Container ::new", std::any::type_name::()); VecDeque::new() } fn len(&self) -> usize { self.len() } fn push_back(&mut self, val: EVT) { self.push_back(val); } fn get_iter_ty_1(&self, pos: usize) -> Option> { self.get(pos).map(|x| x.clone()) } fn iter_ty_1(&self) -> impl Iterator::IterTy1<'_>> { self.iter().map(|x| x.clone()) } fn drain_into(&mut self, dst: &mut Self, range: Range) { dst.extend(self.drain(range)); } fn into_user_facing_fields(self) -> Vec<(String, Box)> { vec![("values".into(), Box::new(self))] } fn into_user_facing_fields_json(self) -> Vec<(String, Box)> { vec![("values".into(), Box::new(self))] } } impl Container for VecDeque { fn new() -> Self { VecDeque::new() } fn len(&self) -> usize { self.len() } fn push_back(&mut self, val: String) { self.push_back(val); } fn get_iter_ty_1(&self, pos: usize) -> Option<&str> { self.get(pos).map(|x| x.as_str()) } fn iter_ty_1(&self) -> impl Iterator::IterTy1<'_>> { self.iter().map(|x| x.as_str()) } fn drain_into(&mut self, dst: &mut Self, range: Range) { dst.extend(self.drain(range)) } fn into_user_facing_fields(self) -> Vec<(String, Box)> { vec![("values".into(), Box::new(self))] } fn into_user_facing_fields_json(self) -> Vec<(String, Box)> { vec![("values".into(), Box::new(self))] } } macro_rules! impl_event_value_type { ($evt:ty) => { impl EventValueType for $evt { type Container = VecDeque; type AggregatorTimeWeight = AggregatorNumeric; type AggTimeWeightOutputAvg = f64; type IterTy1<'a> = $evt; const SERDE_ID: u32 = <$evt as SubFrId>::SUB as _; const BYTE_ESTIMATE_V00: u32 = core::mem::size_of::<$evt>() as u32; } impl PartialOrdEvtA<$evt> for $evt { fn cmp_a(&self, other: &$evt) -> Option { self.partial_cmp(other) } } }; } impl_event_value_type!(u8); impl_event_value_type!(u16); impl_event_value_type!(u32); impl_event_value_type!(u64); impl_event_value_type!(i8); impl_event_value_type!(i16); impl_event_value_type!(i32); impl_event_value_type!(i64); // impl_event_value_type!(f32); // impl_event_value_type!(f64); impl PartialOrdEvtA for f32 { fn cmp_a(&self, other: &f32) -> Option { self.partial_cmp(other) } } impl PartialOrdEvtA for f64 { fn cmp_a(&self, other: &f64) -> Option { self.partial_cmp(other) } } impl PartialOrdEvtA for bool { fn cmp_a(&self, other: &bool) -> Option { self.partial_cmp(other) } } impl PartialOrdEvtA for &str { fn cmp_a(&self, other: &String) -> Option { (*self).partial_cmp(other.as_str()) } } impl EventValueType for f32 { type Container = VecDeque; type AggregatorTimeWeight = AggregatorNumeric; type AggTimeWeightOutputAvg = f32; type IterTy1<'a> = f32; const SERDE_ID: u32 = ::SUB as _; const BYTE_ESTIMATE_V00: u32 = core::mem::size_of::() as u32; } impl EventValueType for f64 { type Container = VecDeque; type AggregatorTimeWeight = AggregatorNumeric; type AggTimeWeightOutputAvg = f64; type IterTy1<'a> = f64; const SERDE_ID: u32 = ::SUB as _; const BYTE_ESTIMATE_V00: u32 = core::mem::size_of::() as u32; } impl EventValueType for bool { type Container = VecDeque; type AggregatorTimeWeight = AggregatorNumeric; type AggTimeWeightOutputAvg = f64; type IterTy1<'a> = bool; const SERDE_ID: u32 = ::SUB as _; const BYTE_ESTIMATE_V00: u32 = core::mem::size_of::() as u32; } impl EventValueType for String { type Container = VecDeque; type AggregatorTimeWeight = AggregatorNumeric; type AggTimeWeightOutputAvg = f64; type IterTy1<'a> = &'a str; const SERDE_ID: u32 = ::SUB as _; const BYTE_ESTIMATE_V00: u32 = 400; } macro_rules! impl_event_value_type_vec { ($evt:ty) => { impl EventValueType for Vec<$evt> { type Container = VecDeque; type AggregatorTimeWeight = AggregatorVecNumeric; type AggTimeWeightOutputAvg = f32; type IterTy1<'a> = Vec<$evt>; const SERDE_ID: u32 = as SubFrId>::SUB as _; // TODO must use a more precise number dependent on actual elements const BYTE_ESTIMATE_V00: u32 = 1200 * core::mem::size_of::() as u32; } impl PartialOrdEvtA> for Vec<$evt> { fn cmp_a(&self, other: &Vec<$evt>) -> Option { self.partial_cmp(other) } } }; } impl_event_value_type_vec!(u8); impl_event_value_type_vec!(u16); impl_event_value_type_vec!(u32); impl_event_value_type_vec!(u64); impl_event_value_type_vec!(i8); impl_event_value_type_vec!(i16); impl_event_value_type_vec!(i32); impl_event_value_type_vec!(i64); impl_event_value_type_vec!(f32); impl_event_value_type_vec!(f64); impl_event_value_type_vec!(bool); impl_event_value_type_vec!(String); impl_event_value_type_vec!(EnumVariant); #[derive(Debug)] pub struct PulsedValIterTy<'a, EVT> where EVT: EventValueType, { pulse: u64, evt: EVT::IterTy1<'a>, } impl<'a, EVT> Clone for PulsedValIterTy<'a, EVT> where EVT: EventValueType + SubFrId, { fn clone(&self) -> Self { Self { pulse: self.pulse, evt: self.evt.clone(), } } } impl<'a, EVT> PartialOrdEvtA> for PulsedValIterTy<'a, EVT> where EVT: EventValueType + SubFrId, { fn cmp_a(&self, other: &PulsedVal) -> Option { use std::cmp::Ordering; match self.evt.cmp_a(&other.1) { Some(Ordering::Less) => Some(Ordering::Less), Some(Ordering::Greater) => Some(Ordering::Greater), Some(Ordering::Equal) => Some(Ordering::Equal), None => None, } } } impl<'a, EVT> From> for PulsedVal where EVT: EventValueType, { fn from(value: PulsedValIterTy<'a, EVT>) -> Self { Self(value.pulse, value.evt.into()) } } #[derive(Debug, Clone, PartialEq, Serialize)] pub struct PulsedVal(pub u64, pub EVT) where EVT: EventValueType; impl fmt::Display for PulsedVal where EVT: EventValueType, { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "{:?}", self) } } impl PartialOrd for PulsedVal where EVT: EventValueType, { fn partial_cmp(&self, other: &Self) -> Option { self.1.partial_cmp(&other.1) } } mod serde_pulsed_val { use super::EventValueType; use super::PulsedVal; use serde::Deserialize; use serde::Deserializer; impl<'de, EVT> Deserialize<'de> for PulsedVal where EVT: EventValueType, { fn deserialize(de: D) -> Result where D: Deserializer<'de>, { todo!("TODO mod serde_pulsed_val") } } } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct VecDequePulsed where EVT: EventValueType, { pulses: VecDeque, vals: EVT::Container, } impl PreviewRange for VecDequePulsed where EVT: EventValueType, { fn preview<'a>(&'a self) -> Box { let ret = items_0::vecpreview::PreviewCell { a: self.pulses.front(), b: self.pulses.back(), }; Box::new(ret) } } impl Container> for VecDequePulsed where EVT: EventValueType, for<'a> PulsedVal: EventValueType = PulsedValIterTy<'a, EVT>>, { fn new() -> Self { Self { pulses: VecDeque::new(), vals: <::Container as Container>::new(), } } fn len(&self) -> usize { self.vals.len() } fn push_back(&mut self, val: PulsedVal) { self.pulses.push_back(val.0); self.vals.push_back(val.1); } fn get_iter_ty_1(&self, pos: usize) -> Option< as EventValueType>::IterTy1<'_>> { if let (Some(&pulse), Some(val)) = (self.pulses.get(pos), self.vals.get_iter_ty_1(pos)) { let x = PulsedValIterTy { pulse, evt: val }; Some(x) } else { None } } fn iter_ty_1(&self) -> impl Iterator as EventValueType>::IterTy1<'_>> { self.pulses .iter() .map(|&x| x) .zip(self.vals.iter_ty_1()) .map(|(pulse, evt)| PulsedValIterTy { pulse, evt }) } fn drain_into(&mut self, dst: &mut Self, range: Range) { dst.pulses.extend(self.pulses.drain(range.clone())); self.vals.drain_into(&mut dst.vals, range.clone()); } fn into_user_facing_fields(self) -> Vec<(String, Box)> { vec![ ("pulses".into(), Box::new(self.pulses)), ("values".into(), Box::new(self.vals)), ] } fn into_user_facing_fields_json(self) -> Vec<(String, Box)> { let (pulses_anch, pulses_offs) = pulse_offs_from_abs(&self.pulses); vec![ ("pulseAnchor".into(), Box::new(pulses_anch)), ("pulseOff".into(), Box::new(pulses_offs)), ("values".into(), Box::new(self.vals)), ] } } impl PartialOrdEvtA> for PulsedVal where EVT: EventValueType, { fn cmp_a(&self, other: &PulsedVal) -> Option { self.partial_cmp(other) } } impl EventValueType for PulsedVal where EVT: EventValueType + SubFrId, { type Container = VecDequePulsed; type AggregatorTimeWeight = AggregatorPulsedNumeric; type AggTimeWeightOutputAvg = EVT::AggTimeWeightOutputAvg; type IterTy1<'a> = PulsedValIterTy<'a, EVT>; const SERDE_ID: u32 = items_0::subfr::pulsed_subfr(::SUB) as _; const BYTE_ESTIMATE_V00: u32 = core::mem::size_of::() as u32; } #[derive(Debug, Clone)] pub struct EventSingleRef<'a, EVT> where EVT: EventValueType, { pub ts: TsNano, pub val: EVT::IterTy1<'a>, } impl<'a, EVT> EventSingleRef<'a, EVT> where EVT: EventValueType {} #[derive(Debug, Clone)] pub struct EventSingle { pub ts: TsNano, pub val: EVT, } impl<'a, EVT> From> for EventSingle where EVT: EventValueType, { fn from(value: EventSingleRef<'a, EVT>) -> Self { Self { ts: value.ts, val: value.val.into(), } } } impl<'a, EVT> From<&EventSingleRef<'a, EVT>> for EventSingle where EVT: EventValueType, { fn from(value: &EventSingleRef<'a, EVT>) -> Self { Self { ts: value.ts, val: value.val.clone().into(), } } } #[derive(Debug, ThisError)] #[cstm(name = "EventsContainerError")] pub enum EventsContainerError { Unordered, } #[derive(Clone)] pub struct ContainerEvents where EVT: EventValueType, { tss: VecDeque, vals: ::Container, byte_estimate: u64, } mod container_events_serde { use super::ContainerEvents; use super::EventValueType; use serde::de::MapAccess; use serde::de::SeqAccess; use serde::de::Visitor; use serde::ser::SerializeStruct; use serde::Deserialize; use serde::Deserializer; use serde::Serialize; use serde::Serializer; use std::fmt; use std::marker::PhantomData; macro_rules! trace_serde { ($($arg:tt)*) => ( if false { eprintln!($($arg)*); }) } impl Serialize for ContainerEvents where EVT: EventValueType, { fn serialize(&self, ser: S) -> Result where S: Serializer, { let stname = std::any::type_name::(); let mut st = ser.serialize_struct(stname, 2)?; st.serialize_field("tss", &self.tss)?; st.serialize_field("vals", &self.vals)?; st.end() } } struct Vis { _t1: PhantomData, } impl<'de, EVT> Visitor<'de> for Vis where EVT: EventValueType, { type Value = ContainerEvents; fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.write_str("a struct with fields tss and vals") } fn visit_seq(self, mut seq: S) -> Result where S: SeqAccess<'de>, { trace_serde!("Vis ContainerEvents visit_map"); let tss = seq .next_element()? .ok_or_else(|| serde::de::Error::invalid_length(0, &self))?; let vals = seq .next_element()? .ok_or_else(|| serde::de::Error::invalid_length(1, &self))?; let ret = Self::Value { tss, vals, // TODO make container recompute byte_estimate byte_estimate: 0, }; Ok(ret) } fn visit_map(self, mut map: M) -> Result where M: MapAccess<'de>, { trace_serde!("Vis ContainerEvents visit_map"); let mut tss = None; let mut vals = None; while let Some(key) = map.next_key::<&str>()? { match key { "tss" => { tss = Some(map.next_value()?); } "vals" => { vals = Some(map.next_value()?); } _ => { use serde::de::Error; return Err(Error::unknown_field(key, &["tss", "vals"])); } } } let ret = Self::Value { tss: tss.unwrap(), vals: vals.unwrap(), byte_estimate: 0, }; Ok(ret) } } impl<'de, EVT> Deserialize<'de> for ContainerEvents where EVT: EventValueType, { fn deserialize(de: D) -> Result where D: Deserializer<'de>, { let stname = std::any::type_name::(); de.deserialize_struct(stname, &["tss", "vals"], Vis { _t1: PhantomData }) } } } impl ContainerEvents where EVT: EventValueType, { pub fn from_constituents( tss: VecDeque, vals: ::Container, ) -> Self { Self { tss, vals, byte_estimate: 0, } } pub fn type_name() -> &'static str { any::type_name::() } pub fn new() -> Self { Self { tss: VecDeque::new(), vals: Container::new(), byte_estimate: 0, } } pub fn len(&self) -> usize { self.tss.len() } pub fn verify(&self) -> Result<(), EventsContainerError> { if self .tss .iter() .zip(self.tss.iter().skip(1)) .any(|(&a, &b)| a > b) { return Err(EventsContainerError::Unordered); } Ok(()) } pub fn push_back(&mut self, ts: TsNano, val: EVT) { self.tss.push_back(ts); self.vals.push_back(val); } pub fn iter_zip<'a>(&'a self) -> impl Iterator)> { self.tss.iter().map(|&x| x).zip(self.vals.iter_ty_1()) } pub fn serde_id() -> u32 { items_0::streamitem::CONTAINER_EVENTS_TYPE_ID } } impl fmt::Debug for ContainerEvents where EVT: EventValueType, { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let self_name = any::type_name::(); write!( fmt, "{self_name} {{ len: {:?}, tss: {:?}, vals {:?} }}", self.len(), VecPreview::new(&self.tss), VecPreview::new(&self.vals), ) } } impl AsAnyRef for ContainerEvents where EVT: EventValueType, { fn as_any_ref(&self) -> &dyn any::Any { self } } impl AsAnyMut for ContainerEvents where EVT: EventValueType, { fn as_any_mut(&mut self) -> &mut dyn any::Any { self } } impl WithLen for ContainerEvents where EVT: EventValueType, { fn len(&self) -> usize { self.len() } } impl ByteEstimate for ContainerEvents where EVT: EventValueType, { fn byte_estimate(&self) -> u64 { self.byte_estimate } } impl Empty for ContainerEvents where EVT: EventValueType, { fn empty() -> Self { ContainerEvents::new() } } impl Appendable for ContainerEvents where EVT: EventValueType, { fn push(&mut self, ts: TsNano, value: EVT) { self.push_back(ts, value); } } pub struct ContainerEventsTakeUpTo<'a, EVT> where EVT: EventValueType, { evs: &'a ContainerEvents, end: usize, pos: usize, // it: Box)>>, } impl<'a, EVT> ContainerEventsTakeUpTo<'a, EVT> where EVT: EventValueType, { pub fn new(evs: &'a ContainerEvents) -> Self { // let it = unsafe { netpod::extltref(evs) }.iter_zip(); // let it = Box::new(it); Self { evs, end: evs.len(), pos: 0, // it, } } pub fn constrain_up_to_ts(&mut self, end: TsNano) { let tss = &self.evs.tss; let pp = tss.partition_point(|&x| x < end); let pp = pp.max(self.pos); assert!(pp <= tss.len(), "len_before pp {} len {}", pp, tss.len()); assert!(pp >= self.pos); self.end = pp; } pub fn extend_to_all(&mut self) { self.end = self.evs.len(); } pub fn len(&self) -> usize { self.end - self.pos } pub fn pos(&self) -> usize { self.pos } pub fn ts_first(&self) -> Option { self.evs.tss.get(self.pos).cloned() } pub fn next(&mut self) -> Option> { let evs = &self.evs; if self.pos < self.end { if let (Some(&ts), Some(val)) = (evs.tss.get(self.pos), evs.vals.get_iter_ty_1(self.pos)) { self.pos += 1; let ev = EventSingleRef { ts, val }; Some(ev) } else { None } } else { None } } } impl MergeableTy for ContainerEvents where EVT: EventValueType, { fn ts_min(&self) -> Option { self.tss.front().copied() } fn ts_max(&self) -> Option { self.tss.back().copied() } fn find_lowest_index_gt(&self, ts: TsNano) -> Option { let x = self.tss.partition_point(|&x| x <= ts); if x >= self.tss.len() { None } else { Some(x) } } fn find_lowest_index_ge(&self, ts: TsNano) -> Option { let x = self.tss.partition_point(|&x| x < ts); if x >= self.tss.len() { None } else { Some(x) } } fn find_highest_index_lt(&self, ts: TsNano) -> Option { let x = self.tss.partition_point(|&x| x < ts); if x == 0 { None } else { Some(x - 1) } } fn tss_for_testing(&self) -> VecDeque { self.tss.clone() } fn drain_into(&mut self, dst: &mut Self, range: Range) -> DrainIntoDstResult { dst.tss.extend(self.tss.drain(range.clone())); self.vals.drain_into(&mut dst.vals, range); DrainIntoDstResult::Done } fn drain_into_new(&mut self, range: Range) -> DrainIntoNewResult { let mut dst = Self::new(); MergeableTy::drain_into(self, &mut dst, range); DrainIntoNewResult::Done(dst) } fn is_consistent(&self) -> bool { let mut good = true; let n = self.tss.len(); for (&ts1, &ts2) in self.tss.iter().zip(self.tss.range(n.min(1)..n)) { if ts1 > ts2 { good = false; error!("unordered event data ts1 {} ts2 {}", ts1, ts2); break; } } good } } impl MergeableDyn for ContainerEvents where EVT: EventValueType, { fn ts_min(&self) -> Option { MergeableTy::ts_min(self) } fn ts_max(&self) -> Option { MergeableTy::ts_max(self) } fn find_lowest_index_gt(&self, ts: TsNano) -> Option { MergeableTy::find_lowest_index_gt(self, ts) } fn find_lowest_index_ge(&self, ts: TsNano) -> Option { MergeableTy::find_lowest_index_ge(self, ts) } fn find_highest_index_lt(&self, ts: TsNano) -> Option { MergeableTy::find_highest_index_lt(self, ts) } fn tss_for_testing(&self) -> VecDeque { MergeableTy::tss_for_testing(self) } fn drain_into( &mut self, dst: &mut dyn MergeableDyn, range: Range, ) -> DrainIntoDstResult { if let Some(dst) = dst.as_any_mut().downcast_mut::() { MergeableTy::drain_into(self, dst, range) } else { DrainIntoDstResult::NotCompatible } } fn drain_into_new(&mut self, range: Range) -> DrainIntoNewDynResult { match MergeableTy::drain_into_new(self, range) { DrainIntoNewResult::Done(x) => DrainIntoNewDynResult::Done(Box::new(x)), DrainIntoNewResult::Partial(x) => DrainIntoNewDynResult::Partial(Box::new(x)), DrainIntoNewResult::NotCompatible => DrainIntoNewDynResult::NotCompatible, } } fn is_consistent(&self) -> bool { MergeableTy::is_consistent(self) } } impl TypeName for ContainerEvents where EVT: EventValueType, { fn type_name(&self) -> String { std::any::type_name::().into() } } #[derive(Debug, Serialize)] pub struct ContainerEventsCollected where EVT: EventValueType, { evs: ContainerEvents, range_final: bool, timed_out: bool, } impl WithLen for ContainerEventsCollected where EVT: EventValueType, { fn len(&self) -> usize { self.evs.len() } } impl TypeName for ContainerEventsCollected where EVT: EventValueType, { fn type_name(&self) -> String { std::any::type_name::().into() } } impl ToUserFacingApiType for ContainerEventsCollected where EVT: EventValueType, { fn into_user_facing_api_type(self: Self) -> Box { let evs = ContainerEventsApi:: { tss: self.evs.tss, values: self.evs.vals, range_final: self.range_final, timed_out: self.timed_out, }; Box::new(evs) } fn into_user_facing_api_type_box(self: Box) -> Box { (*self).into_user_facing_api_type() } } impl CollectedDyn for ContainerEventsCollected where EVT: EventValueType {} impl ByteEstimate for ContainerEventsCollector where EVT: EventValueType, { fn byte_estimate(&self) -> u64 { EVT::BYTE_ESTIMATE_V00 as _ } } #[derive(Debug)] pub struct ContainerEventsCollector where EVT: EventValueType, { evs: ContainerEvents, range_final: bool, timed_out: bool, } impl ContainerEventsCollector where EVT: EventValueType, { pub fn new() -> Self { debug!("ContainerEventsCollector::new"); Self { evs: ContainerEvents::new(), range_final: false, timed_out: false, } } } impl WithLen for ContainerEventsCollector where EVT: EventValueType, { fn len(&self) -> usize { self.evs.len() } } impl CollectorTy for ContainerEventsCollector where EVT: EventValueType, { type Input = ContainerEvents; type Output = ContainerEventsCollected; fn ingest(&mut self, src: &mut Self::Input) { MergeableTy::drain_into(src, &mut self.evs, 0..src.len()); } fn set_range_complete(&mut self) { self.range_final = true; } fn set_timed_out(&mut self) { self.timed_out = true; } fn result(&mut self) -> Result { let ret = Self::Output { evs: self.evs.clone(), range_final: self.range_final, timed_out: self.timed_out, }; Ok(ret) } } impl CollectableDyn for ContainerEvents where EVT: EventValueType, { fn new_collector(&self) -> Box { // crate::eventsdim0::EventsDim0; Box::new(ContainerEventsCollector::::new()) } } impl ToUserFacingApiType for ContainerEvents where EVT: EventValueType, { fn into_user_facing_api_type(self: Self) -> Box { let ret = ContainerEventsApi:: { tss: self.tss, values: self.vals, range_final: false, timed_out: false, }; Box::new(ret) } fn into_user_facing_api_type_box(self: Box) -> Box { let this = *self; this.into_user_facing_api_type() } } impl BinningggContainerEventsDyn for ContainerEvents where EVT: EventValueType, { fn binned_events_timeweight_traitobj( &self, range: BinnedRange, ) -> Box { BinnedEventsTimeweightDynbox::::new(range) } fn to_anybox(&mut self) -> Box { let ret = core::mem::replace(self, Self::new()); Box::new(ret) } fn clone_dyn(&self) -> Box { Box::new(self.clone()) } fn serde_id(&self) -> u32 { Self::serde_id() } fn nty_id(&self) -> u32 { EVT::SERDE_ID } fn eq(&self, rhs: &dyn BinningggContainerEventsDyn) -> bool { if let Some(rhs) = rhs.as_any_ref().downcast_ref::() { self.eq(rhs) } else { false } } fn as_mergeable_dyn_mut(&mut self) -> &mut dyn MergeableDyn { self } fn as_collectable_dyn_mut(&mut self) -> &mut dyn CollectableDyn { self } } #[cfg(test)] mod test_frame { use super::*; use crate::channelevents::ChannelEvents; use crate::framable::Framable; use crate::frame::decode_frame; use crate::inmem::InMemoryFrame; use crate::inmem::ParseResult; use items_0::streamitem::sitem_data; use items_0::streamitem::RangeCompletableItem; use items_0::streamitem::Sitemty; use items_0::streamitem::StreamItem; #[test] fn events_serialize() { let mut evs = ContainerEvents::::new(); evs.push_back(TsNano::from_ns(123), 55.); evs.push_back(TsNano::from_ns(124), 56.); let item = ChannelEvents::from(evs); let item: Sitemty<_> = sitem_data(item); let buf = item.make_frame_dyn().unwrap(); let frame = match InMemoryFrame::parse(&buf) { Ok(ParseResult::Parsed(n, val)) => val, Ok(ParseResult::NotEnoughData(n)) => panic!(), Err(e) => panic!("{}", e), }; let item: Sitemty = decode_frame(&frame).unwrap(); let item = if let Ok(x) = item { x } else { panic!() }; let item = if let StreamItem::DataItem(x) = item { x } else { panic!() }; let item = if let RangeCompletableItem::Data(x) = item { x } else { panic!() }; let item = if let ChannelEvents::Events(x) = item { x } else { panic!() }; let item = if let Some(item) = item.as_any_ref().downcast_ref::>() { item } else { panic!() }; assert_eq!( MergeableTy::tss_for_testing(item), &[TsNano::from_ns(123), TsNano::from_ns(124)] ); } } #[cfg(test)] mod test_serde_opt { use super::*; #[derive(Serialize)] struct A { a: Option, #[serde(default)] b: Option, #[serde(default, skip_serializing_if = "Option::is_none")] c: Option, } #[test] fn test_a() { let s = serde_json::to_string(&A { a: None, b: None, c: None, }) .unwrap(); assert_eq!(s, r#"{"a":null,"b":null}"#); } }