perspective_client/config/
aggregates.rs1use std::fmt::Display;
14
15use serde::{Deserialize, Serialize};
16use ts_rs::TS;
17
18use crate::proto::{ColumnType, view_config};
19
20#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize, TS)]
21#[serde(untagged)]
22pub enum Aggregate {
23 SingleAggregate(String),
24 MultiAggregate(String, Vec<String>),
25}
26
27impl Aggregate {
28 pub fn default_for(column_type: ColumnType) -> Self {
30 match column_type {
31 ColumnType::Integer | ColumnType::Float => Aggregate::SingleAggregate("sum".into()),
32 _ => Aggregate::SingleAggregate("count".into()),
33 }
34 }
35}
36
37impl From<&'static str> for Aggregate {
38 fn from(value: &'static str) -> Self {
39 if value.contains(" by ") {
40 let mut parts = value.split(" by ");
41 Aggregate::MultiAggregate(
42 parts.next().unwrap().into(),
43 parts.map(|x| x.into()).collect(),
44 )
45 } else {
46 Aggregate::SingleAggregate(value.into())
47 }
48 }
49}
50
51impl Display for Aggregate {
52 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
53 match self {
54 Self::SingleAggregate(x) => write!(fmt, "{x}")?,
55 Self::MultiAggregate(agg, x) => write!(fmt, "{} by {}", agg, x.join(", "))?,
56 };
57 Ok(())
58 }
59}
60
61impl From<Aggregate> for view_config::AggList {
62 fn from(value: Aggregate) -> Self {
63 view_config::AggList {
64 aggregations: match value {
65 Aggregate::SingleAggregate(x) => vec![x],
66 Aggregate::MultiAggregate(x, y) => {
67 vec![x, y.join(",")]
68 },
69 },
70 }
71 }
72}
73
74impl From<view_config::AggList> for Aggregate {
75 fn from(value: view_config::AggList) -> Self {
76 if value.aggregations.len() == 1 {
77 Aggregate::SingleAggregate(value.aggregations.first().unwrap().clone())
78 } else {
79 Aggregate::MultiAggregate(
80 value.aggregations.first().unwrap().clone(),
81 value
82 .aggregations
83 .get(1)
84 .unwrap()
85 .split(",")
86 .map(|x| x.to_owned())
87 .collect(),
88 )
89 }
90 }
91}