From b04df026d90167d9bcbc94cf0e48c9ceee24edf6 Mon Sep 17 00:00:00 2001 From: Ryan Hunt <rhunt@eqrion.net> Date: Thu, 11 May 2017 03:57:57 -0400 Subject: [PATCH] Rename directive to annotation --- README.md | 2 +- compile-tests/{directive.rs => annotation.rs} | 0 src/bindgen/{directive.rs => annotation.rs} | 80 ++++++++++--------- src/bindgen/config.rs | 38 ++++----- src/bindgen/items.rs | 76 +++++++++--------- src/bindgen/library.rs | 40 +++++----- src/bindgen/mod.rs | 2 +- 7 files changed, 121 insertions(+), 117 deletions(-) rename compile-tests/{directive.rs => annotation.rs} (100%) rename src/bindgen/{directive.rs => annotation.rs} (50%) diff --git a/README.md b/README.md index d7af7c1..6f49f4a 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ This project can be used to generate C bindings for Rust code. It is currently b * Builds bindings for a crate, its mods, its dependent crates, and their mods * Only the necessary types for exposed functions are given bindings - * Can specify directives for controlling some aspects of binding + * Can specify annotations for controlling some aspects of binding * Generic structs can be exposed using `type IntFoo = Foo<i32>;` * Customizable formatting, can be used in C or C++ projects diff --git a/compile-tests/directive.rs b/compile-tests/annotation.rs similarity index 100% rename from compile-tests/directive.rs rename to compile-tests/annotation.rs diff --git a/src/bindgen/directive.rs b/src/bindgen/annotation.rs similarity index 50% rename from src/bindgen/directive.rs rename to src/bindgen/annotation.rs index ec7e810..e3e8218 100644 --- a/src/bindgen/directive.rs +++ b/src/bindgen/annotation.rs @@ -1,45 +1,49 @@ use std::collections::HashMap; use std::str::FromStr; +// A system for specifying properties on items. Annotations are +// given through document comments and parsed by this code. +// +// An annotation is in the form cbindgen:PROPERTY=VALUE +// Where PROPERTY depends on the item +// Where VALUE can be +// * list - [Item1, Item2, Item3, ...] +// * atom - Foo +// * bool - true,false +// Examples: +// * cbindgen:field-names=[mHandle, mNamespace] +// * cbindgen:function-postfix=WR_DESTRUCTOR_SAFE + +/// A value specified by an annotation. #[derive(Debug, Clone)] -pub enum DirectiveValue { +pub enum AnnotationValue { List(Vec<String>), Atom(Option<String>), Bool(bool), } -/// A simple system for specifying properties on items -/// -/// a directive is given by cbindgen:PROPERTY=VALUE -/// where PROPERTY depends on the item -/// where VALUE can be -/// * list - [item1, item2, item3] -/// * atom - foo -/// * bool - true,false -/// Examples: -/// * cbindgen:field-names=[mHandle, mNamespace] -/// * cbindgen:function-postfix=WR_DESTRUCTOR_SAFE +/// A set of annotations specified by a document comment. #[derive(Debug, Clone)] -pub struct DirectiveSet { - directives: HashMap<String, DirectiveValue> +pub struct AnnotationSet { + annotations: HashMap<String, AnnotationValue> } -impl DirectiveSet { - pub fn new() -> DirectiveSet { - DirectiveSet { - directives: HashMap::new(), +impl AnnotationSet { + pub fn new() -> AnnotationSet { + AnnotationSet { + annotations: HashMap::new(), } } - pub fn parse(text: String) -> Result<DirectiveSet, String> { - let mut directives = HashMap::new(); + pub fn parse(text: String) -> Result<AnnotationSet, String> { + let mut annotations = HashMap::new(); for line in text.lines().map(|x| x.trim_left_matches("///").trim()) { if !line.starts_with("cbindgen:") { continue; } - let directive = &line[9..]; - let parts: Vec<&str> = directive.split("=") + let annotation = &line[9..]; + let parts: Vec<&str> = annotation.split("=") .map(|x| x.trim()) .collect(); @@ -50,47 +54,47 @@ impl DirectiveSet { let name = parts[0]; if parts.len() == 1 { - directives.insert(name.to_string(), DirectiveValue::Bool(true)); + annotations.insert(name.to_string(), AnnotationValue::Bool(true)); continue; } let value = parts[1]; if let Some(x) = parse_list(value) { - directives.insert(name.to_string(), DirectiveValue::List(x)); + annotations.insert(name.to_string(), AnnotationValue::List(x)); continue; } if let Ok(x) = value.parse::<bool>() { - directives.insert(name.to_string(), DirectiveValue::Bool(x)); + annotations.insert(name.to_string(), AnnotationValue::Bool(x)); continue; } - directives.insert(name.to_string(), if value.len() == 0 { - DirectiveValue::Atom(None) + annotations.insert(name.to_string(), if value.len() == 0 { + AnnotationValue::Atom(None) } else { - DirectiveValue::Atom(Some(value.to_string())) + AnnotationValue::Atom(Some(value.to_string())) }); } - Ok(DirectiveSet { - directives: directives + Ok(AnnotationSet { + annotations: annotations }) } pub fn list(&self, name: &str) -> Option<Vec<String>> { - match self.directives.get(name) { - Some(&DirectiveValue::List(ref x)) => Some(x.clone()), + match self.annotations.get(name) { + Some(&AnnotationValue::List(ref x)) => Some(x.clone()), _ => None, } } pub fn atom(&self, name: &str) -> Option<Option<String>> { - match self.directives.get(name) { - Some(&DirectiveValue::Atom(ref x)) => Some(x.clone()), + match self.annotations.get(name) { + Some(&AnnotationValue::Atom(ref x)) => Some(x.clone()), _ => None, } } pub fn bool(&self, name: &str) -> Option<bool> { - match self.directives.get(name) { - Some(&DirectiveValue::Bool(ref x)) => Some(*x), + match self.annotations.get(name) { + Some(&AnnotationValue::Bool(ref x)) => Some(*x), _ => None, } } @@ -98,8 +102,8 @@ impl DirectiveSet { pub fn parse_atom<T>(&self, name: &str) -> Option<T> where T: Default + FromStr { - match self.directives.get(name) { - Some(&DirectiveValue::Atom(ref x)) => { + match self.annotations.get(name) { + Some(&AnnotationValue::Atom(ref x)) => { Some(x.as_ref().map_or(T::default(), |y| { y.parse::<T>().ok().unwrap() })) } _ => None, diff --git a/src/bindgen/config.rs b/src/bindgen/config.rs index 3c6e0a4..9ef3b37 100644 --- a/src/bindgen/config.rs +++ b/src/bindgen/config.rs @@ -7,7 +7,7 @@ use std::str::FromStr; use toml; -pub use bindgen::directive::*; +pub use bindgen::annotation::*; pub use bindgen::rename::*; pub const VERSION: &'static str = env!("CARGO_PKG_VERSION"); @@ -246,15 +246,15 @@ impl Config { } impl FunctionConfig { - pub fn prefix(&self, directives: &DirectiveSet) -> Option<String> { - if let Some(x) = directives.atom("prefix") { + pub fn prefix(&self, annotations: &AnnotationSet) -> Option<String> { + if let Some(x) = annotations.atom("prefix") { return x; } self.prefix.clone() } - pub fn postfix(&self, directives: &DirectiveSet) -> Option<String> { - if let Some(x) = directives.atom("postfix") { + pub fn postfix(&self, annotations: &AnnotationSet) -> Option<String> { + if let Some(x) = annotations.atom("postfix") { return x; } self.postfix.clone() @@ -262,38 +262,38 @@ impl FunctionConfig { } impl StructConfig { - pub fn derive_eq(&self, directives: &DirectiveSet) -> bool { - if let Some(x) = directives.bool("derive-eq") { + pub fn derive_eq(&self, annotations: &AnnotationSet) -> bool { + if let Some(x) = annotations.bool("derive-eq") { return x; } self.derive_eq } - pub fn derive_neq(&self, directives: &DirectiveSet) -> bool { - if let Some(x) = directives.bool("derive-neq") { + pub fn derive_neq(&self, annotations: &AnnotationSet) -> bool { + if let Some(x) = annotations.bool("derive-neq") { return x; } self.derive_neq } - pub fn derive_lt(&self, directives: &DirectiveSet) -> bool { - if let Some(x) = directives.bool("derive-lt") { + pub fn derive_lt(&self, annotations: &AnnotationSet) -> bool { + if let Some(x) = annotations.bool("derive-lt") { return x; } self.derive_lt } - pub fn derive_lte(&self, directives: &DirectiveSet) -> bool { - if let Some(x) = directives.bool("derive-lte") { + pub fn derive_lte(&self, annotations: &AnnotationSet) -> bool { + if let Some(x) = annotations.bool("derive-lte") { return x; } self.derive_lte } - pub fn derive_gt(&self, directives: &DirectiveSet) -> bool { - if let Some(x) = directives.bool("derive-gt") { + pub fn derive_gt(&self, annotations: &AnnotationSet) -> bool { + if let Some(x) = annotations.bool("derive-gt") { return x; } self.derive_gt } - pub fn derive_gte(&self, directives: &DirectiveSet) -> bool { - if let Some(x) = directives.bool("derive-gte") { + pub fn derive_gte(&self, annotations: &AnnotationSet) -> bool { + if let Some(x) = annotations.bool("derive-gte") { return x; } self.derive_gte @@ -301,8 +301,8 @@ impl StructConfig { } impl EnumConfig { - pub fn add_sentinel(&self, directives: &DirectiveSet) -> bool { - if let Some(x) = directives.bool("add-sentinel") { + pub fn add_sentinel(&self, annotations: &AnnotationSet) -> bool { + if let Some(x) = annotations.bool("add-sentinel") { return x; } self.add_sentinel diff --git a/src/bindgen/items.rs b/src/bindgen/items.rs index bba40f8..fd4ef77 100644 --- a/src/bindgen/items.rs +++ b/src/bindgen/items.rs @@ -5,7 +5,7 @@ use syn::*; use bindgen::cdecl; use bindgen::config::{Config, Language, Layout}; -use bindgen::directive::*; +use bindgen::annotation::*; use bindgen::library::*; use bindgen::rename::*; use bindgen::syn_helpers::*; @@ -273,7 +273,7 @@ impl Type { #[derive(Debug, Clone)] pub struct Function { pub name: String, - pub directives: DirectiveSet, + pub annotations: AnnotationSet, pub ret: Option<Type>, pub args: Vec<(String, Type)>, pub extern_decl: bool, @@ -281,7 +281,7 @@ pub struct Function { impl Function { pub fn convert(name: String, - directives: DirectiveSet, + annotations: AnnotationSet, decl: &FnDecl, extern_decl: bool) -> ConvertResult<Function> { @@ -291,7 +291,7 @@ impl Function { Ok(Function { name: name, - directives: directives, + annotations: annotations, ret: ret, args: args, extern_decl: extern_decl, @@ -299,7 +299,7 @@ impl Function { } pub fn resolve(&mut self, config: &Config) { - let rules = [self.directives.parse_atom::<RenameRule>("rename-all"), + let rules = [self.annotations.parse_atom::<RenameRule>("rename-all"), config.function.rename_args]; // TODO, cleanup @@ -338,14 +338,14 @@ impl Function { // ... ) // POSTFIX ; - let prefix = config.function.prefix(&self.directives); + let prefix = config.function.prefix(&self.annotations); let ret = match self.ret.as_ref() { Some(ret) => ret.to_string(), None => format!("void"), }; let name = &self.name; let args = self.args.iter().map(|x| x.1.to_string_with_ident(&x.0)).collect::<Vec<_>>(); - let postfix = config.function.postfix(&self.directives); + let postfix = config.function.postfix(&self.annotations); let option_1: usize = prefix.as_ref().map_or(0, |x| x.len()) + ret.len() + @@ -419,14 +419,14 @@ impl Function { #[derive(Debug, Clone)] pub struct Struct { pub name: String, - pub directives: DirectiveSet, + pub annotations: AnnotationSet, pub fields: Vec<(String, Type)>, pub generic_params: Vec<PathRef>, } impl Struct { pub fn convert(name: String, - directives: DirectiveSet, + annotations: AnnotationSet, decl: &VariantData, generics: &Generics) -> ConvertResult<Struct> { @@ -456,14 +456,14 @@ impl Struct { Ok(Struct { name: name, - directives: directives, + annotations: annotations, fields: fields, generic_params: generic_params, }) } pub fn resolve(&mut self, config: &Config) { - let rules = [self.directives.parse_atom::<RenameRule>("rename-all"), + let rules = [self.annotations.parse_atom::<RenameRule>("rename-all"), config.structure.rename_fields]; // TODO, cleanup @@ -473,7 +473,7 @@ impl Struct { rules[1] }; - if let Some(o) = self.directives.list("field-names") { + if let Some(o) = self.annotations.list("field-names") { let mut overriden_fields = Vec::new(); for (i, &(ref name, ref ty)) in self.fields.iter().enumerate() { @@ -546,27 +546,27 @@ impl Struct { out.close_brace(false); }; - if config.structure.derive_eq(&self.directives) && + if config.structure.derive_eq(&self.annotations) && !self.fields.is_empty() && self.fields.iter().all(|x| x.1.can_cmp_eq()) { emit_op("==", "&&"); } - if config.structure.derive_neq(&self.directives) && + if config.structure.derive_neq(&self.annotations) && !self.fields.is_empty() && self.fields.iter().all(|x| x.1.can_cmp_eq()) { emit_op("!=", "||"); } - if config.structure.derive_lt(&self.directives) && + if config.structure.derive_lt(&self.annotations) && self.fields.len() == 1 && self.fields[0].1.can_cmp_order() { emit_op("<", "&&"); } - if config.structure.derive_lte(&self.directives) && + if config.structure.derive_lte(&self.annotations) && self.fields.len() == 1 && self.fields[0].1.can_cmp_order() { emit_op("<=", "&&"); } - if config.structure.derive_gt(&self.directives) && + if config.structure.derive_gt(&self.annotations) && self.fields.len() == 1 && self.fields[0].1.can_cmp_order() { emit_op(">", "&&"); } - if config.structure.derive_gte(&self.directives) && + if config.structure.derive_gte(&self.annotations) && self.fields.len() == 1 && self.fields[0].1.can_cmp_order() { emit_op(">=", "&&"); } @@ -584,15 +584,15 @@ impl Struct { #[derive(Debug, Clone)] pub struct OpaqueStruct { pub name: PathRef, - pub directives: DirectiveSet, + pub annotations: AnnotationSet, } impl OpaqueStruct { - pub fn new(name: String, directives: DirectiveSet) -> OpaqueStruct + pub fn new(name: String, annotations: AnnotationSet) -> OpaqueStruct { OpaqueStruct { name: name, - directives: directives, + annotations: annotations, } } @@ -611,14 +611,14 @@ impl OpaqueStruct { pub struct Enum { pub name: String, pub repr: Repr, - pub directives: DirectiveSet, + pub annotations: AnnotationSet, pub values: Vec<(String, u64)>, } impl Enum { pub fn convert(name: String, repr: Repr, - directives: DirectiveSet, + annotations: AnnotationSet, variants: &Vec<Variant>) -> ConvertResult<Enum> { if repr != Repr::U32 && @@ -656,7 +656,7 @@ impl Enum { } } - if let Some(variants) = directives.list("enum-trailing-values") { + if let Some(variants) = annotations.list("enum-trailing-values") { for variant in variants { values.push((variant, current)); current = current + 1; @@ -666,13 +666,13 @@ impl Enum { Ok(Enum { name: name, repr: repr, - directives: directives, + annotations: annotations, values: values, }) } pub fn resolve(&mut self, config: &Config) { - let rules = [self.directives.parse_atom::<RenameRule>("rename-all"), + let rules = [self.annotations.parse_atom::<RenameRule>("rename-all"), config.enumeration.rename_variants]; // TODO, cleanup @@ -711,7 +711,7 @@ impl Enum { } out.write(&format!("{} = {},", value.0, value.1)); } - if config.enumeration.add_sentinel(&self.directives) { + if config.enumeration.add_sentinel(&self.annotations) { out.new_line(); out.new_line(); out.write("Sentinel /* this must be last for serialization purposes. */"); @@ -728,14 +728,14 @@ impl Enum { #[derive(Debug, Clone)] pub struct Specialization { pub name: String, - pub directives: DirectiveSet, + pub annotations: AnnotationSet, pub aliased: PathRef, pub generic_values: Vec<Type>, } impl Specialization { pub fn convert(name: String, - directives: DirectiveSet, + annotations: AnnotationSet, ty: &Ty) -> ConvertResult<Specialization> { match ty { @@ -748,7 +748,7 @@ impl Specialization { Ok(Specialization { name: name, - directives: directives, + annotations: annotations, aliased: path, generic_values: generics, }) @@ -773,7 +773,7 @@ impl Specialization { PathValue::OpaqueStruct(_) => { Ok(PathValue::OpaqueStruct(OpaqueStruct { name: self.name.clone(), - directives: self.directives.clone(), + annotations: self.annotations.clone(), })) } PathValue::Struct(aliased) => { @@ -788,7 +788,7 @@ impl Specialization { Ok(PathValue::Struct(Struct { name: self.name.clone(), - directives: self.directives.clone(), + annotations: self.annotations.clone(), fields: aliased.fields.iter() .map(|x| (x.0.clone(), x.1.specialize(&mappings))) .collect(), @@ -799,21 +799,21 @@ impl Specialization { Ok(PathValue::Enum(Enum { name: self.name.clone(), repr: aliased.repr.clone(), - directives: self.directives.clone(), + annotations: self.annotations.clone(), values: aliased.values.clone(), })) } PathValue::Typedef(aliased) => { Ok(PathValue::Typedef(Typedef { name: self.name.clone(), - directives: self.directives.clone(), + annotations: self.annotations.clone(), aliased: aliased.aliased.clone(), })) } PathValue::Specialization(aliased) => { Specialization { name: self.name.clone(), - directives: self.directives.clone(), + annotations: self.annotations.clone(), aliased: aliased.aliased.clone(), generic_values: aliased.generic_values.clone(), }.specialize(config, library) @@ -830,17 +830,17 @@ impl Specialization { #[derive(Debug, Clone)] pub struct Typedef { pub name: String, - pub directives: DirectiveSet, + pub annotations: AnnotationSet, pub aliased: Type, } impl Typedef { pub fn convert(name: String, - directives: DirectiveSet, + annotations: AnnotationSet, ty: &Ty) -> ConvertResult<Typedef> { Ok(Typedef { name: name, - directives: directives, + annotations: annotations, aliased: try!(Type::convert(ty)), }) } diff --git a/src/bindgen/library.rs b/src/bindgen/library.rs index 002351a..54f4224 100644 --- a/src/bindgen/library.rs +++ b/src/bindgen/library.rs @@ -7,7 +7,7 @@ use syn::*; use bindgen::config; use bindgen::config::{Config, Language}; -use bindgen::directive::*; +use bindgen::annotation::*; use bindgen::items::*; use bindgen::rust_lib; use bindgen::syn_helpers::*; @@ -110,15 +110,15 @@ impl<'a> Library<'a> { match foreign_item.node { ForeignItemKind::Fn(ref decl, ref _generic) => { - let directives = match DirectiveSet::parse(foreign_item.get_doc_attr()) { + let annotations = match AnnotationSet::parse(foreign_item.get_doc_attr()) { Ok(x) => x, Err(msg) => { warn!("{}", msg); - DirectiveSet::new() + AnnotationSet::new() } }; - match Function::convert(foreign_item.ident.to_string(), directives, decl, true) { + match Function::convert(foreign_item.ident.to_string(), annotations, decl, true) { Ok(func) => { info!("take {}::{}", mod_name, &foreign_item.ident); @@ -140,15 +140,15 @@ impl<'a> Library<'a> { ref _generic, ref _block) => { if item.is_no_mangle() && abi.is_c() { - let directives = match DirectiveSet::parse(item.get_doc_attr()) { + let annotations = match AnnotationSet::parse(item.get_doc_attr()) { Ok(x) => x, Err(msg) => { warn!("{}", msg); - DirectiveSet::new() + AnnotationSet::new() } }; - match Function::convert(item.ident.to_string(), directives, decl, false) { + match Function::convert(item.ident.to_string(), annotations, decl, false) { Ok(func) => { info!("take {}::{}", mod_name, &item.ident); @@ -163,16 +163,16 @@ impl<'a> Library<'a> { ItemKind::Struct(ref variant, ref generics) => { let struct_name = item.ident.to_string(); - let directives = match DirectiveSet::parse(item.get_doc_attr()) { + let annotations = match AnnotationSet::parse(item.get_doc_attr()) { Ok(x) => x, Err(msg) => { warn!("{}", msg); - DirectiveSet::new() + AnnotationSet::new() } }; if item.is_repr_c() { - match Struct::convert(struct_name.clone(), directives.clone(), variant, generics) { + match Struct::convert(struct_name.clone(), annotations.clone(), variant, generics) { Ok(st) => { info!("take {}::{}", mod_name, &item.ident); library.structs.insert(struct_name, @@ -181,13 +181,13 @@ impl<'a> Library<'a> { Err(msg) => { info!("take {}::{} - opaque ({})", mod_name, &item.ident, msg); library.opaque_structs.insert(struct_name.clone(), - OpaqueStruct::new(struct_name, directives)); + OpaqueStruct::new(struct_name, annotations)); } } } else { info!("take {}::{} - opaque (not marked as repr(C))", mod_name, &item.ident); library.opaque_structs.insert(struct_name.clone(), - OpaqueStruct::new(struct_name, directives)); + OpaqueStruct::new(struct_name, annotations)); } } ItemKind::Enum(ref variants, ref generics) => { @@ -199,15 +199,15 @@ impl<'a> Library<'a> { } let enum_name = item.ident.to_string(); - let directives = match DirectiveSet::parse(item.get_doc_attr()) { + let annotations = match AnnotationSet::parse(item.get_doc_attr()) { Ok(x) => x, Err(msg) => { warn!("{}", msg); - DirectiveSet::new() + AnnotationSet::new() } }; - match Enum::convert(enum_name.clone(), item.get_repr(), directives.clone(), variants) { + match Enum::convert(enum_name.clone(), item.get_repr(), annotations.clone(), variants) { Ok(en) => { info!("take {}::{}", mod_name, &item.ident); library.enums.insert(enum_name, en); @@ -215,7 +215,7 @@ impl<'a> Library<'a> { Err(msg) => { info!("take {}::{} - opaque ({})", mod_name, &item.ident, msg); library.opaque_structs.insert(enum_name.clone(), - OpaqueStruct::new(enum_name, directives)); + OpaqueStruct::new(enum_name, annotations)); } } } @@ -228,15 +228,15 @@ impl<'a> Library<'a> { } let alias_name = item.ident.to_string(); - let directives = match DirectiveSet::parse(item.get_doc_attr()) { + let annotations = match AnnotationSet::parse(item.get_doc_attr()) { Ok(x) => x, Err(msg) => { warn!("{}", msg); - DirectiveSet::new() + AnnotationSet::new() } }; - let fail1 = match Specialization::convert(alias_name.clone(), directives.clone(), ty) { + let fail1 = match Specialization::convert(alias_name.clone(), annotations.clone(), ty) { Ok(spec) => { info!("take {}::{}", mod_name, &item.ident); library.specializations.insert(alias_name, spec); @@ -244,7 +244,7 @@ impl<'a> Library<'a> { } Err(msg) => msg, }; - let fail2 = match Typedef::convert(alias_name.clone(), directives, ty) { + let fail2 = match Typedef::convert(alias_name.clone(), annotations, ty) { Ok(typedef) => { info!("take {}::{}", mod_name, &item.ident); library.typedefs.insert(alias_name, typedef); diff --git a/src/bindgen/mod.rs b/src/bindgen/mod.rs index 1b20760..9783358 100644 --- a/src/bindgen/mod.rs +++ b/src/bindgen/mod.rs @@ -29,7 +29,7 @@ macro_rules! deserialize_enum_str { mod cdecl; mod config; -mod directive; +mod annotation; mod items; mod library; mod rename; -- GitLab