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