perspective_client/virtual_server/
data.rs1use std::error::Error;
14use std::ops::{Deref, DerefMut};
15
16use indexmap::IndexMap;
17use serde::Serialize;
18
19use crate::config::{Scalar, ViewConfig};
20
21#[derive(Debug, Serialize)]
26#[serde(untagged)]
27pub enum VirtualDataColumn {
28 Boolean(Vec<Option<bool>>),
29 String(Vec<Option<String>>),
30 Float(Vec<Option<f64>>),
31 Integer(Vec<Option<i32>>),
32 Datetime(Vec<Option<i64>>),
33 IntegerIndex(Vec<Option<Vec<i32>>>),
34 RowPath(Vec<Vec<Scalar>>),
35}
36
37#[derive(Debug, Serialize)]
42#[serde(untagged)]
43pub enum VirtualDataCell {
44 Boolean(Option<bool>),
45 String(Option<String>),
46 Float(Option<f64>),
47 Integer(Option<i32>),
48 Datetime(Option<i64>),
49 IntegerIndex(Option<Vec<i32>>),
50 RowPath(Vec<Scalar>),
51}
52
53impl VirtualDataColumn {
54 pub fn is_empty(&self) -> bool {
56 match self {
57 VirtualDataColumn::Boolean(v) => v.is_empty(),
58 VirtualDataColumn::String(v) => v.is_empty(),
59 VirtualDataColumn::Float(v) => v.is_empty(),
60 VirtualDataColumn::Integer(v) => v.is_empty(),
61 VirtualDataColumn::Datetime(v) => v.is_empty(),
62 VirtualDataColumn::IntegerIndex(v) => v.is_empty(),
63 VirtualDataColumn::RowPath(v) => v.is_empty(),
64 }
65 }
66
67 pub fn len(&self) -> usize {
69 match self {
70 VirtualDataColumn::Boolean(v) => v.len(),
71 VirtualDataColumn::String(v) => v.len(),
72 VirtualDataColumn::Float(v) => v.len(),
73 VirtualDataColumn::Integer(v) => v.len(),
74 VirtualDataColumn::Datetime(v) => v.len(),
75 VirtualDataColumn::IntegerIndex(v) => v.len(),
76 VirtualDataColumn::RowPath(v) => v.len(),
77 }
78 }
79}
80
81pub trait SetVirtualDataColumn {
87 fn write_to(self, col: &mut VirtualDataColumn) -> Result<(), &'static str>;
91
92 fn new_column() -> VirtualDataColumn;
94
95 fn to_scalar(self) -> Scalar;
97}
98
99macro_rules! template_psp {
100 ($t:ty, $u:ident, $v:ident, $w:ty) => {
101 impl SetVirtualDataColumn for Option<$t> {
102 fn write_to(self, col: &mut VirtualDataColumn) -> Result<(), &'static str> {
103 if let VirtualDataColumn::$u(x) = col {
104 x.push(self);
105 Ok(())
106 } else {
107 Err("Bad type")
108 }
109 }
110
111 fn new_column() -> VirtualDataColumn {
112 VirtualDataColumn::$u(vec![])
113 }
114
115 fn to_scalar(self) -> Scalar {
116 if let Some(x) = self {
117 Scalar::$v(x as $w)
118 } else {
119 Scalar::Null
120 }
121 }
122 }
123 };
124}
125
126template_psp!(String, String, String, String);
127template_psp!(f64, Float, Float, f64);
128template_psp!(i32, Integer, Float, f64);
129template_psp!(i64, Datetime, Float, f64);
130template_psp!(bool, Boolean, Bool, bool);
131
132#[derive(Debug, Serialize)]
137#[serde(transparent)]
138pub struct VirtualDataSlice(
139 #[serde(skip)] ViewConfig,
140 IndexMap<String, VirtualDataColumn>,
141);
142
143impl Deref for VirtualDataSlice {
144 type Target = IndexMap<String, VirtualDataColumn>;
145
146 fn deref(&self) -> &Self::Target {
147 &self.1
148 }
149}
150
151impl DerefMut for VirtualDataSlice {
152 fn deref_mut(&mut self) -> &mut Self::Target {
153 &mut self.1
154 }
155}
156
157impl VirtualDataSlice {
158 pub fn new(config: ViewConfig) -> Self {
159 VirtualDataSlice(config, IndexMap::default())
160 }
161
162 pub(super) fn to_rows(&self) -> Vec<IndexMap<String, VirtualDataCell>> {
163 let num_rows = self.values().next().map(|x| x.len()).unwrap_or(0);
164 (0..num_rows)
165 .map(|row_idx| {
166 self.iter()
167 .map(|(col_name, col_data)| {
168 let row_value = match col_data {
169 VirtualDataColumn::Boolean(v) => VirtualDataCell::Boolean(v[row_idx]),
170 VirtualDataColumn::String(v) => {
171 VirtualDataCell::String(v[row_idx].clone())
172 },
173 VirtualDataColumn::Float(v) => VirtualDataCell::Float(v[row_idx]),
174 VirtualDataColumn::Integer(v) => VirtualDataCell::Integer(v[row_idx]),
175 VirtualDataColumn::Datetime(v) => VirtualDataCell::Datetime(v[row_idx]),
176 VirtualDataColumn::IntegerIndex(v) => {
177 VirtualDataCell::IntegerIndex(v[row_idx].clone())
178 },
179 VirtualDataColumn::RowPath(v) => {
180 VirtualDataCell::RowPath(v[row_idx].clone())
181 },
182 };
183 (col_name.clone(), row_value)
184 })
185 .collect()
186 })
187 .collect()
188 }
189
190 pub fn set_col<T: SetVirtualDataColumn>(
198 &mut self,
199 name: &str,
200 grouping_id: Option<usize>,
201 index: usize,
202 value: T,
203 ) -> Result<(), Box<dyn Error>> {
204 if name.starts_with("__ROW_PATH_") {
205 let group_by_index: u32 = name[11..name.len() - 2].parse()?;
206 let max_grouping_id = 2_i32.pow((self.0.group_by.len() as u32) - group_by_index) - 1;
207 if grouping_id.map(|x| x as i32).unwrap_or(i32::MAX) < max_grouping_id
208 || !self.0.split_by.is_empty()
209 {
210 if !self.contains_key("__ROW_PATH__") {
211 self.insert(
212 "__ROW_PATH__".to_owned(),
213 VirtualDataColumn::RowPath(vec![]),
214 );
215 }
216
217 let Some(VirtualDataColumn::RowPath(col)) = self.get_mut("__ROW_PATH__") else {
218 return Err("__ROW_PATH__ column has unexpected type".into());
219 };
220
221 if let Some(row) = col.get_mut(index) {
222 let scalar = value.to_scalar();
223 row.push(scalar);
224 } else {
225 while col.len() < index {
226 col.push(vec![])
227 }
228
229 let scalar = value.to_scalar();
230 col.push(vec![scalar]);
231 }
232 }
233
234 Ok(())
235 } else {
236 if !self.contains_key(name) {
237 self.insert(name.to_owned(), T::new_column());
238 }
239
240 let col = self
241 .get_mut(name)
242 .ok_or_else(|| format!("Column '{}' not found after insertion", name))?;
243
244 Ok(value.write_to(col)?)
245 }
246 }
247}