use super::*;
use crate::errors::PointCloudError;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum ValueSummary {
#[doc(hidden)]
Null,
BoolSummary(BoolSummary),
NumberSummary(NumberSummary),
VectorSummary(VectorSummary),
StringSummary(StringSummary),
}
pub trait Summary {
fn add(&mut self, v: &Value) -> Result<(), PointCloudError>;
fn combine(v: &[&ValueSummary]) -> Result<ValueSummary, PointCloudError>;
fn to_json(&self) -> String;
}
impl Summary for ValueSummary {
fn add(&mut self, v: &Value) -> Result<(), PointCloudError> {
match (self, v) {
(ValueSummary::BoolSummary(bl), Value::Bool(..)) => bl.add(v),
(ValueSummary::NumberSummary(nl), Value::Number(..)) => nl.add(v),
(ValueSummary::VectorSummary(vl), Value::Vector(..)) => vl.add(v),
(ValueSummary::StringSummary(sl), Value::String(..)) => sl.add(v),
_ => {
panic!("Tried to add a natural number onto a real summary or something like that. Check your metadata!");
}
}
}
fn combine(v: &[&ValueSummary]) -> Result<ValueSummary, PointCloudError> {
match v[0] {
ValueSummary::BoolSummary(..) => BoolSummary::combine(v),
ValueSummary::NumberSummary(..) => NumberSummary::combine(v),
ValueSummary::VectorSummary(..) => VectorSummary::combine(v),
ValueSummary::StringSummary(..) => StringSummary::combine(v),
ValueSummary::Null => Err(PointCloudError::data_access(
0,
"Tried to merge Null summaries".to_string(),
)),
}
}
fn to_json(&self) -> String {
match self {
ValueSummary::BoolSummary(bl) => bl.to_json(),
ValueSummary::NumberSummary(nl) => nl.to_json(),
ValueSummary::VectorSummary(vl) => vl.to_json(),
ValueSummary::StringSummary(sl) => sl.to_json(),
_ => {
panic!("Tried to add a natural number onto a real summary or something like that. Check your metadata!");
}
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct MetaSummary {
pub summaries: IndexMap<String, ValueSummary>,
}
impl MetaSummary {
#[doc(hidden)]
pub fn new() -> MetaSummary {
let summaries = IndexMap::new();
MetaSummary { summaries }
}
#[doc(hidden)]
pub fn insert(&mut self, key: String, value_sum: ValueSummary) {
self.summaries.insert(key, value_sum);
}
#[doc(hidden)]
pub fn add(&mut self, label: &Metadata) -> Result<(), PointCloudError> {
for (k, v) in label.iter() {
match self.summaries.get_mut(k) {
Some(l) => l.add(v),
None => Err(PointCloudError::data_access(
0,
"label access error, no key".to_string(),
)),
}?;
}
Ok(())
}
#[doc(hidden)]
pub fn combine(metasummaries: &[MetaSummary]) -> Result<MetaSummary, PointCloudError> {
let mut summary_vecs: IndexMap<String, Vec<&ValueSummary>> = IndexMap::new();
for metasummary in metasummaries.iter() {
for (k, v) in &metasummary.summaries {
summary_vecs
.entry(k.to_string())
.or_insert(Vec::new())
.push(v);
}
}
let mut summaries: IndexMap<String, ValueSummary> = IndexMap::new();
for (k, v) in summary_vecs {
summaries.insert(k, ValueSummary::combine(&v)?);
}
Ok(MetaSummary { summaries })
}
pub fn get(&self, key: &str) -> Option<&ValueSummary> {
self.summaries.get(key)
}
pub fn to_json(&self) -> String {
let sum = self
.summaries
.iter()
.map(|(n, v)| format!("\"{}\":{}", n, v.to_json()))
.collect::<Vec<String>>()
.join(",");
format!("{{{}}}", sum)
}
}