assemble_core/project/
buildable.rs1use crate::identifier::TaskId;
12
13use crate::project::ProjectResult;
14
15use crate::project::Project;
16
17use std::collections::HashSet;
18use std::fmt::{Debug, Formatter};
19use std::ops::{Deref, DerefMut};
20use std::sync::Arc;
21
22pub trait IntoBuildable {
24 type Buildable: Buildable;
25 fn into_buildable(self) -> Self::Buildable;
27}
28
29pub trait GetBuildable {
30 fn as_buildable(&self) -> BuildableObject;
32}
33
34assert_obj_safe!(GetBuildable);
35
36impl<B: IntoBuildable + Clone> GetBuildable for B
37where
38 <B as IntoBuildable>::Buildable: 'static,
39{
40 fn as_buildable(&self) -> BuildableObject {
41 BuildableObject::new(self.clone().into_buildable())
42 }
43}
44
45impl<B: Buildable> IntoBuildable for B {
46 type Buildable = B;
47
48 fn into_buildable(self) -> B {
49 self
50 }
51}
52
53pub trait Buildable: Send + Sync + Debug {
56 fn get_dependencies(&self, project: &Project) -> ProjectResult<HashSet<TaskId>>;
58}
59
60assert_obj_safe!(Buildable);
61
62impl<B: Buildable> Buildable for &B {
63 fn get_dependencies(&self, project: &Project) -> ProjectResult<HashSet<TaskId>> {
64 (*self).get_dependencies(project)
65 }
66}
67
68impl Buildable for Box<dyn Buildable + '_> {
69 fn get_dependencies(&self, project: &Project) -> ProjectResult<HashSet<TaskId>> {
70 self.as_ref().get_dependencies(project)
71 }
72}
73
74impl Buildable for Arc<dyn Buildable + '_> {
75 fn get_dependencies(&self, project: &Project) -> ProjectResult<HashSet<TaskId>> {
76 self.as_ref().get_dependencies(project)
77 }
78}
79
80impl<B: Buildable> Buildable for Vec<B> {
81 fn get_dependencies(&self, project: &Project) -> ProjectResult<HashSet<TaskId>> {
82 self.iter()
83 .map(|b| b.get_dependencies(project))
84 .collect::<Result<Vec<HashSet<_>>, _>>()
85 .map(|v| v.into_iter().flatten().collect())
86 }
87}
88
89#[derive(Default, Clone)]
91pub struct BuiltByContainer(Vec<Arc<dyn Buildable>>);
92
93impl BuiltByContainer {
94 pub const fn new() -> Self {
96 Self(Vec::new())
97 }
98
99 pub fn with_capacity(capacity: usize) -> Self {
101 Self(Vec::with_capacity(capacity))
102 }
103
104 pub fn with_buildable<B: IntoBuildable>(buildable: B) -> Self
106 where
107 <B as IntoBuildable>::Buildable: 'static,
108 {
109 let mut output = BuiltByContainer::with_capacity(1);
110 output.add(buildable);
111 output
112 }
113
114 pub fn join(self, other: Self) -> Self {
116 let mut inner = self.0;
117 inner.extend(other.0);
118 Self(inner)
119 }
120
121 pub fn add<T: IntoBuildable>(&mut self, buildable: T)
122 where
123 <T as IntoBuildable>::Buildable: 'static,
124 {
125 let buildable: Arc<dyn Buildable> = Arc::new(buildable.into_buildable());
126 self.0.push(buildable);
127 }
128}
129
130impl Debug for BuiltByContainer {
131 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
132 write!(f, "BuiltByContainer ")?;
133 f.debug_set().entries(&self.0).finish()
134 }
135}
136
137impl Buildable for BuiltByContainer {
138 fn get_dependencies(&self, project: &Project) -> ProjectResult<HashSet<TaskId>> {
139 let mut output = HashSet::new();
140 for dep in &self.0 {
141 trace!("Getting dependencies for buildable: {:#?}", dep);
142 output.extend(dep.get_dependencies(project)?);
143 }
144 Ok(output)
145 }
146}
147
148#[derive(Debug)]
150pub struct BuiltBy<T: Debug> {
151 built_by: Arc<dyn Buildable>,
152 value: T,
153}
154
155impl<T: Debug + Clone> Clone for BuiltBy<T> {
156 fn clone(&self) -> Self {
157 Self {
158 built_by: self.built_by.clone(),
159 value: self.value.clone(),
160 }
161 }
162}
163
164impl<T: Debug> DerefMut for BuiltBy<T> {
165 fn deref_mut(&mut self) -> &mut Self::Target {
166 &mut self.value
167 }
168}
169
170impl<T: Debug> Deref for BuiltBy<T> {
171 type Target = T;
172
173 fn deref(&self) -> &Self::Target {
174 &self.value
175 }
176}
177
178impl<T: Debug> IntoBuildable for BuiltBy<T> {
179 type Buildable = Arc<dyn Buildable>;
180
181 fn into_buildable(self) -> Self::Buildable {
182 self.built_by
183 }
184}
185
186impl<T: Debug> BuiltBy<T> {
187 pub fn new<B: IntoBuildable + 'static>(built_by: B, value: T) -> Self {
189 Self {
190 built_by: Arc::new(built_by.into_buildable()),
191 value,
192 }
193 }
194
195 pub fn into_inner(self) -> T {
197 self.value
198 }
199
200 pub fn as_ref(&self) -> BuiltBy<&T> {
202 BuiltBy {
203 built_by: self.built_by.clone(),
204 value: &self.value,
205 }
206 }
207
208 pub fn built_by(&self) -> &dyn Buildable {
210 &self.built_by
211 }
212}
213
214#[derive(Clone, Debug)]
216pub enum BuildableObject {
217 Container(BuiltByContainer),
219 Id(TaskId),
221 Other(Arc<dyn Buildable>),
223 None,
225}
226
227impl BuildableObject {
228 pub fn new<B: IntoBuildable>(buildable: B) -> Self
230 where
231 <B as IntoBuildable>::Buildable: 'static,
232 {
233 Self::Other(Arc::new(buildable.into_buildable()))
234 }
235}
236
237impl Buildable for BuildableObject {
238 fn get_dependencies(&self, project: &Project) -> ProjectResult<HashSet<TaskId>> {
239 match self {
240 BuildableObject::Container(c) => c.get_dependencies(project),
241 BuildableObject::Id(id) => id.get_dependencies(project),
242 BuildableObject::Other(o) => o.get_dependencies(project),
243 BuildableObject::None => Ok(HashSet::new()),
244 }
245 }
246}
247
248impl From<BuiltByContainer> for BuildableObject {
249 fn from(c: BuiltByContainer) -> Self {
250 BuildableObject::Container(c)
251 }
252}
253
254impl From<TaskId> for BuildableObject {
255 fn from(c: TaskId) -> Self {
256 BuildableObject::Id(c)
257 }
258}
259
260impl From<Box<dyn Buildable>> for BuildableObject {
261 fn from(boxed: Box<dyn Buildable>) -> Self {
262 let arc = Arc::from(boxed);
263 BuildableObject::Other(arc)
264 }
265}
266
267assert_impl_all!(BuildableObject: Buildable, IntoBuildable, GetBuildable);