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
|
use std::fmt;
use eyre::{eyre, Result};
use regex::Captures;
use super::command_line::CommandLine;
use super::pattern::r#match;
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct InferenceRule {
pub products: Vec<String>,
pub prerequisites: Vec<String>,
pub commands: Vec<CommandLine>,
}
impl InferenceRule {
/// s1 is the product, s2 is the prereq
pub fn new_suffix(s1: String, s2: String, commands: Vec<CommandLine>) -> Self {
Self {
products: vec![format!("%.{}", s1)],
prerequisites: vec![format!("%.{}", s2)],
commands,
}
}
fn first_match<'s, 't: 's>(&'s self, target_name: &'t str) -> Result<Option<Captures<'t>>> {
self.products
.iter()
.map(|pattern| r#match(pattern, target_name))
.try_fold(None, |x, y| y.map(|y| x.or(y)))
}
pub fn matches(&self, target_name: &str) -> Result<bool> {
self.first_match(target_name).map(|x| x.is_some())
}
pub fn prereqs<'s>(
&'s self,
target_name: &'s str,
) -> Result<impl Iterator<Item = String> + 's> {
let capture = self
.first_match(target_name)?
.ok_or_else(|| eyre!("asked non-matching inference rule for prerequisites"))?;
let percent_expansion = capture.get(1).expect("should've matched the %").as_str();
Ok(self
.prerequisites
.iter()
.map(move |p| p.replace('%', percent_expansion)))
}
}
impl fmt::Display for InferenceRule {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(
f,
"{}: {}",
self.products.join(" "),
self.prerequisites.join(" ")
)?;
for command in &self.commands {
writeln!(f, "\t{}", command)?;
}
Ok(())
}
}
|