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
use cargo_metadata::{Metadata, Target};

#[derive(Debug)]
pub(crate) struct Config {
    pub buildpack_target: String,
}

pub(crate) fn config_from_metadata(cargo_metadata: &Metadata) -> Result<Config, ConfigError> {
    let root_package = cargo_metadata
        .root_package()
        .ok_or(ConfigError::MissingRootPackage)?;

    let buildpack_bin_targets: Vec<&Target> = root_package
        .targets
        .iter()
        .filter(|target| target.kind == vec!["bin"])
        .collect();

    match buildpack_bin_targets.as_slice() {
        [single_target] => Ok(Config {
            buildpack_target: single_target.name.clone(),
        }),
        [] => Err(ConfigError::NoBinTargetsFound),
        bin_target_names => {
            let has_bin_target_with_root_package_name = bin_target_names
                .iter()
                .any(|target_name| target_name.name == root_package.name);

            if has_bin_target_with_root_package_name {
                Ok(Config {
                    buildpack_target: root_package.name.clone(),
                })
            } else {
                Err(ConfigError::MultipleBinTargetsFound)
            }
        }
    }
}

#[derive(Debug)]
pub enum ConfigError {
    MissingRootPackage,
    NoBinTargetsFound,
    MultipleBinTargetsFound,
}