assemble_core/
task.rs

1use crate::exception::BuildResult;
2use crate::project::Project;
3
4use parking_lot::RwLock;
5use std::error::Error;
6use std::fmt::{Debug, Display, Formatter};
7use std::sync::Arc;
8
9use crate::identifier::TaskId;
10
11use crate::project::buildable::BuiltByContainer;
12
13pub mod action;
14mod any_task;
15pub mod create_task;
16mod executable;
17pub mod flags;
18pub mod initialize_task;
19mod lazy_task;
20pub mod task_container;
21pub mod task_executor;
22pub mod task_io;
23mod task_ordering;
24pub mod up_to_date;
25pub mod work_handler;
26
27use crate::project::error::ProjectResult;
28use crate::task::flags::{OptionDeclarations, OptionsDecoder};
29use crate::task::up_to_date::UpToDate;
30pub use any_task::AnyTaskHandle;
31use create_task::CreateTask;
32pub use executable::{force_rerun, Executable};
33use initialize_task::InitializeTask;
34pub use lazy_task::*;
35use task_io::TaskIO;
36
37pub use task_ordering::*;
38
39/// The outcome of task.
40#[derive(Debug, Clone)]
41pub enum TaskOutcome {
42    /// the task executed successfully
43    Executed,
44    /// The task was skipped
45    Skipped,
46    /// The task was up to date
47    UpToDate,
48    /// The task had no source
49    NoSource,
50    /// The task failed
51    Failed,
52}
53
54pub trait Task: UpToDate + InitializeTask + CreateTask + TaskIO + Sized + Debug {
55    /// Check whether this task did work.
56    ///
57    /// By default, this is always true.
58    fn did_work(&self) -> bool {
59        true
60    }
61
62    /// The action that the task performs
63    fn task_action(_task: &mut Executable<Self>, _project: &Project) -> BuildResult;
64}
65
66/// Represents an object that has a task id
67pub trait HasTaskId {
68    /// Gets the task id
69    fn task_id(&self) -> TaskId;
70}
71
72/// Tasks that are buildable are able to produce a [`BuiltByContainer`][0] that
73/// describes what tasks are required in order to run the task.
74///
75/// [0]: BuiltByContainer
76pub trait BuildableTask: HasTaskId {
77    /// Gets the tasks that this task depends on
78    fn built_by(&self) -> BuiltByContainer {
79        let mut output = BuiltByContainer::new();
80        for task_ordering in self.ordering() {
81            match task_ordering.ordering_kind() {
82                TaskOrderingKind::DependsOn => {
83                    output.add(task_ordering.buildable().clone());
84                }
85                _ => {}
86            }
87        }
88        output
89    }
90
91    /// Gets the total ordering associated with the task. This includes all types of ordering,
92    /// including those that aren't strict dependencies.
93    ///
94    /// See [`TaskOrdering`](TaskOrdering) for more information
95    fn ordering(&self) -> Vec<TaskOrdering>;
96}
97
98/// A object safe generic trait for executing tasks
99pub trait ExecutableTask: HasTaskId + Send + Sync {
100    /// Get the options declaration for this task
101    fn options_declarations(&self) -> Option<OptionDeclarations>;
102
103    /// Try to set values from a decoder
104    fn try_set_from_decoder(&mut self, decoder: &OptionsDecoder) -> ProjectResult<()>;
105
106    /// Executes the task, with a given project
107    fn execute(&mut self, project: &Project) -> BuildResult;
108
109    /// Checks if this task did work
110    fn did_work(&self) -> bool;
111    /// Check if this task marked itself as up to date
112    fn task_up_to_date(&self) -> bool;
113
114    /// Gets the group of the task
115    fn group(&self) -> String;
116
117    /// Gets the description of the task
118    fn description(&self) -> String;
119}
120
121assert_obj_safe!(ExecutableTask);
122
123/// A full task is buildable and executable.
124pub trait FullTask: BuildableTask + ExecutableTask + Send + Sync {}
125
126impl Debug for Box<dyn FullTask> {
127    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
128        write!(f, "Task {}", self.task_id())
129    }
130}
131
132impl Display for Box<dyn FullTask> {
133    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
134        write!(f, "Task {}", self.task_id())
135    }
136}
137
138impl HasTaskId for Box<dyn FullTask> {
139    fn task_id(&self) -> TaskId {
140        (**self).task_id()
141    }
142}
143
144impl ExecutableTask for Box<dyn FullTask> {
145    fn options_declarations(&self) -> Option<OptionDeclarations> {
146        (**self).options_declarations()
147    }
148
149    fn try_set_from_decoder(&mut self, decoder: &OptionsDecoder) -> ProjectResult<()> {
150        (**self).try_set_from_decoder(decoder)
151    }
152
153    fn execute(&mut self, project: &Project) -> BuildResult {
154        (**self).execute(project)
155    }
156
157    fn did_work(&self) -> bool {
158        (**self).did_work()
159    }
160
161    fn task_up_to_date(&self) -> bool {
162        (**self).task_up_to_date()
163    }
164
165    fn group(&self) -> String {
166        (**self).group()
167    }
168
169    fn description(&self) -> String {
170        (**self).description()
171    }
172}
173
174impl<E: ExecutableTask> HasTaskId for Arc<RwLock<E>> {
175    fn task_id(&self) -> TaskId {
176        self.read().task_id()
177    }
178}
179
180impl<E: ExecutableTask + Send + Sync> ExecutableTask for Arc<RwLock<E>> {
181    fn options_declarations(&self) -> Option<OptionDeclarations> {
182        self.read().options_declarations()
183    }
184
185    fn try_set_from_decoder(&mut self, decoder: &OptionsDecoder) -> ProjectResult<()> {
186        self.write().try_set_from_decoder(decoder)
187    }
188
189    fn execute(&mut self, project: &Project) -> BuildResult {
190        self.write().execute(project)
191    }
192
193    fn did_work(&self) -> bool {
194        self.read().did_work()
195    }
196
197    fn task_up_to_date(&self) -> bool {
198        self.read().task_up_to_date()
199    }
200
201    fn group(&self) -> String {
202        self.read().group()
203    }
204
205    fn description(&self) -> String {
206        self.read().description()
207    }
208}
209
210impl Debug for Box<dyn FullTask + Send + Sync> {
211    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
212        write!(f, "Task {}", self.task_id())
213    }
214}
215
216impl Display for Box<dyn FullTask + Send + Sync> {
217    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
218        write!(f, "Task {}", self.task_id())
219    }
220}
221
222impl<F: BuildableTask + ExecutableTask> FullTask for F {}
223
224assert_obj_safe!(FullTask);