summaryrefslogtreecommitdiffstats
path: root/crates/driver/src/args.rs
blob: 510a156e990adf4263cee7dd9d7f1aca9b79bcea (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
119
120
121
122
use std::{
	collections::{hash_map, HashMap},
	hash,
	rc::Rc,
};

use enum_kinds::EnumKind;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, PartialEq, Eq)]
pub struct Platform {
	#[serde(skip)]
	pub short: String,
	pub gnu_triplet: String,
	pub karch: String,
	pub prefix: String,
}

#[derive(Debug, Serialize, PartialEq, Eq)]
pub struct PlatformRelation {
	pub is_same: bool,
	pub sysroot: String,
	pub cross_compile: String,
}

#[derive(Clone, Debug, Serialize, PartialEq, Eq, EnumKind)]
#[serde(untagged)]
#[enum_kind(ArgType, derive(Deserialize), serde(rename_all = "snake_case"))]
pub enum Arg {
	String(Rc<String>),
	Platform(Rc<Platform>),
	PlatformRelation(Rc<PlatformRelation>),
}

impl From<&Arg> for Arg {
	fn from(value: &Arg) -> Self {
		value.clone()
	}
}

impl From<String> for Arg {
	fn from(value: String) -> Self {
		Arg::String(Rc::new(value))
	}
}

impl From<Platform> for Arg {
	fn from(value: Platform) -> Self {
		Arg::Platform(Rc::new(value))
	}
}

impl From<PlatformRelation> for Arg {
	fn from(value: PlatformRelation) -> Self {
		Arg::PlatformRelation(Rc::new(value))
	}
}

#[derive(Clone, Debug, Serialize, PartialEq, Eq, Default)]
pub struct TaskArgs(HashMap<String, Arg>);

impl TaskArgs {
	pub fn contains_key(&self, key: &str) -> bool {
		self.0.contains_key(key)
	}

	pub fn get(&self, key: &str) -> Option<&Arg> {
		self.0.get(key)
	}

	pub fn set<T>(&mut self, key: &str, value: Option<T>)
	where
		T: Into<Arg>,
	{
		if let Some(v) = value {
			self.0.insert(key.to_string(), v.into());
		} else {
			self.0.remove(key);
		}
	}

	pub fn iter(&self) -> hash_map::Iter<String, Arg> {
		self.into_iter()
	}
}

impl FromIterator<(String, Arg)> for TaskArgs {
	fn from_iter<T: IntoIterator<Item = (String, Arg)>>(iter: T) -> Self {
		TaskArgs(HashMap::from_iter(iter))
	}
}

impl<'a> IntoIterator for &'a TaskArgs {
	type Item = (&'a String, &'a Arg);

	type IntoIter = hash_map::Iter<'a, String, Arg>;

	fn into_iter(self) -> Self::IntoIter {
		self.0.iter()
	}
}

#[allow(clippy::derive_hash_xor_eq)]
impl hash::Hash for TaskArgs {
	fn hash<H: hash::Hasher>(&self, _state: &mut H) {
		// Don't do anything: Properly hashing the task args is likely to cost
		// much more performance than the hash collisions caused by TaskRefs
		// that only differ by the args
	}
}

pub fn arg<A: Into<Arg>>(key: &str, value: A) -> (String, Arg) {
	(key.to_string(), value.into())
}

#[derive(Clone, Debug, Deserialize, Default, PartialEq, Eq)]
pub struct ArgMapping(pub HashMap<String, String>);

#[allow(clippy::derive_hash_xor_eq)]
impl hash::Hash for ArgMapping {
	fn hash<H: hash::Hasher>(&self, _state: &mut H) {}
}