use std::path::{Path, PathBuf};
use std::process::Command;
use serde_json::Value;
pub(crate) fn cargo_metadata(manifest_path: &Path) -> Result<Value, String> {
let output = Command::new("cargo")
.args([
"metadata",
"--no-deps",
"--format-version",
"1",
"--manifest-path",
])
.arg(manifest_path)
.output()
.map_err(|err| err.to_string())?;
if !output.status.success() {
return Err(String::from_utf8_lossy(&output.stderr).trim().to_string());
}
serde_json::from_slice(&output.stdout).map_err(|err| err.to_string())
}
pub(crate) fn find_package<'a>(metadata: &'a Value, package: &str) -> Option<&'a Value> {
metadata["packages"]
.as_array()?
.iter()
.find(|candidate| candidate["name"].as_str() == Some(package))
}
pub(crate) fn crate_root_file(package: &Value) -> Option<PathBuf> {
let targets = package["targets"].as_array()?;
let has_kind = |target: &Value, wanted: &str| {
target["kind"]
.as_array()
.map(|kinds| kinds.iter().any(|k| k.as_str() == Some(wanted)))
.unwrap_or(false)
};
let pick = targets
.iter()
.find(|t| has_kind(t, "lib"))
.or_else(|| targets.iter().find(|t| has_kind(t, "proc-macro")))
.or_else(|| targets.iter().find(|t| has_kind(t, "bin")))?;
pick["src_path"].as_str().map(PathBuf::from)
}