use super::super::stats_collector::its_stats::ItsStats;
use super::trigger_stats::TriggerStats;
use crate::util::*;
#[derive(Default, PartialEq, Debug, Serialize, Deserialize)]
pub struct RdhStats {
rdhs_seen: u64,
rdhs_filtered: u64,
rdh_version: Option<u8>,
hbfs_seen: u32,
payload_size: u64,
data_format: Option<u8>,
links: Vec<u8>,
fee_id: Vec<u16>,
system_id: Option<SystemId>,
run_trigger_type: Option<(u32, Box<str>)>,
its_stats: ItsStats,
trigger_stats: TriggerStats,
}
impl RdhStats {
pub fn record_rdh_version(&mut self, version: u8) {
if self.rdh_version.is_some() {
panic!("Cannot set RDH version more than once!")
} else {
self.rdh_version = Some(version);
}
}
pub fn rdh_version(&self) -> u8 {
self.rdh_version
.expect("RDH version has not been recorded!")
}
pub fn record_data_format(&mut self, data_format: u8) {
if self.data_format.is_some() {
panic!("Cannot set Data format more than once!")
} else {
self.data_format = Some(data_format);
}
}
pub fn data_format(&self) -> u8 {
self.data_format.expect("Data format has not been recoded!")
}
pub fn record_link(&mut self, link_id: u8) {
self.links.push(link_id);
}
pub fn sort_links_observed(&mut self) {
self.links.sort_unstable();
}
pub fn links_as_slice(&self) -> &[u8] {
self.links.as_slice()
}
pub fn record_fee_observed(&mut self, fee_id: u16) {
if !self.fee_id.contains(&fee_id) {
self.fee_id.push(fee_id);
}
}
pub fn fee_ids_as_slice(&self) -> &[u16] {
self.fee_id.as_slice()
}
pub fn record_system_id(&mut self, system_id: SystemId) {
if self.system_id.is_none() {
self.system_id = Some(system_id);
} else {
panic!("Cannot set system ID more than once!")
}
}
pub fn system_id(&self) -> Option<SystemId> {
self.system_id
}
pub fn record_run_trigger_type(&mut self, run_trigger_type: (u32, Box<str>)) {
if self.run_trigger_type.is_none() {
self.run_trigger_type = Some(run_trigger_type);
} else {
panic!("Cannot set Run Trigger Type more than once!")
}
}
pub fn run_trigger_type(&self) -> (u32, Box<str>) {
self.run_trigger_type
.clone()
.expect("Run Trigger Type has not been recorded!")
}
pub fn record_trigger_type(&mut self, trigger_type: u32) {
self.trigger_stats.collect_stats(trigger_type);
}
pub fn trigger_stats(&self) -> &TriggerStats {
&self.trigger_stats
}
pub fn record_layer_stave_seen(&mut self, layer_stave: (u8, u8)) {
self.its_stats.record_layer_stave_seen(layer_stave);
}
pub fn layer_staves_as_slice(&self) -> &[(u8, u8)] {
self.its_stats.layer_staves_as_slice()
}
pub(super) fn add_payload_size(&mut self, payload_size: u64) {
self.payload_size += payload_size;
}
pub(crate) fn payload_size(&self) -> u64 {
self.payload_size
}
pub(crate) fn hbfs_seen(&self) -> u32 {
self.hbfs_seen
}
pub(super) fn add_hbfs_seen(&mut self, hbfs: u32) {
self.hbfs_seen += hbfs;
}
#[allow(dead_code)]
pub(super) fn incr_rdhs_seen(&mut self) {
self.rdhs_seen += 1;
}
pub(super) fn add_rdhs_seen(&mut self, rdhs_seen: u32) {
self.rdhs_seen += rdhs_seen as u64;
}
pub(crate) fn rdhs_seen(&self) -> u64 {
self.rdhs_seen
}
#[allow(dead_code)]
pub(super) fn incr_rdhs_filtered(&mut self) {
self.rdhs_filtered += 1;
}
pub(super) fn add_rdhs_filtered(&mut self, rdhs_filtered: u32) {
self.rdhs_filtered += rdhs_filtered as u64;
}
pub(crate) fn rdhs_filtered(&self) -> u64 {
self.rdhs_filtered
}
pub(crate) fn finalize(&mut self) {
self.sort_links_observed();
}
pub(super) fn validate_other(&self, other: &Self) -> Result<(), Vec<String>> {
let mut errs: Vec<String> = vec![];
if let Err(mut sub_errs) = self.its_stats.validate_other(&other.its_stats) {
errs.append(&mut sub_errs);
}
if let Err(mut sub_errs) = self.trigger_stats.validate_other(&other.trigger_stats) {
errs.append(&mut sub_errs);
}
let other_top_fields_only = Self {
rdhs_seen: other.rdhs_seen,
rdhs_filtered: other.rdhs_filtered,
rdh_version: other.rdh_version,
hbfs_seen: other.hbfs_seen,
payload_size: other.payload_size,
data_format: other.data_format,
links: other.links.clone(),
fee_id: other.fee_id.clone(),
system_id: other.system_id,
run_trigger_type: other.run_trigger_type.clone(),
its_stats: ItsStats::default(), trigger_stats: TriggerStats::default(), };
if let Err(mut local_top_field_errs) = self.validate_fields(&other_top_fields_only) {
errs.append(&mut local_top_field_errs);
}
if errs.is_empty() {
Ok(())
} else {
Err(errs)
}
}
crate::validate_fields!(
RdhStats,
rdhs_seen,
rdhs_filtered,
rdh_version,
hbfs_seen,
payload_size,
data_format,
links,
fee_id,
system_id,
run_trigger_type
);
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn test_serde_consistency() {
let mut rdh_stats = RdhStats {
rdhs_seen: 10,
rdhs_filtered: 0,
rdh_version: Some(7),
hbfs_seen: 0,
payload_size: 0,
data_format: Some(0),
links: vec![0, 1, 2, 3, 4, 5, 6],
fee_id: vec![8, 9, 10, 11, 12, 13, 14],
system_id: Some(SystemId::MFT),
run_trigger_type: Some((1, "Test".into())),
its_stats: ItsStats::default(),
trigger_stats: TriggerStats::default(),
};
rdh_stats.add_hbfs_seen(1);
let rdh_stats_ser_json = serde_json::to_string(&rdh_stats).unwrap();
println!("{}", serde_json::to_string_pretty(&rdh_stats).unwrap());
let rdh_stats_de_json: RdhStats = serde_json::from_str(&rdh_stats_ser_json).unwrap();
assert_eq!(rdh_stats, rdh_stats_de_json);
let rdh_stats_ser_toml = toml::to_string(&rdh_stats).unwrap();
println!("{}", rdh_stats_ser_toml);
let rdh_stats_de_toml: RdhStats = toml::from_str(&rdh_stats_ser_toml).unwrap();
assert_eq!(rdh_stats, rdh_stats_de_toml);
}
}