1use crate::spec::transform::aggregate::AggregateOpSpec;
2use crate::spec::values::{SignalExpressionSpec, SortOrderSpec};
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::HashMap;
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8pub struct ScaleSpec {
9 pub name: String,
10
11 #[serde(skip_serializing_if = "Option::is_none", rename = "type")]
12 pub type_: Option<ScaleTypeSpec>,
13
14 #[serde(skip_serializing_if = "Option::is_none")]
15 pub domain: Option<ScaleDomainSpec>,
16
17 #[serde(skip_serializing_if = "Option::is_none")]
18 pub range: Option<ScaleRangeSpec>,
19
20 #[serde(skip_serializing_if = "Option::is_none")]
21 pub bins: Option<ScaleBinsSpec>,
22
23 #[serde(flatten)]
24 pub extra: HashMap<String, Value>,
25}
26
27#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Hash, Eq)]
28#[serde(rename_all = "lowercase")]
29pub enum ScaleTypeSpec {
30 Linear,
32 Log,
33 Pow,
34 Sqrt,
35 Symlog,
36 Time,
37 Utc,
38 Sequential,
39
40 Ordinal,
42 Band,
43 Point,
44
45 Quantile,
47 Quantize,
48 Threshold,
49 #[serde(rename = "bin-ordinal")]
50 BinOrdinal,
51}
52
53impl Default for ScaleTypeSpec {
54 fn default() -> Self {
55 Self::Linear
56 }
57}
58
59impl ScaleTypeSpec {
60 pub fn is_discrete(&self) -> bool {
61 use ScaleTypeSpec::*;
62 matches!(self, Ordinal | Band | Point)
63 }
64}
65
66#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
67#[serde(untagged)]
68pub enum ScaleDomainSpec {
69 Array(Vec<ScaleArrayElementSpec>),
70 FieldReference(ScaleFieldReferenceSpec),
71 FieldsVecStrings(ScaleVecStringsSpec),
72 FieldsReference(ScaleFieldsReferenceSpec),
73 FieldsReferences(ScaleFieldsReferencesSpec),
74 FieldsSignals(ScaleSignalsSpec),
75 Signal(SignalExpressionSpec),
76 Value(Value),
77}
78
79#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
80pub struct ScaleFieldsReferencesSpec {
81 pub fields: Vec<ScaleDataReferenceOrSignalSpec>,
82
83 #[serde(skip_serializing_if = "Option::is_none")]
84 pub sort: Option<ScaleDataReferenceSort>,
85
86 #[serde(flatten)]
87 pub extra: HashMap<String, Value>,
88}
89
90#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
91pub struct ScaleVecStringsSpec {
92 pub fields: Vec<Vec<String>>,
93
94 #[serde(flatten)]
95 pub extra: HashMap<String, Value>,
96}
97
98#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
99#[serde(untagged)]
100pub enum ScaleDataReferenceOrSignalSpec {
101 Reference(ScaleFieldReferenceSpec),
102 Signal(SignalExpressionSpec),
103}
104
105#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
106pub struct ScaleFieldReferenceSpec {
107 pub data: String,
108 pub field: String,
109
110 #[serde(skip_serializing_if = "Option::is_none")]
111 pub sort: Option<ScaleDataReferenceSort>,
112
113 #[serde(flatten)]
117 pub extra: HashMap<String, Value>,
118}
119
120#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
121pub struct ScaleFieldsReferenceSpec {
122 #[serde(skip_serializing_if = "Option::is_none")]
123 pub data: Option<String>,
124
125 pub fields: Vec<String>,
126
127 #[serde(skip_serializing_if = "Option::is_none")]
128 pub sort: Option<ScaleDataReferenceSort>,
129
130 #[serde(flatten)]
131 pub extra: HashMap<String, Value>,
132}
133
134impl ScaleFieldsReferenceSpec {
135 pub fn to_field_references(&self) -> Vec<ScaleFieldReferenceSpec> {
136 if let Some(data) = &self.data.clone() {
137 self.fields
138 .iter()
139 .map(|f| ScaleFieldReferenceSpec {
140 data: data.clone(),
141 field: f.clone(),
142 sort: self.sort.clone(),
143 extra: Default::default(),
144 })
145 .collect::<Vec<_>>()
146 } else {
147 Vec::new()
148 }
149 }
150}
151
152#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
153pub struct ScaleSignalsSpec {
154 pub fields: Vec<SignalExpressionSpec>,
155
156 #[serde(flatten)]
157 pub extra: HashMap<String, Value>,
158}
159
160#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
161#[serde(untagged)]
162pub enum ScaleDataReferenceSort {
163 Bool(bool),
164 Parameters(ScaleDataReferenceSortParameters),
165}
166
167impl Default for ScaleDataReferenceSort {
168 fn default() -> Self {
169 Self::Bool(false)
170 }
171}
172
173#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
174pub struct ScaleDataReferenceSortParameters {
175 #[serde(skip_serializing_if = "Option::is_none")]
176 pub op: Option<AggregateOpSpec>,
177
178 #[serde(skip_serializing_if = "Option::is_none")]
179 pub field: Option<String>,
180
181 #[serde(skip_serializing_if = "Option::is_none")]
182 pub order: Option<SortOrderSpec>,
183}
184
185#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
186#[serde(untagged)]
187pub enum ScaleArrayElementSpec {
188 Signal(SignalExpressionSpec),
189 Value(Value),
190}
191
192#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
193#[serde(untagged)]
194pub enum ScaleBinsSpec {
195 Signal(SignalExpressionSpec),
196 Array(Vec<ScaleArrayElementSpec>),
197 Value(Value),
198}
199
200#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
201#[serde(untagged)]
202pub enum ScaleRangeSpec {
203 Array(Vec<ScaleArrayElementSpec>),
204 Reference(ScaleFieldReferenceSpec),
205 Signal(SignalExpressionSpec),
206 Value(Value),
207}