summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/chooser.rs14
-rwxr-xr-xsrc/codegen/mod.rs11
-rw-r--r--src/ir/context.rs4
-rw-r--r--src/ir/int.rs38
-rw-r--r--src/ir/var.rs30
-rwxr-xr-xsrc/lib.rs14
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)
diff --git a/src/lib.rs b/src/lib.rs
index a632c461..2c6eebbe 100755
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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,
}
}
}