pub fn build_tree<D: Diagnostics + ?Sized>(
plan: &AxisPlan,
items: Vec<Record>,
diag: &mut D,
) -> Result<Vec<Cluster>, FaceError>Expand description
Cluster items according to plan, dispatching per-axis to the
appropriate strategy and recursing on within.
All §5.2, §5.3, and explicit §5.4 strategies are implemented:
Strategy::Exact, Strategy::Prefix, Strategy::Top,
Strategy::Bands, Strategy::Quantiles,
Strategy::Natural, Strategy::Similar. Future variants added to the
#[non_exhaustive] enum surface as FaceError::Unsupported until
their dispatch arms land.
§Errors
Returns FaceError::Unsupported only when the plan references a
Strategy variant added after this build (the #[non_exhaustive]
catchall).
§Examples
use face_core::{Axis, AxisPlan, NullDiagnostics, Record, build_tree};
use serde_json::json;
let axis: Axis = serde_json::from_value(json!({
"field": "kind",
"strategy": "exact",
"auto": false,
})).unwrap();
let plan = AxisPlan::leaf(axis);
let items = vec![json!({"kind": "a"}), json!({"kind": "b"}), json!({"kind": "a"})];
let records = Record::from_items(items, None);
let mut diag = NullDiagnostics;
let clusters = build_tree(&plan, records, &mut diag).unwrap();
assert_eq!(clusters.len(), 2);
// Sorted by count desc, label asc → "a" (2) before "b" (1).
assert_eq!(clusters[0].label, "a");
assert_eq!(clusters[0].total, 2);
assert_eq!(clusters[1].label, "b");
assert_eq!(clusters[1].total, 1);