mod group;
mod params;
mod total;
use serde_json::{Map, Value};
use crate::metadata::{InputCardinality, NodeCategory, NodeMetadata};
use crate::processor::{
BatchFile, BatchInput, FileData, NodeInput, NodeOutput, NodeProcessor, OutputFile,
};
use crate::progress::ProgressReporter;
use crate::{BntoError, ProcessContext};
use params::{SummarizeParams, build_summarize_parameters};
pub struct Summarize;
impl Summarize {
pub fn new() -> Self {
Self
}
}
impl Default for Summarize {
fn default() -> Self {
Self::new()
}
}
impl NodeProcessor for Summarize {
fn name(&self) -> &str {
"summarize"
}
fn metadata(&self) -> NodeMetadata {
NodeMetadata {
node_type: "summarize".to_string(),
name: "Summarize".to_string(),
description: "Summarize items by metadata fields, one item per group with \
its count and the totals of numeric fields (sum_<field>). Groups \
keep first-seen order; the items summarized don't pass through."
.to_string(),
category: NodeCategory::Data,
accepts: vec![],
platforms: vec![
"browser".to_string(),
"cli".to_string(),
"desktop".to_string(),
],
parameters: build_summarize_parameters(),
input_cardinality: InputCardinality::Batch,
requires: vec![],
}
}
fn validate(&self, params: &Map<String, Value>) -> Vec<String> {
SummarizeParams::read(params).err().into_iter().collect()
}
fn process(
&self,
input: NodeInput,
progress: &ProgressReporter,
ctx: &dyn ProcessContext,
) -> Result<NodeOutput, BntoError> {
let file = BatchFile {
data: input.data,
filename: input.filename,
mime_type: input.mime_type,
metadata: Map::new(),
};
let batch = BatchInput {
files: vec![file],
params: input.params,
};
self.process_batch(batch, progress, ctx)
}
fn process_batch(
&self,
input: BatchInput,
_progress: &ProgressReporter,
_ctx: &dyn ProcessContext,
) -> Result<NodeOutput, BntoError> {
let params = SummarizeParams::read(&input.params).map_err(BntoError::InvalidInput)?;
let groups = group::summarize(&input.files, ¶ms).map_err(BntoError::InvalidInput)?;
let mut metadata = Map::new();
metadata.insert("groupCount".to_string(), groups.len().into());
let files = groups.into_iter().enumerate().map(summary_item).collect();
Ok(NodeOutput { files, metadata })
}
}
fn summary_item((i, metadata): (usize, Map<String, Value>)) -> OutputFile {
OutputFile {
data: FileData::Bytes(Vec::new()),
filename: format!("group{i}"),
mime_type: "application/octet-stream".to_string(),
metadata,
}
}
#[cfg(test)]
mod tests;