perspective_client/virtual_server/features.rs
1// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7// ┃ Copyright (c) 2017, the Perspective Authors. ┃
8// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9// ┃ This file is part of the Perspective library, distributed under the terms ┃
10// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
13use std::borrow::Cow;
14
15use indexmap::IndexMap;
16use serde::Deserialize;
17
18use crate::proto::get_features_resp::{AggregateArgs, AggregateOptions, ColumnTypeOptions};
19use crate::proto::{ColumnType, GetFeaturesResp};
20
21/// Describes the capabilities supported by a virtual server handler.
22///
23/// This struct is returned by
24/// [`VirtualServerHandler::get_features`](super::VirtualServerHandler::get_features)
25/// to inform clients about which operations are available.
26#[derive(Debug, Default, Deserialize)]
27pub struct Features<'a> {
28 /// Whether group-by aggregation is supported.
29 #[serde(default)]
30 pub group_by: bool,
31
32 /// Whether split-by (pivot) operations are supported.
33 #[serde(default)]
34 pub split_by: bool,
35
36 /// Available filter operators per column type.
37 #[serde(default)]
38 pub filter_ops: IndexMap<ColumnType, Vec<Cow<'a, str>>>,
39
40 /// Available aggregate functions per column type.
41 #[serde(default)]
42 pub aggregates: IndexMap<ColumnType, Vec<AggSpec<'a>>>,
43
44 /// Whether sorting is supported.
45 #[serde(default)]
46 pub sort: bool,
47
48 /// Whether computed expressions are supported.
49 #[serde(default)]
50 pub expressions: bool,
51
52 /// Whether update callbacks are supported.
53 #[serde(default)]
54 pub on_update: bool,
55}
56
57/// Specification for an aggregate function.
58///
59/// Aggregates can either take no additional arguments ([`AggSpec::Single`])
60/// or require column type arguments ([`AggSpec::Multiple`]).
61#[derive(Debug, Deserialize)]
62#[serde(untagged)]
63pub enum AggSpec<'a> {
64 /// An aggregate function with no additional arguments.
65 Single(Cow<'a, str>),
66 /// An aggregate function that requires column type arguments.
67 Multiple(Cow<'a, str>, Vec<ColumnType>),
68}
69
70impl<'a> From<Features<'a>> for GetFeaturesResp {
71 fn from(value: Features<'a>) -> GetFeaturesResp {
72 GetFeaturesResp {
73 group_by: value.group_by,
74 split_by: value.split_by,
75 expressions: value.expressions,
76 on_update: value.on_update,
77 sort: value.sort,
78 aggregates: value
79 .aggregates
80 .iter()
81 .map(|(dtype, aggs)| {
82 (*dtype as u32, AggregateOptions {
83 aggregates: aggs
84 .iter()
85 .map(|agg| match agg {
86 AggSpec::Single(cow) => AggregateArgs {
87 name: cow.to_string(),
88 args: vec![],
89 },
90 AggSpec::Multiple(cow, column_types) => AggregateArgs {
91 name: cow.to_string(),
92 args: column_types.iter().map(|x| *x as i32).collect(),
93 },
94 })
95 .collect(),
96 })
97 })
98 .collect(),
99 filter_ops: value
100 .filter_ops
101 .iter()
102 .map(|(ty, options)| {
103 (*ty as u32, ColumnTypeOptions {
104 options: options.iter().map(|x| (*x).to_string()).collect(),
105 })
106 })
107 .collect(),
108 }
109 }
110}