diff options
-rw-r--r-- | src/chooser.rs | 14 | ||||
-rwxr-xr-x | src/codegen/mod.rs | 11 | ||||
-rw-r--r-- | src/ir/context.rs | 4 | ||||
-rw-r--r-- | src/ir/int.rs | 38 | ||||
-rw-r--r-- | src/ir/var.rs | 30 | ||||
-rwxr-xr-x | src/lib.rs | 14 |
6 files changed, 94 insertions, 17 deletions
diff --git a/src/chooser.rs b/src/chooser.rs new file mode 100644 index 00000000..10a77dc9 --- /dev/null +++ b/src/chooser.rs @@ -0,0 +1,14 @@ +//! A public API for more fine-grained customization of bindgen behavior. + +pub use ir::int::IntKind; +use std::fmt; + +/// A trait to allow configuring different kinds of types in different +/// situations. +pub trait TypeChooser: fmt::Debug { + /// The integer kind an integer macro should have, given a name and the + /// value of that macro, or `None` if you want the default to be chosen. + fn int_macro(&self, _name: &str, _value: i64) -> Option<IntKind> { + None + } +} diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 7fa8b19c..e8c507a1 100755 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1453,8 +1453,19 @@ impl ToRustTy for Type { IntKind::ULong => raw!(c_ulong), IntKind::LongLong => raw!(c_longlong), IntKind::ULongLong => raw!(c_ulonglong), + + IntKind::I8 => aster::ty::TyBuilder::new().i8(), + IntKind::U8 => aster::ty::TyBuilder::new().u8(), + IntKind::I16 => aster::ty::TyBuilder::new().i16(), IntKind::U16 => aster::ty::TyBuilder::new().u16(), + IntKind::I32 => aster::ty::TyBuilder::new().i32(), IntKind::U32 => aster::ty::TyBuilder::new().u32(), + IntKind::I64 => aster::ty::TyBuilder::new().i64(), + IntKind::U64 => aster::ty::TyBuilder::new().u64(), + IntKind::Custom(name, _signed) => { + let ident = ctx.rust_ident_raw(name); + quote_ty!(ctx.ext_cx(), $ident) + } // FIXME: This doesn't generate the proper alignment, but we // can't do better right now. We should be able to use // i128/u128 when they're available. diff --git a/src/ir/context.rs b/src/ir/context.rs index 977db9c5..00ece529 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -4,7 +4,7 @@ use BindgenOptions; use cexpr; use clang::{self, Cursor}; use parse::ClangItemParser; -use std::borrow::{Borrow, Cow}; +use std::borrow::Cow; use std::collections::{HashMap, hash_map}; use std::collections::btree_map::{self, BTreeMap}; use std::fmt; @@ -245,7 +245,7 @@ impl<'ctx> BindgenContext<'ctx> { /// Returns a mangled name as a rust identifier. pub fn rust_ident_raw(&self, name: &str) -> Ident { - self.ext_cx().ident_of(name.borrow()) + self.ext_cx().ident_of(name) } /// Iterate over all items that have been defined. diff --git a/src/ir/int.rs b/src/ir/int.rs index a18e4c58..562169f7 100644 --- a/src/ir/int.rs +++ b/src/ir/int.rs @@ -36,18 +36,41 @@ pub enum IntKind { /// An `unsigned long long`. ULongLong, + /// A 8-bit signed integer. + I8, + + /// A 8-bit unsigned integer. + U8, + + /// A 16-bit signed integer. + I16, + /// Either a `char16_t` or a `wchar_t`. U16, - /// A `char32_t`. + /// A 32-bit signed integer. + I32, + + /// A 32-bit unsigned integer. U32, + /// A 64-bit signed integer. + I64, + + /// A 64-bit unsigned integer. + U64, + /// An `int128_t` I128, /// A `uint128_t`. - U128, /* Though now we're at it we could add equivalents for the rust - * types... */ + U128, + + /// A custom integer type, used to allow custom macro types depending on + /// range. + /// + /// The boolean means a whether this is a signed integer type or not. + Custom(&'static str, bool), } impl IntKind { @@ -55,10 +78,13 @@ impl IntKind { pub fn is_signed(&self) -> bool { use self::IntKind::*; match *self { - Bool | UChar | UShort | UInt | ULong | ULongLong | U16 | U32 | - U128 => false, + Bool | UChar | UShort | UInt | ULong | ULongLong | U8 | U16 | + U32 | U64 | U128 => false, + + Char | Short | Int | Long | LongLong | I8 | I16 | I32 | I64 | + I128 => true, - Char | Short | Int | Long | LongLong | I128 => true, + Custom(_, signed) => signed, } } } diff --git a/src/ir/var.rs b/src/ir/var.rs index 62f17030..0c09bad4 100644 --- a/src/ir/var.rs +++ b/src/ir/var.rs @@ -111,16 +111,28 @@ impl ClangSubItemParser for Var { EvalResult::Invalid => return Err(ParseError::Continue), EvalResult::Int(Wrapping(value)) => { - let kind = if value < 0 { - if value < i32::min_value() as i64 { - IntKind::LongLong - } else { - IntKind::Int + let kind = match ctx.options().type_chooser { + Some(ref chooser) => { + chooser.int_macro(&name, value) + } + None => None, + }; + + let kind = match kind { + Some(kind) => kind, + None => { + if value < 0 { + if value < i32::min_value() as i64 { + IntKind::LongLong + } else { + IntKind::Int + } + } else if value > u32::max_value() as i64 { + IntKind::ULongLong + } else { + IntKind::UInt + } } - } else if value > u32::max_value() as i64 { - IntKind::ULongLong - } else { - IntKind::UInt }; (kind, value) @@ -63,6 +63,8 @@ mod parse; mod regex_set; mod uses; +pub mod chooser; + #[cfg(rustfmt)] mod codegen; @@ -229,6 +231,13 @@ impl Builder { self } + /// Allows configuring types in different situations, see the `TypeChooser` + /// documentation. + pub fn type_chooser(mut self, cb: Box<chooser::TypeChooser>) -> Self { + self.options.type_chooser = Some(cb); + self + } + /// Generate the Rust bindings using the options built up thus far. pub fn generate<'ctx>(self) -> Result<Bindings<'ctx>, ()> { Bindings::generate(self.options, None) @@ -320,6 +329,10 @@ pub struct BindgenOptions { /// Generate a dummy C/C++ file that includes the header and has dummy uses /// of all types defined therein. See the `uses` module for more. pub dummy_uses: Option<String>, + + /// A user-provided type chooser to allow customizing different kinds of + /// situations. + pub type_chooser: Option<Box<chooser::TypeChooser>>, } impl Default for BindgenOptions { @@ -347,6 +360,7 @@ impl Default for BindgenOptions { clang_args: vec![], input_header: None, dummy_uses: None, + type_chooser: None, } } } |