perspective_client/config/
filters.rs1use std::fmt::Display;
14
15use itertools::Itertools;
16use serde::{Deserialize, Serialize};
17use ts_rs::TS;
18
19use crate::proto;
20use crate::proto::scalar;
21
22#[derive(Clone, Deserialize, Debug, PartialEq, Serialize, TS)]
25#[serde(untagged)]
26pub enum Scalar {
27 Float(f64),
28 String(String),
29 Bool(bool),
30 Null,
34}
35
36impl From<&str> for Scalar {
37 fn from(value: &str) -> Self {
38 Self::String(value.into())
39 }
40}
41
42impl Default for Scalar {
43 fn default() -> Self {
44 Self::Null
45 }
46}
47
48impl Display for Scalar {
49 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
50 match self {
51 Self::Float(x) => write!(fmt, "{x}"),
52 Self::String(x) => write!(fmt, "{x}"),
53 Self::Bool(x) => write!(fmt, "{x}"),
54 Self::Null => write!(fmt, ""),
55 }
56 }
57}
58
59#[derive(Clone, Deserialize, Debug, PartialEq, Serialize, TS)]
60#[serde(untagged)]
61pub enum FilterTerm {
62 Array(Vec<Scalar>),
63 Scalar(#[serde(default)] Scalar),
64}
65
66impl<'a, T> From<T> for FilterTerm
67where
68 T: AsRef<[&'a str]>,
69{
70 fn from(value: T) -> Self {
71 Self::Array(value.as_ref().iter().map(|x| (*x).into()).collect())
72 }
73}
74
75impl Default for FilterTerm {
76 fn default() -> Self {
77 Self::Scalar(Scalar::Null)
78 }
79}
80
81impl Display for FilterTerm {
82 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
83 match self {
84 Self::Scalar(x) => {
85 write!(fmt, "{x}")?;
86 },
87 Self::Array(xs) => write!(
88 fmt,
89 "{}",
90 Itertools::intersperse(xs.iter().map(|x| format!("{x}")), ",".to_owned())
91 .collect::<String>()
92 )?,
93 }
94
95 Ok(())
96 }
97}
98
99#[derive(Clone, Deserialize, Debug, PartialEq, Serialize, TS)]
100#[serde()]
101pub struct Filter(String, String, #[serde(default)] FilterTerm);
102
103impl Filter {
104 pub fn new<T>(column: &str, op: &str, term: T) -> Self
105 where
106 FilterTerm: From<T>,
107 {
108 Filter(column.to_string(), op.to_string(), term.into())
109 }
110
111 pub fn column(&self) -> &str {
112 self.0.as_str()
113 }
114
115 pub fn op(&self) -> &str {
116 self.1.as_str()
117 }
118
119 pub fn term(&self) -> &FilterTerm {
120 &self.2
121 }
122
123 pub fn column_mut(&mut self) -> &mut String {
124 &mut self.0
125 }
126
127 pub fn op_mut(&mut self) -> &mut String {
128 &mut self.1
129 }
130
131 pub fn term_mut(&mut self) -> &mut FilterTerm {
132 &mut self.2
133 }
134}
135
136#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, TS)]
137pub enum FilterReducer {
138 #[serde(rename = "and")]
139 And,
140 #[serde(rename = "or")]
141 Or,
142}
143
144impl Default for FilterReducer {
145 fn default() -> Self {
146 Self::And
147 }
148}
149
150impl From<Scalar> for proto::Scalar {
151 fn from(value: Scalar) -> Self {
152 match value {
153 Scalar::Float(x) => proto::Scalar {
154 scalar: Some(scalar::Scalar::Float(x)),
155 },
156 Scalar::String(x) => proto::Scalar {
157 scalar: Some(scalar::Scalar::String(x)),
158 },
159 Scalar::Bool(x) => proto::Scalar {
160 scalar: Some(scalar::Scalar::Bool(x)),
161 },
162 Scalar::Null => proto::Scalar {
163 scalar: Some(scalar::Scalar::Null(0)),
164 },
165 }
166 }
167}
168
169impl From<proto::Scalar> for Scalar {
170 fn from(value: proto::Scalar) -> Self {
171 match value.scalar {
172 Some(scalar::Scalar::Bool(x)) => Scalar::Bool(x),
173 Some(scalar::Scalar::String(x)) => Scalar::String(x),
174 Some(scalar::Scalar::Float(x)) => Scalar::Float(x),
175 Some(scalar::Scalar::Null(_)) => Scalar::Null,
176 None => Scalar::Null,
177 }
178 }
179}
180
181impl From<Filter> for proto::view_config::Filter {
182 fn from(value: Filter) -> Self {
183 proto::view_config::Filter {
184 column: value.0,
185 op: value.1,
186 value: match value.2 {
187 FilterTerm::Scalar(x) => vec![x.into()],
188 FilterTerm::Array(x) => x.into_iter().map(|x| x.into()).collect(),
189 },
190 }
191 }
192}
193
194impl From<proto::view_config::Filter> for Filter {
195 fn from(value: proto::view_config::Filter) -> Self {
196 Filter(
197 value.column,
198 value.op,
199 if value.value.len() == 1 {
200 FilterTerm::Scalar(value.value.into_iter().next().unwrap().into())
201 } else {
202 FilterTerm::Array(value.value.into_iter().map(|x| x.into()).collect())
203 },
204 )
205 }
206}