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
pub mod action;
pub mod assets;
pub mod comm;
pub mod gui;
pub mod launcher;
pub mod resource;
pub mod server;
pub mod util;

#[cfg(all(feature = "audio", not(any(feature = "rodio"))))]
compile_error!("Cannot enable feature \"audio\" without a backend (\"rodio\").");

#[cfg(all(
    feature = "stream",
    not(any(feature = "gstreamer", feature = "ffmpeg"))
))]
compile_error!("Cannot enable feature \"stream\" without a backend (\"gstreamer\" or \"ffmpeg\").");

macro_rules! impl_verify_features {
    ($($feature:literal),* $(,)?) => {
        pub fn verify_features(content: &str) -> eyre::Result<()> {
            use eyre::eyre;
            use regex::Regex;

            let re = Regex::new(r"^//@[ \t]*([[:alpha:]][[:word:]]*)[ \t]*$").unwrap();
            let features: Vec<_> = content
                .lines()
                .map_while(|p| re.captures(p).map(|c| c[1].to_string()))
                .collect();

            for f in features {
                match f.as_str() {
                    $(
                    $feature => {
                        #[cfg(not(feature = $feature))]
                        Err(eyre!("Task requires missing feature ({}).", $feature))?;
                    }
                    )*
                    f => {
                        Err(eyre!("Task requires unknown feature: {f}"))?;
                    }
                }
            }

            Ok(())
        }
    };
}

impl_verify_features!(
    "rodio",
    "gstreamer",
    "ffmpeg",
    "savage",
    "python",
    "audio",
    "stream"
);