summaryrefslogtreecommitdiffstats
path: root/src/context.rs
blob: 9ebd5498a0520f3301df33545efd849ea30c3574 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use std::{
	collections::{HashMap, HashSet},
	fmt::Display,
	hash::Hash,
	ops::Index,
};

use serde::Serialize;

use crate::task::*;

#[derive(Clone, Debug, Serialize, PartialEq, Eq, Hash)]
pub struct TaskRef<'ctx> {
	pub id: &'ctx TaskID,
	pub args: TaskArgs,
}

impl<'ctx> Display for TaskRef<'ctx> {
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		self.id.fmt(f)
	}
}

#[derive(Clone, Debug, Serialize, PartialEq, Eq, Hash)]
pub struct OutputRef<'ctx> {
	pub task: TaskRef<'ctx>,
	pub output: &'ctx str,
}

#[derive(Debug)]
pub struct Context {
	tasks: HashMap<TaskID, TaskDef>,
}

impl Context {
	pub fn new(tasks: HashMap<TaskID, TaskDef>) -> Self {
		Context { tasks }
	}

	pub fn get(&self, id: &TaskID) -> Option<&TaskDef> {
		self.tasks.get(id)
	}

	fn task_ref<'a>(&'a self, id: &'a TaskID, args: &TaskArgs) -> TaskRef {
		TaskRef {
			id,
			args: args.clone(),
		}
	}

	pub fn make_ref(&self, id: &TaskID, args: &TaskArgs) -> Option<TaskRef> {
		let (map_id, _) = self.tasks.get_key_value(id)?;
		Some(self.task_ref(map_id, args))
	}

	fn inherit_ref<'a>(&'a self, dep: &'a InheritDep, args: &TaskArgs) -> TaskRef {
		self.task_ref(&dep.task, args)
	}

	pub fn output_ref<'a>(&'a self, dep: &'a OutputDep, args: &TaskArgs) -> OutputRef<'a> {
		OutputRef {
			task: self.task_ref(&dep.task, args),
			output: &dep.output,
		}
	}

	pub fn get_inherit_depend(&self, task_ref: &TaskRef) -> Option<TaskRef> {
		let task = &self[task_ref.id];
		Some(self.inherit_ref(task.inherit.as_ref()?, &task_ref.args))
	}

	pub fn get_build_depends(&self, task_ref: &TaskRef) -> HashSet<OutputRef> {
		let task = &self[task_ref.id];
		task.build_depends
			.iter()
			.map(|dep| self.output_ref(dep, &task_ref.args))
			.collect()
	}

	pub fn get_host_depends(&self, task_ref: &TaskRef) -> HashSet<OutputRef> {
		let task = &self[task_ref.id];
		task.depends
			.iter()
			.map(|dep| self.output_ref(dep, &task_ref.args))
			.collect()
	}

	pub fn get_dependent_tasks(&self, task_ref: &TaskRef) -> HashSet<TaskRef> {
		let task = &self[task_ref.id];
		task.inherit
			.iter()
			.map(|dep| self.inherit_ref(dep, &task_ref.args))
			.chain(
				task.build_depends
					.iter()
					.chain(task.depends.iter())
					.map(|dep| self.task_ref(&dep.task, &task_ref.args)),
			)
			.collect()
	}

	pub fn get_dependent_outputs(&self, task_ref: &TaskRef) -> HashSet<OutputRef> {
		let task = &self[task_ref.id];
		task.build_depends
			.iter()
			.chain(task.depends.iter())
			.map(|dep| self.output_ref(dep, &task_ref.args))
			.collect()
	}
}

impl Index<&TaskID> for Context {
	type Output = TaskDef;

	fn index(&self, index: &TaskID) -> &TaskDef {
		self.tasks.get(index).expect("Invalid TaskID")
	}
}