Move workspace crates into subfolder
This commit is contained in:
204
crates/items_0/src/collect_s.rs
Normal file
204
crates/items_0/src/collect_s.rs
Normal file
@@ -0,0 +1,204 @@
|
||||
use crate::timebin::TimeBinned;
|
||||
use crate::AsAnyMut;
|
||||
use crate::AsAnyRef;
|
||||
use crate::Events;
|
||||
use crate::TypeName;
|
||||
use crate::WithLen;
|
||||
use err::Error;
|
||||
use netpod::log::*;
|
||||
use netpod::range::evrange::SeriesRange;
|
||||
use netpod::BinnedRangeEnum;
|
||||
use serde::Serialize;
|
||||
use std::any;
|
||||
use std::any::Any;
|
||||
use std::fmt;
|
||||
|
||||
// TODO check usage of this trait
|
||||
pub trait ToJsonBytes {
|
||||
fn to_json_bytes(&self) -> Result<Vec<u8>, Error>;
|
||||
}
|
||||
|
||||
// TODO check usage of this trait
|
||||
pub trait ToJsonResult: erased_serde::Serialize + fmt::Debug + AsAnyRef + AsAnyMut + Send {
|
||||
fn to_json_result(&self) -> Result<Box<dyn ToJsonBytes>, 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<Box<dyn ToJsonBytes>, Error> {
|
||||
Ok(Box::new(self.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJsonBytes for serde_json::Value {
|
||||
fn to_json_bytes(&self) -> Result<Vec<u8>, Error> {
|
||||
Ok(serde_json::to_vec(self)?)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Collected: fmt::Debug + Send + AsAnyRef + WithLen + ToJsonResult {}
|
||||
|
||||
erased_serde::serialize_trait_object!(Collected);
|
||||
|
||||
impl ToJsonResult for Box<dyn Collected> {
|
||||
fn to_json_result(&self) -> Result<Box<dyn ToJsonBytes>, Error> {
|
||||
self.as_ref().to_json_result()
|
||||
}
|
||||
}
|
||||
|
||||
impl WithLen for Box<dyn Collected> {
|
||||
fn len(&self) -> usize {
|
||||
self.as_ref().len()
|
||||
}
|
||||
}
|
||||
|
||||
impl Collected for Box<dyn Collected> {}
|
||||
|
||||
// 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<SeriesRange>, binrange: Option<BinnedRangeEnum>) -> Result<Self::Output, Error>;
|
||||
}
|
||||
|
||||
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<SeriesRange>,
|
||||
binrange: Option<BinnedRangeEnum>,
|
||||
) -> Result<Box<dyn Collected>, Error>;
|
||||
}
|
||||
|
||||
impl<T> Collector for T
|
||||
where
|
||||
T: fmt::Debug + CollectorType + 'static,
|
||||
{
|
||||
fn ingest(&mut self, src: &mut dyn Collectable) {
|
||||
if let Some(src) = src.as_any_mut().downcast_mut::<<T as CollectorType>::Input>() {
|
||||
trace!("sees incoming &mut ref");
|
||||
T::ingest(self, src)
|
||||
} else {
|
||||
if let Some(src) = src.as_any_mut().downcast_mut::<Box<<T as CollectorType>::Input>>() {
|
||||
trace!("sees incoming &mut Box");
|
||||
T::ingest(self, src)
|
||||
} else {
|
||||
error!(
|
||||
"No idea what this is. Expect: {} input {} got: {} {:?}",
|
||||
any::type_name::<T>(),
|
||||
any::type_name::<<T as CollectorType>::Input>(),
|
||||
src.type_name(),
|
||||
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<SeriesRange>,
|
||||
binrange: Option<BinnedRangeEnum>,
|
||||
) -> Result<Box<dyn Collected>, Error> {
|
||||
let ret = T::result(self, range, binrange)?;
|
||||
Ok(Box::new(ret))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO rename to `Typed`
|
||||
pub trait CollectableType: fmt::Debug + WithLen + AsAnyRef + AsAnyMut + TypeName + Send {
|
||||
type Collector: CollectorType<Input = Self>;
|
||||
fn new_collector() -> Self::Collector;
|
||||
}
|
||||
|
||||
pub trait Collectable: fmt::Debug + WithLen + AsAnyRef + AsAnyMut + TypeName + Send {
|
||||
fn new_collector(&self) -> Box<dyn Collector>;
|
||||
}
|
||||
|
||||
impl TypeName for Box<dyn Events> {
|
||||
fn type_name(&self) -> String {
|
||||
self.as_ref().type_name()
|
||||
}
|
||||
}
|
||||
|
||||
impl Collectable for Box<dyn Events> {
|
||||
fn new_collector(&self) -> Box<dyn Collector> {
|
||||
self.as_ref().new_collector()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Collectable for T
|
||||
where
|
||||
T: CollectableType + 'static,
|
||||
{
|
||||
fn new_collector(&self) -> Box<dyn Collector> {
|
||||
Box::new(T::new_collector())
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeName for Box<dyn Collectable> {
|
||||
fn type_name(&self) -> String {
|
||||
self.as_ref().type_name()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO do this with some blanket impl:
|
||||
impl WithLen for Box<dyn Collectable> {
|
||||
fn len(&self) -> usize {
|
||||
WithLen::len(self.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
// TODO do this with some blanket impl:
|
||||
impl Collectable for Box<dyn Collectable> {
|
||||
fn new_collector(&self) -> Box<dyn Collector> {
|
||||
Collectable::new_collector(self.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl WithLen for Box<dyn TimeBinned> {
|
||||
fn len(&self) -> usize {
|
||||
WithLen::len(self.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeName for Box<dyn TimeBinned> {
|
||||
fn type_name(&self) -> String {
|
||||
self.as_ref().type_name()
|
||||
}
|
||||
}
|
||||
|
||||
impl Collectable for Box<dyn TimeBinned> {
|
||||
fn new_collector(&self) -> Box<dyn Collector> {
|
||||
self.as_ref().new_collector()
|
||||
}
|
||||
}
|
||||
11
crates/items_0/src/container.rs
Normal file
11
crates/items_0/src/container.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
use crate::Events;
|
||||
|
||||
pub trait ByteEstimate {
|
||||
fn byte_estimate(&self) -> u64;
|
||||
}
|
||||
|
||||
impl ByteEstimate for Box<dyn Events> {
|
||||
fn byte_estimate(&self) -> u64 {
|
||||
self.as_ref().byte_estimate()
|
||||
}
|
||||
}
|
||||
19
crates/items_0/src/framable.rs
Normal file
19
crates/items_0/src/framable.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
// Required for any inner type of Sitemty.
|
||||
pub trait FrameTypeInnerStatic {
|
||||
const FRAME_TYPE_ID: u32;
|
||||
}
|
||||
|
||||
// To be implemented by the T of Sitemty<T>, e.g. ScalarEvents.
|
||||
pub trait FrameTypeInnerDyn {
|
||||
// TODO check actual usage of this
|
||||
fn frame_type_id(&self) -> u32;
|
||||
}
|
||||
|
||||
impl<T> FrameTypeInnerDyn for T
|
||||
where
|
||||
T: FrameTypeInnerStatic,
|
||||
{
|
||||
fn frame_type_id(&self) -> u32 {
|
||||
<Self as FrameTypeInnerStatic>::FRAME_TYPE_ID
|
||||
}
|
||||
}
|
||||
25
crates/items_0/src/isodate.rs
Normal file
25
crates/items_0/src/isodate.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use chrono::DateTime;
|
||||
use chrono::TimeZone;
|
||||
use chrono::Utc;
|
||||
use netpod::DATETIME_FMT_3MS;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use serde::Serializer;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub struct IsoDateTime(DateTime<Utc>);
|
||||
|
||||
impl Serialize for IsoDateTime {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.0.format(DATETIME_FMT_3MS).to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_iso_ts(tss: &[u64]) -> Vec<IsoDateTime> {
|
||||
tss.iter()
|
||||
.map(|&k| IsoDateTime(Utc.timestamp_nanos(k as i64)))
|
||||
.collect()
|
||||
}
|
||||
255
crates/items_0/src/items_0.rs
Normal file
255
crates/items_0/src/items_0.rs
Normal file
@@ -0,0 +1,255 @@
|
||||
pub mod collect_s;
|
||||
pub mod container;
|
||||
pub mod framable;
|
||||
pub mod isodate;
|
||||
pub mod overlap;
|
||||
pub mod scalar_ops;
|
||||
pub mod streamitem;
|
||||
pub mod subfr;
|
||||
pub mod test;
|
||||
pub mod timebin;
|
||||
pub mod transform;
|
||||
|
||||
pub mod bincode {
|
||||
pub use bincode::*;
|
||||
}
|
||||
|
||||
pub use futures_util;
|
||||
|
||||
use collect_s::Collectable;
|
||||
use container::ByteEstimate;
|
||||
use netpod::range::evrange::SeriesRange;
|
||||
use std::any::Any;
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt;
|
||||
use timebin::TimeBinnable;
|
||||
|
||||
pub trait WithLen {
|
||||
fn len(&self) -> usize;
|
||||
}
|
||||
|
||||
pub trait Empty {
|
||||
fn empty() -> Self;
|
||||
}
|
||||
|
||||
pub trait Resettable {
|
||||
fn reset(&mut self);
|
||||
}
|
||||
|
||||
pub trait Appendable<STY>: Empty + WithLen {
|
||||
fn push(&mut self, ts: u64, pulse: u64, value: STY);
|
||||
}
|
||||
|
||||
pub trait TypeName {
|
||||
fn type_name(&self) -> String;
|
||||
}
|
||||
|
||||
pub trait AppendEmptyBin {
|
||||
fn append_empty_bin(&mut self, ts1: u64, ts2: u64);
|
||||
}
|
||||
|
||||
pub trait AppendAllFrom {
|
||||
fn append_all_from(&mut self, src: &mut Self);
|
||||
}
|
||||
|
||||
// TODO check usage, probably only for legacy
|
||||
pub trait HasNonemptyFirstBin {
|
||||
fn has_nonempty_first_bin(&self) -> bool;
|
||||
}
|
||||
|
||||
pub trait AsAnyRef {
|
||||
fn as_any_ref(&self) -> &dyn Any;
|
||||
}
|
||||
|
||||
pub trait AsAnyMut {
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||
}
|
||||
|
||||
impl<T> AsAnyRef for Box<T>
|
||||
where
|
||||
T: AsAnyRef + ?Sized,
|
||||
{
|
||||
fn as_any_ref(&self) -> &dyn Any {
|
||||
self.as_ref().as_any_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsAnyMut for Box<T>
|
||||
where
|
||||
T: AsAnyMut + ?Sized,
|
||||
{
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
self.as_mut().as_any_mut()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MergeError {
|
||||
NotCompatible,
|
||||
Full,
|
||||
}
|
||||
|
||||
impl From<MergeError> for err::Error {
|
||||
fn from(e: MergeError) -> Self {
|
||||
format!("{e:?}").into()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO can I remove the Any bound?
|
||||
|
||||
/// Container of some form of events, for use as trait object.
|
||||
pub trait Events:
|
||||
fmt::Debug
|
||||
+ TypeName
|
||||
+ Any
|
||||
+ Collectable
|
||||
+ TimeBinnable
|
||||
+ WithLen
|
||||
+ ByteEstimate
|
||||
+ Send
|
||||
+ erased_serde::Serialize
|
||||
+ EventsNonObj
|
||||
{
|
||||
fn as_time_binnable_ref(&self) -> &dyn TimeBinnable;
|
||||
fn as_time_binnable_mut(&mut self) -> &mut dyn TimeBinnable;
|
||||
fn verify(&self) -> bool;
|
||||
fn output_info(&self);
|
||||
fn as_collectable_mut(&mut self) -> &mut dyn Collectable;
|
||||
fn as_collectable_with_default_ref(&self) -> &dyn Collectable;
|
||||
fn as_collectable_with_default_mut(&mut self) -> &mut dyn Collectable;
|
||||
fn ts_min(&self) -> Option<u64>;
|
||||
fn ts_max(&self) -> Option<u64>;
|
||||
// TODO is this used?
|
||||
fn take_new_events_until_ts(&mut self, ts_end: u64) -> Box<dyn Events>;
|
||||
fn new_empty_evs(&self) -> Box<dyn Events>;
|
||||
fn drain_into_evs(&mut self, dst: &mut Box<dyn Events>, range: (usize, usize)) -> Result<(), MergeError>;
|
||||
fn find_lowest_index_gt_evs(&self, ts: u64) -> Option<usize>;
|
||||
fn find_lowest_index_ge_evs(&self, ts: u64) -> Option<usize>;
|
||||
fn find_highest_index_lt_evs(&self, ts: u64) -> Option<usize>;
|
||||
fn clone_dyn(&self) -> Box<dyn Events>;
|
||||
fn partial_eq_dyn(&self, other: &dyn Events) -> bool;
|
||||
fn serde_id(&self) -> &'static str;
|
||||
fn nty_id(&self) -> u32;
|
||||
fn tss(&self) -> &VecDeque<u64>;
|
||||
fn pulses(&self) -> &VecDeque<u64>;
|
||||
fn frame_type_id(&self) -> u32;
|
||||
fn to_min_max_avg(&mut self) -> Box<dyn Events>;
|
||||
}
|
||||
|
||||
impl WithLen for Box<dyn Events> {
|
||||
fn len(&self) -> usize {
|
||||
self.as_ref().len()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait EventsNonObj {
|
||||
fn into_tss_pulses(self: Box<Self>) -> (VecDeque<u64>, VecDeque<u64>);
|
||||
}
|
||||
|
||||
erased_serde::serialize_trait_object!(Events);
|
||||
|
||||
impl PartialEq for Box<dyn Events> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
Events::partial_eq_dyn(self.as_ref(), other.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl EventsNonObj for Box<dyn Events> {
|
||||
fn into_tss_pulses(self: Box<Self>) -> (VecDeque<u64>, VecDeque<u64>) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Events for Box<dyn Events> {
|
||||
fn as_time_binnable_ref(&self) -> &dyn TimeBinnable {
|
||||
Events::as_time_binnable_ref(self.as_ref())
|
||||
}
|
||||
|
||||
fn as_time_binnable_mut(&mut self) -> &mut dyn TimeBinnable {
|
||||
Events::as_time_binnable_mut(self.as_mut())
|
||||
}
|
||||
|
||||
fn verify(&self) -> bool {
|
||||
Events::verify(self.as_ref())
|
||||
}
|
||||
|
||||
fn output_info(&self) {
|
||||
Events::output_info(self.as_ref())
|
||||
}
|
||||
|
||||
fn as_collectable_mut(&mut self) -> &mut dyn Collectable {
|
||||
Events::as_collectable_mut(self.as_mut())
|
||||
}
|
||||
|
||||
fn as_collectable_with_default_ref(&self) -> &dyn Collectable {
|
||||
Events::as_collectable_with_default_ref(self.as_ref())
|
||||
}
|
||||
|
||||
fn as_collectable_with_default_mut(&mut self) -> &mut dyn Collectable {
|
||||
Events::as_collectable_with_default_mut(self.as_mut())
|
||||
}
|
||||
|
||||
fn ts_min(&self) -> Option<u64> {
|
||||
Events::ts_min(self.as_ref())
|
||||
}
|
||||
|
||||
fn ts_max(&self) -> Option<u64> {
|
||||
Events::ts_max(self.as_ref())
|
||||
}
|
||||
|
||||
fn take_new_events_until_ts(&mut self, ts_end: u64) -> Box<dyn Events> {
|
||||
Events::take_new_events_until_ts(self.as_mut(), ts_end)
|
||||
}
|
||||
|
||||
fn new_empty_evs(&self) -> Box<dyn Events> {
|
||||
Events::new_empty_evs(self.as_ref())
|
||||
}
|
||||
|
||||
fn drain_into_evs(&mut self, dst: &mut Box<dyn Events>, range: (usize, usize)) -> Result<(), MergeError> {
|
||||
Events::drain_into_evs(self.as_mut(), dst, range)
|
||||
}
|
||||
|
||||
fn find_lowest_index_gt_evs(&self, ts: u64) -> Option<usize> {
|
||||
Events::find_lowest_index_gt_evs(self.as_ref(), ts)
|
||||
}
|
||||
|
||||
fn find_lowest_index_ge_evs(&self, ts: u64) -> Option<usize> {
|
||||
Events::find_lowest_index_ge_evs(self.as_ref(), ts)
|
||||
}
|
||||
|
||||
fn find_highest_index_lt_evs(&self, ts: u64) -> Option<usize> {
|
||||
Events::find_highest_index_lt_evs(self.as_ref(), ts)
|
||||
}
|
||||
|
||||
fn clone_dyn(&self) -> Box<dyn Events> {
|
||||
Events::clone_dyn(self.as_ref())
|
||||
}
|
||||
|
||||
fn partial_eq_dyn(&self, other: &dyn Events) -> bool {
|
||||
Events::partial_eq_dyn(self.as_ref(), other)
|
||||
}
|
||||
|
||||
fn serde_id(&self) -> &'static str {
|
||||
Events::serde_id(self.as_ref())
|
||||
}
|
||||
|
||||
fn nty_id(&self) -> u32 {
|
||||
Events::nty_id(self.as_ref())
|
||||
}
|
||||
|
||||
fn tss(&self) -> &VecDeque<u64> {
|
||||
Events::tss(self.as_ref())
|
||||
}
|
||||
|
||||
fn pulses(&self) -> &VecDeque<u64> {
|
||||
Events::pulses(self.as_ref())
|
||||
}
|
||||
|
||||
fn frame_type_id(&self) -> u32 {
|
||||
Events::frame_type_id(self.as_ref())
|
||||
}
|
||||
|
||||
fn to_min_max_avg(&mut self) -> Box<dyn Events> {
|
||||
Events::to_min_max_avg(self.as_mut())
|
||||
}
|
||||
}
|
||||
151
crates/items_0/src/overlap.rs
Normal file
151
crates/items_0/src/overlap.rs
Normal file
@@ -0,0 +1,151 @@
|
||||
use netpod::log::*;
|
||||
use netpod::range::evrange::SeriesRange;
|
||||
|
||||
// TODO rename, no more deque involved
|
||||
pub trait HasTimestampDeque {
|
||||
fn timestamp_min(&self) -> Option<u64>;
|
||||
fn timestamp_max(&self) -> Option<u64>;
|
||||
fn pulse_min(&self) -> Option<u64>;
|
||||
fn pulse_max(&self) -> Option<u64>;
|
||||
}
|
||||
|
||||
pub trait RangeOverlapInfo {
|
||||
fn ends_before(&self, range: &SeriesRange) -> bool;
|
||||
fn ends_after(&self, range: &SeriesRange) -> bool;
|
||||
fn starts_after(&self, range: &SeriesRange) -> bool;
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_range_overlap_info_events {
|
||||
($ty:ident) => {
|
||||
impl<STY> RangeOverlapInfo for $ty<STY>
|
||||
where
|
||||
STY: ScalarOps,
|
||||
{
|
||||
fn ends_before(&self, range: &SeriesRange) -> bool {
|
||||
if range.is_time() {
|
||||
if let Some(max) = HasTimestampDeque::timestamp_max(self) {
|
||||
max < range.beg_u64()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else if range.is_pulse() {
|
||||
if let Some(max) = HasTimestampDeque::pulse_max(self) {
|
||||
max < range.beg_u64()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
error!("unexpected");
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn ends_after(&self, range: &SeriesRange) -> bool {
|
||||
if range.is_time() {
|
||||
if let Some(max) = HasTimestampDeque::timestamp_max(self) {
|
||||
max >= range.end_u64()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else if range.is_pulse() {
|
||||
if let Some(max) = HasTimestampDeque::pulse_max(self) {
|
||||
max >= range.end_u64()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
error!("unexpected");
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn starts_after(&self, range: &SeriesRange) -> bool {
|
||||
if range.is_time() {
|
||||
if let Some(min) = HasTimestampDeque::timestamp_min(self) {
|
||||
min >= range.end_u64()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else if range.is_pulse() {
|
||||
if let Some(min) = HasTimestampDeque::pulse_min(self) {
|
||||
min >= range.end_u64()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
error!("unexpected");
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_range_overlap_info_bins {
|
||||
($ty:ident) => {
|
||||
impl<STY> RangeOverlapInfo for $ty<STY>
|
||||
where
|
||||
STY: ScalarOps,
|
||||
{
|
||||
fn ends_before(&self, range: &SeriesRange) -> bool {
|
||||
if range.is_time() {
|
||||
if let Some(max) = HasTimestampDeque::timestamp_max(self) {
|
||||
max <= range.beg_u64()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else if range.is_pulse() {
|
||||
// TODO for the time being, the ts represent either ts or pulse
|
||||
if let Some(max) = HasTimestampDeque::timestamp_max(self) {
|
||||
max <= range.beg_u64()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
error!("unexpected");
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn ends_after(&self, range: &SeriesRange) -> bool {
|
||||
if range.is_time() {
|
||||
if let Some(max) = HasTimestampDeque::timestamp_max(self) {
|
||||
max > range.end_u64()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else if range.is_pulse() {
|
||||
if let Some(max) = HasTimestampDeque::timestamp_max(self) {
|
||||
max > range.end_u64()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
error!("unexpected");
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn starts_after(&self, range: &SeriesRange) -> bool {
|
||||
if range.is_time() {
|
||||
if let Some(min) = HasTimestampDeque::timestamp_min(self) {
|
||||
min >= range.end_u64()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else if range.is_pulse() {
|
||||
if let Some(min) = HasTimestampDeque::timestamp_min(self) {
|
||||
min >= range.end_u64()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
error!("unexpected");
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
214
crates/items_0/src/scalar_ops.rs
Normal file
214
crates/items_0/src/scalar_ops.rs
Normal file
@@ -0,0 +1,214 @@
|
||||
use crate::subfr::SubFrId;
|
||||
use serde::Serialize;
|
||||
use std::fmt;
|
||||
use std::ops;
|
||||
|
||||
#[allow(unused)]
|
||||
const fn is_nan_int<T>(_x: &T) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn is_nan_f32(x: f32) -> bool {
|
||||
x.is_nan()
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn is_nan_f64(x: f64) -> bool {
|
||||
x.is_nan()
|
||||
}
|
||||
|
||||
pub trait AsPrimF32 {
|
||||
fn as_prim_f32_b(&self) -> f32;
|
||||
}
|
||||
|
||||
macro_rules! impl_as_prim_f32 {
|
||||
($ty:ident) => {
|
||||
impl AsPrimF32 for $ty {
|
||||
fn as_prim_f32_b(&self) -> f32 {
|
||||
*self as f32
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_as_prim_f32!(u8);
|
||||
impl_as_prim_f32!(u16);
|
||||
impl_as_prim_f32!(u32);
|
||||
impl_as_prim_f32!(u64);
|
||||
impl_as_prim_f32!(i8);
|
||||
impl_as_prim_f32!(i16);
|
||||
impl_as_prim_f32!(i32);
|
||||
impl_as_prim_f32!(i64);
|
||||
impl_as_prim_f32!(f32);
|
||||
impl_as_prim_f32!(f64);
|
||||
|
||||
impl AsPrimF32 for bool {
|
||||
fn as_prim_f32_b(&self) -> f32 {
|
||||
if *self {
|
||||
1.
|
||||
} else {
|
||||
0.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsPrimF32 for String {
|
||||
fn as_prim_f32_b(&self) -> f32 {
|
||||
// Well, at least some impl.
|
||||
self.len() as f32
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ScalarOps:
|
||||
fmt::Debug + Clone + PartialOrd + PartialEq + SubFrId + AsPrimF32 + Serialize + Unpin + Send + 'static
|
||||
{
|
||||
fn zero_b() -> Self;
|
||||
fn equal_slack(&self, rhs: &Self) -> bool;
|
||||
fn add(&mut self, rhs: &Self);
|
||||
fn div(&mut self, n: usize);
|
||||
fn find_vec_min(a: &Vec<Self>) -> Option<Self>;
|
||||
fn find_vec_max(a: &Vec<Self>) -> Option<Self>;
|
||||
fn avg_vec(a: &Vec<Self>) -> Option<Self>;
|
||||
}
|
||||
|
||||
macro_rules! impl_scalar_ops {
|
||||
($ty:ident, $zero:expr, $equal_slack:ident, $mac_add:ident, $mac_div:ident) => {
|
||||
impl ScalarOps for $ty {
|
||||
fn zero_b() -> Self {
|
||||
$zero
|
||||
}
|
||||
|
||||
fn equal_slack(&self, rhs: &Self) -> bool {
|
||||
$equal_slack(self, rhs)
|
||||
}
|
||||
|
||||
fn add(&mut self, rhs: &Self) {
|
||||
$mac_add!(self, rhs);
|
||||
}
|
||||
|
||||
fn div(&mut self, n: usize) {
|
||||
$mac_div!(self, n);
|
||||
}
|
||||
|
||||
fn find_vec_min(a: &Vec<Self>) -> Option<Self> {
|
||||
if a.len() == 0 {
|
||||
None
|
||||
} else {
|
||||
let mut k = &a[0];
|
||||
for (i, v) in a.iter().enumerate() {
|
||||
if *v < *k {
|
||||
k = &a[i];
|
||||
}
|
||||
}
|
||||
Some(k.clone())
|
||||
}
|
||||
}
|
||||
|
||||
fn find_vec_max(a: &Vec<Self>) -> Option<Self> {
|
||||
if a.len() == 0 {
|
||||
None
|
||||
} else {
|
||||
let mut k = &a[0];
|
||||
for (i, v) in a.iter().enumerate() {
|
||||
if *v > *k {
|
||||
k = &a[i];
|
||||
}
|
||||
}
|
||||
Some(k.clone())
|
||||
}
|
||||
}
|
||||
|
||||
fn avg_vec(a: &Vec<Self>) -> Option<Self> {
|
||||
if a.len() == 0 {
|
||||
None
|
||||
} else {
|
||||
let mut sum = Self::zero_b();
|
||||
let mut c = 0;
|
||||
for v in a.iter() {
|
||||
sum.add(v);
|
||||
c += 1;
|
||||
}
|
||||
ScalarOps::div(&mut sum, c);
|
||||
Some(sum)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn equal_int<T: PartialEq>(a: T, b: T) -> bool {
|
||||
a == b
|
||||
}
|
||||
|
||||
fn equal_f32(&a: &f32, &b: &f32) -> bool {
|
||||
(a - b).abs() < 1e-4 || (a / b > 0.999 && a / b < 1.001)
|
||||
}
|
||||
|
||||
fn equal_f64(&a: &f64, &b: &f64) -> bool {
|
||||
(a - b).abs() < 1e-6 || (a / b > 0.99999 && a / b < 1.00001)
|
||||
}
|
||||
|
||||
fn equal_bool(&a: &bool, &b: &bool) -> bool {
|
||||
a == b
|
||||
}
|
||||
|
||||
fn equal_string(a: &String, b: &String) -> bool {
|
||||
a == b
|
||||
}
|
||||
|
||||
fn add_int<T: ops::AddAssign>(a: &mut T, b: &T) {
|
||||
ops::AddAssign::add_assign(a, todo!());
|
||||
}
|
||||
|
||||
macro_rules! add_int {
|
||||
($a:expr, $b:expr) => {
|
||||
*$a += $b;
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! add_bool {
|
||||
($a:expr, $b:expr) => {
|
||||
*$a |= $b;
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! add_string {
|
||||
($a:expr, $b:expr) => {
|
||||
$a.push_str($b);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! div_int {
|
||||
($a:expr, $b:expr) => {
|
||||
// TODO for average calculation, the accumulator must be large enough!
|
||||
// Use u64 for all ints, and f32 for all floats.
|
||||
// Therefore, the name "add" is too general.
|
||||
//*$a /= $b;
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! div_bool {
|
||||
($a:expr, $b:expr) => {
|
||||
//
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! div_string {
|
||||
($a:expr, $b:expr) => {
|
||||
//
|
||||
};
|
||||
}
|
||||
|
||||
impl_scalar_ops!(u8, 0, equal_int, add_int, div_int);
|
||||
impl_scalar_ops!(u16, 0, equal_int, add_int, div_int);
|
||||
impl_scalar_ops!(u32, 0, equal_int, add_int, div_int);
|
||||
impl_scalar_ops!(u64, 0, equal_int, add_int, div_int);
|
||||
impl_scalar_ops!(i8, 0, equal_int, add_int, div_int);
|
||||
impl_scalar_ops!(i16, 0, equal_int, add_int, div_int);
|
||||
impl_scalar_ops!(i32, 0, equal_int, add_int, div_int);
|
||||
impl_scalar_ops!(i64, 0, equal_int, add_int, div_int);
|
||||
impl_scalar_ops!(f32, 0., equal_f32, add_int, div_int);
|
||||
impl_scalar_ops!(f64, 0., equal_f64, add_int, div_int);
|
||||
impl_scalar_ops!(bool, false, equal_bool, add_bool, div_bool);
|
||||
impl_scalar_ops!(String, String::new(), equal_string, add_string, div_string);
|
||||
179
crates/items_0/src/streamitem.rs
Normal file
179
crates/items_0/src/streamitem.rs
Normal file
@@ -0,0 +1,179 @@
|
||||
use crate::timebin::TimeBinned;
|
||||
use err::Error;
|
||||
use netpod::log::Level;
|
||||
use netpod::DiskStats;
|
||||
use netpod::EventDataReadStats;
|
||||
use netpod::RangeFilterStats;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
pub const TERM_FRAME_TYPE_ID: u32 = 0xaa01;
|
||||
pub const ERROR_FRAME_TYPE_ID: u32 = 0xaa02;
|
||||
pub const SITEMTY_NONSPEC_FRAME_TYPE_ID: u32 = 0xaa04;
|
||||
pub const EVENT_QUERY_JSON_STRING_FRAME: u32 = 0x100;
|
||||
pub const EVENTS_0D_FRAME_TYPE_ID: u32 = 0x500;
|
||||
pub const MIN_MAX_AVG_DIM_0_BINS_FRAME_TYPE_ID: u32 = 0x700;
|
||||
pub const MIN_MAX_AVG_DIM_1_BINS_FRAME_TYPE_ID: u32 = 0x800;
|
||||
pub const MIN_MAX_AVG_WAVE_BINS: u32 = 0xa00;
|
||||
pub const WAVE_EVENTS_FRAME_TYPE_ID: u32 = 0xb00;
|
||||
pub const LOG_FRAME_TYPE_ID: u32 = 0xc00;
|
||||
pub const STATS_FRAME_TYPE_ID: u32 = 0xd00;
|
||||
pub const RANGE_COMPLETE_FRAME_TYPE_ID: u32 = 0xe00;
|
||||
pub const EVENT_FULL_FRAME_TYPE_ID: u32 = 0x2200;
|
||||
pub const EVENTS_ITEM_FRAME_TYPE_ID: u32 = 0x2300;
|
||||
pub const STATS_EVENTS_FRAME_TYPE_ID: u32 = 0x2400;
|
||||
pub const ITEMS_2_CHANNEL_EVENTS_FRAME_TYPE_ID: u32 = 0x2500;
|
||||
pub const X_BINNED_SCALAR_EVENTS_FRAME_TYPE_ID: u32 = 0x8800;
|
||||
pub const X_BINNED_WAVE_EVENTS_FRAME_TYPE_ID: u32 = 0x8900;
|
||||
pub const DATABUFFER_EVENT_BLOB_FRAME_TYPE_ID: u32 = 0x8a00;
|
||||
|
||||
pub fn bool_is_false(j: &bool) -> bool {
|
||||
*j == false
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum RangeCompletableItem<T> {
|
||||
RangeComplete,
|
||||
Data(T),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum StatsItem {
|
||||
EventDataReadStats(EventDataReadStats),
|
||||
RangeFilterStats(RangeFilterStats),
|
||||
DiskStats(DiskStats),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum StreamItem<T> {
|
||||
DataItem(T),
|
||||
Log(LogItem),
|
||||
Stats(StatsItem),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct LogItem {
|
||||
pub node_ix: u32,
|
||||
#[serde(with = "levelserde")]
|
||||
pub level: Level,
|
||||
pub msg: String,
|
||||
}
|
||||
|
||||
impl LogItem {
|
||||
pub fn quick(level: Level, msg: String) -> Self {
|
||||
Self {
|
||||
level,
|
||||
msg,
|
||||
node_ix: 42,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type Sitemty<T> = Result<StreamItem<RangeCompletableItem<T>>, Error>;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! on_sitemty_range_complete {
|
||||
($item:expr, $ex:expr) => {
|
||||
if let Ok($crate::StreamItem::DataItem($crate::RangeCompletableItem::RangeComplete)) = $item {
|
||||
$ex
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! on_sitemty_data_old {
|
||||
($item:expr, $ex:expr) => {
|
||||
if let Ok($crate::streamitem::StreamItem::DataItem($crate::streamitem::RangeCompletableItem::Data(item))) =
|
||||
$item
|
||||
{
|
||||
$ex(item)
|
||||
} else {
|
||||
$item
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! on_sitemty_data {
|
||||
($item:expr, $ex:expr) => {{
|
||||
use $crate::streamitem::RangeCompletableItem;
|
||||
use $crate::streamitem::StreamItem;
|
||||
match $item {
|
||||
Ok(x) => match x {
|
||||
StreamItem::DataItem(x) => match x {
|
||||
RangeCompletableItem::Data(x) => $ex(x),
|
||||
RangeCompletableItem::RangeComplete => {
|
||||
Ok(StreamItem::DataItem(RangeCompletableItem::RangeComplete))
|
||||
}
|
||||
},
|
||||
StreamItem::Log(x) => Ok(StreamItem::Log(x)),
|
||||
StreamItem::Stats(x) => Ok(StreamItem::Stats(x)),
|
||||
},
|
||||
Err(x) => Err(x),
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
pub fn sitem_data<X>(x: X) -> Sitemty<X> {
|
||||
Ok(StreamItem::DataItem(RangeCompletableItem::Data(x)))
|
||||
}
|
||||
|
||||
mod levelserde {
|
||||
use super::Level;
|
||||
use serde::de::{self, Visitor};
|
||||
use serde::{Deserializer, Serializer};
|
||||
use std::fmt;
|
||||
|
||||
pub fn serialize<S>(t: &Level, se: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let g = match *t {
|
||||
Level::ERROR => 1,
|
||||
Level::WARN => 2,
|
||||
Level::INFO => 3,
|
||||
Level::DEBUG => 4,
|
||||
Level::TRACE => 5,
|
||||
};
|
||||
se.serialize_u32(g)
|
||||
}
|
||||
|
||||
struct VisitLevel;
|
||||
|
||||
impl VisitLevel {
|
||||
fn from_u32(x: u32) -> Level {
|
||||
match x {
|
||||
1 => Level::ERROR,
|
||||
2 => Level::WARN,
|
||||
3 => Level::INFO,
|
||||
4 => Level::DEBUG,
|
||||
5 => Level::TRACE,
|
||||
_ => Level::TRACE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Visitor<'de> for VisitLevel {
|
||||
type Value = Level;
|
||||
|
||||
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "expect Level code")
|
||||
}
|
||||
|
||||
fn visit_u64<E>(self, val: u64) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(VisitLevel::from_u32(val as _))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(de: D) -> Result<Level, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
de.deserialize_u32(VisitLevel)
|
||||
}
|
||||
}
|
||||
|
||||
erased_serde::serialize_trait_object!(TimeBinned);
|
||||
51
crates/items_0/src/subfr.rs
Normal file
51
crates/items_0/src/subfr.rs
Normal file
@@ -0,0 +1,51 @@
|
||||
pub trait SubFrId {
|
||||
const SUB: u32;
|
||||
}
|
||||
|
||||
impl SubFrId for u8 {
|
||||
const SUB: u32 = 0x03;
|
||||
}
|
||||
|
||||
impl SubFrId for u16 {
|
||||
const SUB: u32 = 0x05;
|
||||
}
|
||||
|
||||
impl SubFrId for u32 {
|
||||
const SUB: u32 = 0x08;
|
||||
}
|
||||
|
||||
impl SubFrId for u64 {
|
||||
const SUB: u32 = 0x0a;
|
||||
}
|
||||
|
||||
impl SubFrId for i8 {
|
||||
const SUB: u32 = 0x02;
|
||||
}
|
||||
|
||||
impl SubFrId for i16 {
|
||||
const SUB: u32 = 0x04;
|
||||
}
|
||||
|
||||
impl SubFrId for i32 {
|
||||
const SUB: u32 = 0x07;
|
||||
}
|
||||
|
||||
impl SubFrId for i64 {
|
||||
const SUB: u32 = 0x09;
|
||||
}
|
||||
|
||||
impl SubFrId for f32 {
|
||||
const SUB: u32 = 0x0b;
|
||||
}
|
||||
|
||||
impl SubFrId for f64 {
|
||||
const SUB: u32 = 0x0c;
|
||||
}
|
||||
|
||||
impl SubFrId for bool {
|
||||
const SUB: u32 = 0x0d;
|
||||
}
|
||||
|
||||
impl SubFrId for String {
|
||||
const SUB: u32 = 0x0e;
|
||||
}
|
||||
87
crates/items_0/src/test.rs
Normal file
87
crates/items_0/src/test.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
pub fn f32_cmp_near(x: f32, y: f32, abs: f32, rel: f32) -> bool {
|
||||
/*let x = {
|
||||
let mut a = x.to_le_bytes();
|
||||
a[0] &= 0xf0;
|
||||
f32::from_ne_bytes(a)
|
||||
};
|
||||
let y = {
|
||||
let mut a = y.to_le_bytes();
|
||||
a[0] &= 0xf0;
|
||||
f32::from_ne_bytes(a)
|
||||
};
|
||||
x == y*/
|
||||
let ad = (x - y).abs();
|
||||
ad <= abs || (ad / y).abs() <= rel
|
||||
}
|
||||
|
||||
pub fn f64_cmp_near(x: f64, y: f64, abs: f64, rel: f64) -> bool {
|
||||
/*let x = {
|
||||
let mut a = x.to_le_bytes();
|
||||
a[0] &= 0x00;
|
||||
a[1] &= 0x00;
|
||||
f64::from_ne_bytes(a)
|
||||
};
|
||||
let y = {
|
||||
let mut a = y.to_le_bytes();
|
||||
a[0] &= 0x00;
|
||||
a[1] &= 0x00;
|
||||
f64::from_ne_bytes(a)
|
||||
};
|
||||
x == y*/
|
||||
let ad = (x - y).abs();
|
||||
ad <= abs || (ad / y).abs() <= rel
|
||||
}
|
||||
|
||||
pub fn f32_iter_cmp_near<A, B>(a: A, b: B, abs: f32, rel: f32) -> bool
|
||||
where
|
||||
A: IntoIterator<Item = f32>,
|
||||
B: IntoIterator<Item = f32>,
|
||||
{
|
||||
let mut a = a.into_iter();
|
||||
let mut b = b.into_iter();
|
||||
loop {
|
||||
let x = a.next();
|
||||
let y = b.next();
|
||||
if let (Some(x), Some(y)) = (x, y) {
|
||||
if !f32_cmp_near(x, y, abs, rel) {
|
||||
return false;
|
||||
}
|
||||
} else if x.is_some() || y.is_some() {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn f64_iter_cmp_near<A, B>(a: A, b: B, abs: f64, rel: f64) -> bool
|
||||
where
|
||||
A: IntoIterator<Item = f64>,
|
||||
B: IntoIterator<Item = f64>,
|
||||
{
|
||||
let mut a = a.into_iter();
|
||||
let mut b = b.into_iter();
|
||||
loop {
|
||||
let x = a.next();
|
||||
let y = b.next();
|
||||
if let (Some(x), Some(y)) = (x, y) {
|
||||
if !f64_cmp_near(x, y, abs, rel) {
|
||||
return false;
|
||||
}
|
||||
} else if x.is_some() || y.is_some() {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_f32_iter_cmp_near() {
|
||||
let a = [-127.553e17];
|
||||
let b = [-127.554e17];
|
||||
assert_eq!(f32_iter_cmp_near(a, b, 0.000001, 0.000001), false);
|
||||
let a = [-127.55300e17];
|
||||
let b = [-127.55301e17];
|
||||
assert_eq!(f32_iter_cmp_near(a, b, 0.000001, 0.000001), true);
|
||||
}
|
||||
473
crates/items_0/src/timebin.rs
Normal file
473
crates/items_0/src/timebin.rs
Normal file
@@ -0,0 +1,473 @@
|
||||
pub mod timebinimpl;
|
||||
|
||||
use crate::collect_s::Collectable;
|
||||
use crate::collect_s::Collector;
|
||||
use crate::collect_s::ToJsonResult;
|
||||
use crate::overlap::RangeOverlapInfo;
|
||||
use crate::AsAnyMut;
|
||||
use crate::AsAnyRef;
|
||||
use crate::Events;
|
||||
use crate::Resettable;
|
||||
use crate::TypeName;
|
||||
use crate::WithLen;
|
||||
use err::Error;
|
||||
use netpod::log::*;
|
||||
use netpod::range::evrange::SeriesRange;
|
||||
use netpod::BinnedRangeEnum;
|
||||
use std::any::Any;
|
||||
use std::fmt;
|
||||
use std::ops::Range;
|
||||
|
||||
// TODO can probably be removed.
|
||||
pub trait TimeBins {
|
||||
fn ts_min(&self) -> Option<u64>;
|
||||
fn ts_max(&self) -> Option<u64>;
|
||||
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<Self::Output>;
|
||||
|
||||
/// 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<Self::Output>;
|
||||
|
||||
fn append_empty_until_end(&mut self);
|
||||
}
|
||||
|
||||
pub trait TimeBinnableTy: fmt::Debug + WithLen + Send + Sized {
|
||||
type TimeBinner: TimeBinnerTy<Input = Self>;
|
||||
|
||||
fn time_binner_new(&self, binrange: BinnedRangeEnum, do_time_weight: bool) -> Self::TimeBinner;
|
||||
}
|
||||
|
||||
/// Data in time-binned form.
|
||||
pub trait TimeBinned: Any + TypeName + TimeBinnable + Resettable + Collectable + erased_serde::Serialize {
|
||||
fn clone_box_time_binned(&self) -> Box<dyn TimeBinned>;
|
||||
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 Collectable;
|
||||
fn edges_slice(&self) -> (&[u64], &[u64]);
|
||||
fn counts(&self) -> &[u64];
|
||||
fn mins(&self) -> Vec<f32>;
|
||||
fn maxs(&self) -> Vec<f32>;
|
||||
fn avgs(&self) -> Vec<f32>;
|
||||
fn validate(&self) -> Result<(), String>;
|
||||
fn empty_like_self_box_time_binned(&self) -> Box<dyn TimeBinned>;
|
||||
fn to_simple_bins_f32(&mut self) -> Box<dyn TimeBinned>;
|
||||
fn drain_into_tb(&mut self, dst: &mut dyn TimeBinned, range: Range<usize>) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
impl Clone for Box<dyn TimeBinned> {
|
||||
fn clone(&self) -> Self {
|
||||
self.clone_box_time_binned()
|
||||
}
|
||||
}
|
||||
|
||||
impl RangeOverlapInfo for Box<dyn TimeBinned> {
|
||||
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<dyn TimeBinned> {
|
||||
fn time_binner_new(&self, binrange: BinnedRangeEnum, do_time_weight: bool) -> Box<dyn TimeBinner> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn to_box_to_json_result(&self) -> Box<dyn ToJsonResult> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
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<Box<dyn TimeBinned>>;
|
||||
|
||||
/// 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<dyn TimeBinned>;
|
||||
|
||||
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 + Collectable + 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) -> Box<dyn TimeBinner>;
|
||||
// TODO just a helper for the empty result.
|
||||
fn to_box_to_json_result(&self) -> Box<dyn ToJsonResult>;
|
||||
}
|
||||
|
||||
impl WithLen for Box<dyn TimeBinnable> {
|
||||
fn len(&self) -> usize {
|
||||
WithLen::len(self.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl RangeOverlapInfo for Box<dyn TimeBinnable> {
|
||||
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<dyn TimeBinnable> {
|
||||
fn time_binner_new(&self, binrange: BinnedRangeEnum, do_time_weight: bool) -> Box<dyn TimeBinner> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn to_box_to_json_result(&self) -> Box<dyn ToJsonResult> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl RangeOverlapInfo for Box<dyn Events> {
|
||||
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<dyn Events> {
|
||||
fn time_binner_new(&self, binrange: BinnedRangeEnum, do_time_weight: bool) -> Box<dyn TimeBinner> {
|
||||
TimeBinnable::time_binner_new(self.as_ref(), binrange, do_time_weight)
|
||||
}
|
||||
|
||||
fn to_box_to_json_result(&self) -> Box<dyn ToJsonResult> {
|
||||
TimeBinnable::to_box_to_json_result(self.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeName for Box<dyn TimeBinnable> {
|
||||
fn type_name(&self) -> String {
|
||||
format!("Box<dyn TimeBinnable> TODO TypeName for Box<dyn TimeBinnable>")
|
||||
}
|
||||
}
|
||||
|
||||
impl Collectable for Box<dyn TimeBinnable> {
|
||||
fn new_collector(&self) -> Box<dyn Collector> {
|
||||
self.as_ref().new_collector()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TimeBinnerDynStruct {
|
||||
binrange: BinnedRangeEnum,
|
||||
do_time_weight: bool,
|
||||
binner: Option<Box<dyn TimeBinner>>,
|
||||
}
|
||||
|
||||
impl TimeBinnerDynStruct {
|
||||
pub fn type_name() -> &'static str {
|
||||
std::any::type_name::<Self>()
|
||||
}
|
||||
|
||||
pub fn new(binrange: BinnedRangeEnum, do_time_weight: bool, binner: Box<dyn TimeBinner>) -> Self {
|
||||
Self {
|
||||
binrange,
|
||||
do_time_weight,
|
||||
binner: Some(binner),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TimeBinnerTy for TimeBinnerDynStruct {
|
||||
type Input = Box<dyn TimeBinnable>;
|
||||
type Output = Box<dyn TimeBinned>;
|
||||
|
||||
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.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<Self::Output> {
|
||||
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<Self::Output> {
|
||||
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<Box<dyn TimeBinned>> {
|
||||
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<dyn TimeBinned> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn append_empty_until_end(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TimeBinnerDynStruct2 {
|
||||
binrange: BinnedRangeEnum,
|
||||
do_time_weight: bool,
|
||||
binner: Option<Box<dyn TimeBinner>>,
|
||||
}
|
||||
|
||||
impl TimeBinnerDynStruct2 {
|
||||
pub fn type_name() -> &'static str {
|
||||
std::any::type_name::<Self>()
|
||||
}
|
||||
|
||||
pub fn new(binrange: BinnedRangeEnum, do_time_weight: bool, binner: Box<dyn TimeBinner>) -> Self {
|
||||
Self {
|
||||
binrange,
|
||||
do_time_weight,
|
||||
binner: Some(binner),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TimeBinnerTy for TimeBinnerDynStruct2 {
|
||||
type Input = Box<dyn TimeBinned>;
|
||||
type Output = Box<dyn TimeBinned>;
|
||||
|
||||
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.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<Self::Output> {
|
||||
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<Self::Output> {
|
||||
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 TimeBinnerDynStruct2 {
|
||||
fn ingest(&mut self, item: &mut dyn TimeBinnable) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bins_ready_count(&self) -> usize {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bins_ready(&mut self) -> Option<Box<dyn TimeBinned>> {
|
||||
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<dyn TimeBinned> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn append_empty_until_end(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl TimeBinnableTy for Box<dyn TimeBinnable> {
|
||||
type TimeBinner = TimeBinnerDynStruct;
|
||||
|
||||
fn time_binner_new(&self, binrange: BinnedRangeEnum, do_time_weight: bool) -> Self::TimeBinner {
|
||||
let binner = self.as_ref().time_binner_new(binrange.clone(), do_time_weight);
|
||||
TimeBinnerDynStruct::new(binrange, do_time_weight, binner)
|
||||
}
|
||||
}
|
||||
|
||||
impl TimeBinnableTy for Box<dyn TimeBinned> {
|
||||
type TimeBinner = TimeBinnerDynStruct2;
|
||||
|
||||
fn time_binner_new(&self, binrange: BinnedRangeEnum, do_time_weight: bool) -> Self::TimeBinner {
|
||||
let binner = self
|
||||
.as_time_binnable_ref()
|
||||
.time_binner_new(binrange.clone(), do_time_weight);
|
||||
TimeBinnerDynStruct2::new(binrange, do_time_weight, binner)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TimeBinnerIngest: fmt::Debug + TypeName + Send {
|
||||
fn ingest_inrange(&mut self, item: &mut dyn TimeBinnable) -> Result<(), Error>;
|
||||
}
|
||||
199
crates/items_0/src/timebin/timebinimpl.rs
Normal file
199
crates/items_0/src/timebin/timebinimpl.rs
Normal file
@@ -0,0 +1,199 @@
|
||||
#![allow(unused)]
|
||||
use crate::timebin::TimeBinnable;
|
||||
use crate::timebin::TimeBinned;
|
||||
use crate::timebin::TimeBinner;
|
||||
use crate::timebin::TimeBinnerIngest;
|
||||
use crate::TypeName;
|
||||
use netpod::log::*;
|
||||
use netpod::range::evrange::NanoRange;
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! trace2 {
|
||||
($($arg:tt)*) => { trace!($($arg)*) };
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! trace_ingest {
|
||||
($($arg:tt)*) => { trace!($($arg)*) };
|
||||
}
|
||||
|
||||
#[cfg(DISABLED)]
|
||||
impl<T> TimeBinner for T
|
||||
where
|
||||
T: TimeBinnerIngest,
|
||||
{
|
||||
fn bins_ready_count(&self) -> usize {
|
||||
match &self.ready {
|
||||
Some(k) => k.len(),
|
||||
None => 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn bins_ready(&mut self) -> Option<Box<dyn TimeBinned>> {
|
||||
match self.ready.take() {
|
||||
Some(k) => Some(Box::new(k)),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn ingest(&mut self, item: &mut dyn TimeBinnable) {
|
||||
trace2!(
|
||||
"TimeBinner for {} ingest agg.range {:?} item {:?}",
|
||||
self.type_name(),
|
||||
self.agg.range(),
|
||||
item
|
||||
);
|
||||
if item.len() == 0 {
|
||||
// Return already here, RangeOverlapInfo would not give much sense.
|
||||
return;
|
||||
}
|
||||
// TODO optimize by remembering at which event array index we have arrived.
|
||||
// That needs modified interfaces which can take and yield the start and latest index.
|
||||
loop {
|
||||
while item.starts_after(self.agg.range()) {
|
||||
trace!(
|
||||
"{} IGNORE ITEM AND CYCLE BECAUSE item.starts_after",
|
||||
self.type_name()
|
||||
);
|
||||
self.cycle();
|
||||
if self.rng.is_none() {
|
||||
warn!("{} no more bin in edges B", self.type_name());
|
||||
return;
|
||||
}
|
||||
}
|
||||
if item.ends_before(self.agg.range()) {
|
||||
trace!("{} IGNORE ITEM BECAUSE ends_before", self.type_name());
|
||||
return;
|
||||
} else {
|
||||
if self.rng.is_none() {
|
||||
trace!("{} no more bin in edges D", self.type_name());
|
||||
return;
|
||||
} else {
|
||||
match TimeBinnerIngest::ingest_inrange(self, item) {
|
||||
Ok(()) => {
|
||||
if item.ends_after(self.agg.range()) {
|
||||
trace_ingest!("{} FED ITEM, ENDS AFTER.", self.type_name());
|
||||
self.cycle();
|
||||
if self.rng.is_none() {
|
||||
warn!("{} no more bin in edges C", self.type_name());
|
||||
return;
|
||||
} else {
|
||||
trace_ingest!("{} FED ITEM, CYCLED, CONTINUE.", self.type_name());
|
||||
}
|
||||
} else {
|
||||
trace_ingest!("{} FED ITEM.", self.type_name());
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("{}::ingest {}", self.type_name(), e);
|
||||
}
|
||||
}
|
||||
/*
|
||||
// Move to TimeBinnerIngest
|
||||
if let Some(item) = item
|
||||
.as_any_ref()
|
||||
// TODO make statically sure that we attempt to cast to the correct type here:
|
||||
.downcast_ref::<<EventsDim0Aggregator<STY> as TimeBinnableTypeAggregator>::Input>()
|
||||
{
|
||||
// TODO collect statistics associated with this request:
|
||||
trace_ingest!("{self_name} FEED THE ITEM...");
|
||||
self.agg.ingest(item);
|
||||
} else {
|
||||
error!("{self_name}::ingest unexpected item type");
|
||||
};
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn push_in_progress(&mut self, push_empty: bool) {
|
||||
trace!("{}::push_in_progress push_empty {push_empty}", self.type_name());
|
||||
// TODO expand should be derived from AggKind. Is it still required after all?
|
||||
// TODO here, the expand means that agg will assume that the current value is kept constant during
|
||||
// the rest of the time range.
|
||||
if self.rng.is_none() {
|
||||
} else {
|
||||
let expand = true;
|
||||
let range_next = self.next_bin_range();
|
||||
self.rng = range_next.clone();
|
||||
let mut bins = if let Some(range_next) = range_next {
|
||||
self.agg.result_reset(range_next, expand)
|
||||
} else {
|
||||
// Acts as placeholder
|
||||
let range_next = NanoRange {
|
||||
beg: u64::MAX - 1,
|
||||
end: u64::MAX,
|
||||
};
|
||||
self.agg.result_reset(range_next.into(), expand)
|
||||
};
|
||||
if bins.len() != 1 {
|
||||
error!("{}::push_in_progress bins.len() {}", self.type_name(), bins.len());
|
||||
return;
|
||||
} else {
|
||||
if push_empty || bins.counts[0] != 0 {
|
||||
match self.ready.as_mut() {
|
||||
Some(ready) => {
|
||||
ready.append_all_from(&mut bins);
|
||||
}
|
||||
None => {
|
||||
self.ready = Some(bins);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn cycle(&mut self) {
|
||||
trace!("{}::cycle", self.type_name());
|
||||
// TODO refactor this logic.
|
||||
let n = self.bins_ready_count();
|
||||
self.push_in_progress(true);
|
||||
if self.bins_ready_count() == n {
|
||||
let range_next = self.next_bin_range();
|
||||
self.rng = range_next.clone();
|
||||
if let Some(range) = range_next {
|
||||
/*
|
||||
TODO Move out to trait.
|
||||
let mut bins = BinsDim0::empty();
|
||||
if range.is_time() {
|
||||
bins.append_zero(range.beg_u64(), range.end_u64());
|
||||
} else {
|
||||
error!("TODO {self_name}::cycle is_pulse");
|
||||
}
|
||||
match self.ready.as_mut() {
|
||||
Some(ready) => {
|
||||
ready.append_all_from(&mut bins);
|
||||
}
|
||||
None => {
|
||||
self.ready = Some(bins);
|
||||
}
|
||||
}
|
||||
*/
|
||||
if self.bins_ready_count() <= n {
|
||||
error!("{}::cycle failed to push a zero bin", self.type_name());
|
||||
}
|
||||
} else {
|
||||
warn!(
|
||||
"{}::cycle no in-progress bin pushed, but also no more bin to add as zero-bin",
|
||||
self.type_name()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_range_complete(&mut self) {
|
||||
self.range_final = true;
|
||||
}
|
||||
|
||||
fn empty(&self) -> Box<dyn TimeBinned> {
|
||||
/*
|
||||
TODO factor out to trait.
|
||||
let ret = <EventsDim0Aggregator<STY> as TimeBinnableTypeAggregator>::Output::empty();
|
||||
*/
|
||||
let ret = todo!();
|
||||
Box::new(ret)
|
||||
}
|
||||
}
|
||||
189
crates/items_0/src/transform.rs
Normal file
189
crates/items_0/src/transform.rs
Normal file
@@ -0,0 +1,189 @@
|
||||
use crate::collect_s::Collectable;
|
||||
use crate::collect_s::Collected;
|
||||
use crate::streamitem::RangeCompletableItem;
|
||||
use crate::streamitem::Sitemty;
|
||||
use crate::streamitem::StreamItem;
|
||||
use crate::timebin::TimeBinnable;
|
||||
use crate::Events;
|
||||
use err::Error;
|
||||
use futures_util::stream;
|
||||
use futures_util::Future;
|
||||
use futures_util::Stream;
|
||||
use futures_util::StreamExt;
|
||||
use std::pin::Pin;
|
||||
use std::task::Context;
|
||||
use std::task::Poll;
|
||||
|
||||
pub trait EventStreamTrait: Stream<Item = Sitemty<Box<dyn Events>>> + WithTransformProperties + Send {}
|
||||
|
||||
pub trait TimeBinnableStreamTrait:
|
||||
Stream<Item = Sitemty<Box<dyn TimeBinnable>>> + WithTransformProperties + Send
|
||||
{
|
||||
}
|
||||
|
||||
pub trait CollectableStreamTrait:
|
||||
Stream<Item = Sitemty<Box<dyn Collectable>>> + WithTransformProperties + Send
|
||||
{
|
||||
}
|
||||
|
||||
pub struct EventTransformProperties {
|
||||
pub needs_value: bool,
|
||||
}
|
||||
|
||||
pub struct TransformProperties {
|
||||
pub needs_one_before_range: bool,
|
||||
pub needs_value: bool,
|
||||
}
|
||||
|
||||
pub trait WithTransformProperties {
|
||||
fn query_transform_properties(&self) -> TransformProperties;
|
||||
}
|
||||
|
||||
impl<T> WithTransformProperties for Box<T>
|
||||
where
|
||||
T: WithTransformProperties,
|
||||
{
|
||||
fn query_transform_properties(&self) -> TransformProperties {
|
||||
self.as_ref().query_transform_properties()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> WithTransformProperties for Pin<Box<T>>
|
||||
where
|
||||
T: WithTransformProperties,
|
||||
{
|
||||
fn query_transform_properties(&self) -> TransformProperties {
|
||||
self.as_ref().query_transform_properties()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait EventTransform: WithTransformProperties + Send {
|
||||
fn transform(&mut self, src: Box<dyn Events>) -> Box<dyn Events>;
|
||||
}
|
||||
|
||||
impl<T> EventTransform for Box<T>
|
||||
where
|
||||
T: EventTransform,
|
||||
{
|
||||
fn transform(&mut self, src: Box<dyn Events>) -> Box<dyn Events> {
|
||||
self.as_mut().transform(src)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> EventTransform for Pin<Box<T>>
|
||||
where
|
||||
T: EventTransform,
|
||||
{
|
||||
fn transform(&mut self, src: Box<dyn Events>) -> Box<dyn Events> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IdentityTransform {}
|
||||
|
||||
impl IdentityTransform {
|
||||
pub fn default() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl WithTransformProperties for IdentityTransform {
|
||||
fn query_transform_properties(&self) -> TransformProperties {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl EventTransform for IdentityTransform {
|
||||
fn transform(&mut self, src: Box<dyn Events>) -> Box<dyn Events> {
|
||||
src
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TransformEvent(pub Box<dyn EventTransform>);
|
||||
|
||||
impl WithTransformProperties for TransformEvent {
|
||||
fn query_transform_properties(&self) -> TransformProperties {
|
||||
self.0.query_transform_properties()
|
||||
}
|
||||
}
|
||||
|
||||
impl EventTransform for TransformEvent {
|
||||
fn transform(&mut self, src: Box<dyn Events>) -> Box<dyn Events> {
|
||||
self.0.transform(src)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> WithTransformProperties for stream::Iter<T> {
|
||||
fn query_transform_properties(&self) -> TransformProperties {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> EventStreamTrait for stream::Iter<T> where
|
||||
T: core::iter::Iterator<Item = Sitemty<Box<(dyn Events + 'static)>>> + Send
|
||||
{
|
||||
}
|
||||
|
||||
pub struct EventStreamBox(pub Pin<Box<dyn EventStreamTrait>>);
|
||||
|
||||
impl<T> From<T> for EventStreamBox
|
||||
where
|
||||
T: Events,
|
||||
{
|
||||
fn from(value: T) -> Self {
|
||||
let item = Ok(StreamItem::DataItem(RangeCompletableItem::Data(Box::new(value) as _)));
|
||||
let x = stream::iter(vec![item]);
|
||||
Self(Box::pin(x))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TimeBinnableStreamBox(pub Pin<Box<dyn TimeBinnableStreamTrait>>);
|
||||
|
||||
impl WithTransformProperties for TimeBinnableStreamBox {
|
||||
fn query_transform_properties(&self) -> TransformProperties {
|
||||
self.0.query_transform_properties()
|
||||
}
|
||||
}
|
||||
|
||||
impl Stream for TimeBinnableStreamBox {
|
||||
type Item = <dyn TimeBinnableStreamTrait as Stream>::Item;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
self.0.poll_next_unpin(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl TimeBinnableStreamTrait for TimeBinnableStreamBox {}
|
||||
|
||||
pub struct CollectableStreamBox(pub Pin<Box<dyn CollectableStreamTrait>>);
|
||||
|
||||
impl Stream for CollectableStreamBox {
|
||||
type Item = Sitemty<Box<dyn Collectable>>;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
self.0.poll_next_unpin(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl WithTransformProperties for CollectableStreamBox {
|
||||
fn query_transform_properties(&self) -> TransformProperties {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl CollectableStreamTrait for CollectableStreamBox {}
|
||||
|
||||
impl<T> WithTransformProperties for stream::Empty<T> {
|
||||
fn query_transform_properties(&self) -> TransformProperties {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CollectableStreamTrait for stream::Empty<T>
|
||||
where
|
||||
T: Send,
|
||||
stream::Empty<T>: Stream<Item = Sitemty<Box<dyn Collectable>>>,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T> CollectableStreamTrait for Pin<Box<T>> where T: CollectableStreamTrait {}
|
||||
Reference in New Issue
Block a user