vegafusion_core/task_graph/
task.rs1use crate::error::{Result, VegaFusionError};
2use crate::proto::gen::tasks::{
3 task::TaskKind, DataSourceTask, DataUrlTask, DataValuesTask, NodeValueIndex, Task, TzConfig,
4 Variable,
5};
6use crate::proto::gen::tasks::{SignalTask, TaskValue as ProtoTaskValue};
7use crate::task_graph::task_value::TaskValue;
8use std::convert::TryFrom;
9
10use crate::proto::gen::expression::Expression;
11use prost::Message;
12use std::hash::{Hash, Hasher};
13
14#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
15pub struct InputVariable {
16 pub var: Variable,
17 pub propagate: bool,
18}
19
20impl Task {
21 pub fn task_kind(&self) -> &TaskKind {
22 self.task_kind.as_ref().unwrap()
23 }
24 pub fn variable(&self) -> &Variable {
25 self.variable.as_ref().unwrap()
26 }
27
28 pub fn scope(&self) -> &[u32] {
29 self.scope.as_slice()
30 }
31
32 pub fn new_value(variable: Variable, scope: &[u32], value: TaskValue) -> Self {
33 Self {
34 variable: Some(variable),
35 scope: Vec::from(scope),
36 task_kind: Some(TaskKind::Value(ProtoTaskValue::try_from(&value).unwrap())),
37 tz_config: None,
38 }
39 }
40
41 pub fn to_value(&self) -> Result<TaskValue> {
42 if let TaskKind::Value(value) = self.task_kind() {
43 Ok(TaskValue::try_from(value)?)
44 } else {
45 Err(VegaFusionError::internal("Task is not a TaskValue"))
46 }
47 }
48
49 pub fn new_data_url(
50 variable: Variable,
51 scope: &[u32],
52 task: DataUrlTask,
53 tz_config: &TzConfig,
54 ) -> Self {
55 Self {
56 variable: Some(variable),
57 scope: Vec::from(scope),
58 task_kind: Some(TaskKind::DataUrl(task)),
59 tz_config: Some(tz_config.clone()),
60 }
61 }
62
63 pub fn new_data_values(
64 variable: Variable,
65 scope: &[u32],
66 task: DataValuesTask,
67 tz_config: &TzConfig,
68 ) -> Self {
69 Self {
70 variable: Some(variable),
71 scope: Vec::from(scope),
72 task_kind: Some(TaskKind::DataValues(task)),
73 tz_config: Some(tz_config.clone()),
74 }
75 }
76
77 pub fn new_data_source(
78 variable: Variable,
79 scope: &[u32],
80 task: DataSourceTask,
81 tz_config: &TzConfig,
82 ) -> Self {
83 Self {
84 variable: Some(variable),
85 scope: Vec::from(scope),
86 task_kind: Some(TaskKind::DataSource(task)),
87 tz_config: Some(tz_config.clone()),
88 }
89 }
90
91 pub fn new_signal(
92 variable: Variable,
93 scope: &[u32],
94 expr: Expression,
95 tz_config: &TzConfig,
96 ) -> Self {
97 let task_kind = TaskKind::Signal(SignalTask { expr: Some(expr) });
98 Self {
99 variable: Some(variable),
100 scope: Vec::from(scope),
101 task_kind: Some(task_kind),
102 tz_config: Some(tz_config.clone()),
103 }
104 }
105
106 pub fn input_vars(&self) -> Vec<InputVariable> {
107 match self.task_kind() {
108 TaskKind::Value(_) => Vec::new(),
109 TaskKind::DataUrl(task) => task.input_vars(),
110 TaskKind::DataSource(task) => task.input_vars(),
111 TaskKind::DataValues(task) => task.input_vars(),
112 TaskKind::Signal(task) => {
113 let expr = task.expr.as_ref().unwrap();
114 expr.input_vars()
115 }
116 }
117 }
118
119 pub fn output_vars(&self) -> Vec<Variable> {
120 match self.task_kind() {
121 TaskKind::Value(_) => Vec::new(),
122 TaskKind::DataUrl(task) => task.output_vars(),
123 TaskKind::DataSource(task) => task.output_vars(),
124 TaskKind::DataValues(task) => task.output_vars(),
125 TaskKind::Signal(_) => Vec::new(),
126 }
127 }
128}
129
130#[allow(clippy::derived_hash_with_manual_eq)]
131impl Hash for Task {
132 fn hash<H: Hasher>(&self, state: &mut H) {
133 let mut proto_bytes: Vec<u8> = Vec::with_capacity(self.encoded_len());
134
135 self.encode(&mut proto_bytes).unwrap();
137 proto_bytes.hash(state);
138 }
139}
140
141pub trait TaskDependencies {
142 fn input_vars(&self) -> Vec<InputVariable> {
143 Vec::new()
144 }
145 fn output_vars(&self) -> Vec<Variable> {
146 Vec::new()
147 }
148}
149
150#[allow(clippy::derived_hash_with_manual_eq)]
151impl Hash for NodeValueIndex {
152 fn hash<H: Hasher>(&self, state: &mut H) {
153 self.node_index.hash(state);
154 self.output_index.hash(state);
155 }
156}
157
158impl Eq for NodeValueIndex {}