#![deny(missing_docs)]
use std::collections::HashMap;
use std::env;
use std::process::Command;
use std::str::{from_utf8, Utf8Error};
use std::io;
use std::path::Path;
use serde_json;
#[derive(Clone, Deserialize, Debug)]
pub struct Metadata {
pub packages: Vec<Package>,
version: usize,
}
#[derive(Clone, Deserialize, Debug)]
pub struct Package {
pub name: String,
pub version: String,
id: String,
source: Option<String>,
pub dependencies: Vec<Dependency>,
pub targets: Vec<Target>,
features: HashMap<String, Vec<String>>,
pub manifest_path: String,
}
#[derive(Clone, Deserialize, Debug)]
pub struct Dependency {
pub name: String,
source: Option<String>,
pub req: String,
kind: Option<String>,
optional: bool,
uses_default_features: bool,
features: Vec<String>,
target: Option<String>,
}
#[derive(Clone, Deserialize, Debug)]
pub struct Target {
pub name: String,
pub kind: Vec<String>,
#[serde(default)]
pub crate_types: Vec<String>,
pub src_path: String,
}
#[derive(Debug)]
pub enum Error {
Io(io::Error),
Utf8(Utf8Error),
Json(serde_json::Error),
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
Error::Io(err)
}
}
impl From<Utf8Error> for Error {
fn from(err: Utf8Error) -> Self {
Error::Utf8(err)
}
}
impl From<serde_json::Error> for Error {
fn from(err: serde_json::Error) -> Self {
Error::Json(err)
}
}
pub fn metadata(manifest_path: &Path) -> Result<Metadata, Error> {
let cargo = env::var("CARGO").unwrap_or_else(|_| String::from("cargo"));
let mut cmd = Command::new(cargo);
cmd.arg("metadata");
cmd.arg("--all-features");
cmd.arg("--format-version").arg("1");
cmd.arg("--manifest-path");
cmd.arg(manifest_path.to_str().unwrap());
let output = cmd.output()?;
let stdout = from_utf8(&output.stdout)?;
let meta: Metadata = serde_json::from_str(stdout)?;
Ok(meta)
}