vegafusion_core/spec/
values.rs

1use crate::error::Result;
2use crate::expression::parser::parse;
3use crate::task_graph::task::InputVariable;
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(untagged)]
8pub enum StringOrStringList {
9    String(String),
10    StringList(Vec<String>),
11}
12
13impl StringOrStringList {
14    pub fn to_vec(&self) -> Vec<String> {
15        match self {
16            StringOrStringList::String(v) => vec![v.clone()],
17            StringOrStringList::StringList(v) => v.clone(),
18        }
19    }
20}
21
22impl Default for StringOrStringList {
23    fn default() -> Self {
24        Self::StringList(Vec::new())
25    }
26}
27
28#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
29#[serde(untagged)]
30pub enum Field {
31    String(String),
32    Object(FieldObject),
33}
34
35impl Field {
36    pub fn field(&self) -> String {
37        match self {
38            Field::String(field) => field.clone(),
39            Field::Object(FieldObject { field, .. }) => field.clone(),
40        }
41    }
42
43    pub fn as_(&self) -> Option<String> {
44        match self {
45            Field::String(_) => None,
46            Field::Object(FieldObject { as_, .. }) => as_.clone(),
47        }
48    }
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
52pub struct FieldObject {
53    pub field: String,
54
55    #[serde(rename = "as", skip_serializing_if = "Option::is_none")]
56    pub as_: Option<String>,
57}
58
59#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
60pub struct SignalExpressionSpec {
61    pub signal: String,
62}
63
64#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
65#[serde(untagged)]
66pub enum StringOrSignalSpec {
67    String(String),
68    Signal(SignalExpressionSpec),
69}
70
71impl StringOrSignalSpec {
72    pub fn input_vars(&self) -> Result<Vec<InputVariable>> {
73        match self {
74            Self::Signal(signal) => Ok(parse(&signal.signal)?.input_vars()),
75            _ => Ok(Default::default()),
76        }
77    }
78}
79
80#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
81#[serde(untagged)]
82pub enum NumberOrSignalSpec {
83    Number(f64),
84    Signal(SignalExpressionSpec),
85}
86
87impl NumberOrSignalSpec {
88    pub fn input_vars(&self) -> Result<Vec<InputVariable>> {
89        match self {
90            Self::Signal(signal) => Ok(parse(&signal.signal)?.input_vars()),
91            _ => Ok(Default::default()),
92        }
93    }
94}
95
96#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
97#[serde(untagged)]
98pub enum ValueOrSignalSpec {
99    Signal(SignalExpressionSpec),
100    Value(serde_json::Value),
101}
102
103impl ValueOrSignalSpec {
104    pub fn input_vars(&self) -> Result<Vec<InputVariable>> {
105        match self {
106            Self::Signal(signal) => Ok(parse(&signal.signal)?.input_vars()),
107            _ => Ok(Default::default()),
108        }
109    }
110}
111
112#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
113pub struct CompareSpec {
114    pub field: StringOrStringList,
115
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub order: Option<SortOrderOrList>,
118}
119
120#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
121#[serde(rename_all = "lowercase")]
122pub enum SortOrderSpec {
123    Descending,
124    Ascending,
125}
126
127#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
128#[serde(untagged)]
129pub enum SortOrderOrList {
130    SortOrder(SortOrderSpec),
131    SortOrderList(Vec<SortOrderSpec>),
132}
133
134impl SortOrderOrList {
135    pub fn to_vec(&self) -> Vec<SortOrderSpec> {
136        match self {
137            SortOrderOrList::SortOrder(v) => vec![v.clone()],
138            SortOrderOrList::SortOrderList(v) => v.clone(),
139        }
140    }
141}
142
143/// Helper struct that will not drop null values on round trip (de)serialization
144#[derive(Debug, Clone, PartialEq, Eq, Default)]
145pub enum MissingNullOrValue {
146    #[default]
147    Missing,
148    Null,
149    Value(serde_json::Value),
150}
151
152impl MissingNullOrValue {
153    pub fn is_missing(&self) -> bool {
154        matches!(self, MissingNullOrValue::Missing)
155    }
156
157    pub fn as_option(&self) -> Option<serde_json::Value> {
158        match self {
159            MissingNullOrValue::Missing => None,
160            MissingNullOrValue::Null => Some(serde_json::Value::Null),
161            MissingNullOrValue::Value(v) => Some(v.clone()),
162        }
163    }
164}
165
166impl From<Option<serde_json::Value>> for MissingNullOrValue {
167    fn from(opt: Option<serde_json::Value>) -> MissingNullOrValue {
168        match opt {
169            Some(v) => MissingNullOrValue::Value(v),
170            None => MissingNullOrValue::Null,
171        }
172    }
173}
174
175impl<'de> Deserialize<'de> for MissingNullOrValue {
176    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
177    where
178        D: Deserializer<'de>,
179    {
180        Option::deserialize(deserializer).map(Into::into)
181    }
182}
183
184impl Serialize for MissingNullOrValue {
185    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
186    where
187        S: Serializer,
188    {
189        match self {
190            MissingNullOrValue::Missing => None::<Option<serde_json::Value>>.serialize(serializer),
191            MissingNullOrValue::Null => serde_json::Value::Null.serialize(serializer),
192            MissingNullOrValue::Value(v) => v.serialize(serializer),
193        }
194    }
195}