use failure::*;
use maplit::hashmap;
use quote::ToTokens;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Serialize)]
pub struct MetaData {
package: HashMap<&'static str, String>,
lib: HashMap<&'static str, Vec<&'static str>>,
dependencies: HashMap<String, Depenency>,
}
impl MetaData {
fn new(name: &str) -> Self {
MetaData {
package: hashmap! { "version" => "0.0.0".into(), "name" => name.into(), "edition" => "2018".into() },
lib: hashmap! { "crate-type" => vec![ "cdylib" ] },
dependencies: HashMap::new(),
}
}
pub fn name(&self) -> &str {
&self.package["name"]
}
pub fn from_token(func: &syn::ItemFn) -> Fallible<Self> {
let attrs = &func.attrs;
let mut kernel_attrs = MetaData::new(&func.sig.ident.to_string());
for attr in attrs {
let path = attr.path.to_token_stream().to_string();
match path.as_ref() {
"dependencies" => {
let dep = parse_dependency(
attr.tokens
.to_string()
.trim_start_matches('(')
.trim_end_matches(')'),
)?;
for (key, val) in dep {
kernel_attrs.dependencies.insert(key, val);
}
}
"name" => {
let token = attr.tokens.to_string();
let name = token.trim_start_matches('(').trim_end_matches(')').trim();
kernel_attrs.package.insert("name", name.into());
}
_ => {
bail!("Unsupported attribute: {}", path);
}
}
}
kernel_attrs
.dependencies
.entry("accel-core".into())
.or_insert_with(|| Depenency::Version("0.3.0-alpha.4".into()));
Ok(kernel_attrs)
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged, deny_unknown_fields)]
enum Depenency {
Version(String),
VersionTable {
version: String,
#[serde(default)]
features: Vec<String>,
},
Git {
git: String,
branch: Option<String>,
tag: Option<String>,
hash: Option<String>,
#[serde(default)]
features: Vec<String>,
},
Path {
path: String,
#[serde(default)]
features: Vec<String>,
},
}
fn parse_dependency(dep: &str) -> Fallible<HashMap<String, Depenency>> {
Ok(toml::from_str(&dep.replace("\n", ""))?)
}
#[cfg(test)]
mod tests {
#[test]
fn parse_dependency() {
let map = super::parse_dependency(r#"accel-core = "0.1.1""#).unwrap();
dbg!(map);
let map = super::parse_dependency(r#"accel-core = { version = "0.1.1" }"#).unwrap();
dbg!(map);
let map = super::parse_dependency(
r#"accel-core = { git = "https://github.com/rust-accel/accel" }"#,
)
.unwrap();
dbg!(map);
let map = super::parse_dependency(
r#"accel-core = { git = "https://github.com/rust-accel/accel", branch = "master" }"#,
)
.unwrap();
dbg!(map);
assert!(super::parse_dependency(r#"accel-core = { branch = "master" }"#,).is_err());
assert!(super::parse_dependency(
r#"accel-core = { git = "https://github.com/rust-accel/accel", homhom = "master" }"#,
)
.is_err());
}
}