diff --git a/docs.md b/docs.md index ef817ce..600bd0b 100644 --- a/docs.md +++ b/docs.md @@ -691,6 +691,10 @@ rename_args = "PascalCase" # default: "None" sort_by = "Name" +# If this option is true `usize` and `isize` will be converted into `size_t` and `ptrdiff_t` +# instead of `uintptr_t` and `intptr_t` respectively. +usize_is_size_t = true + [struct] # A rule to use to rename struct field names. The renaming assumes the input is # the Rust standard snake_case, however it acccepts all the different rename_args diff --git a/src/bindgen/bindings.rs b/src/bindgen/bindings.rs index c9bbd61..b62fbb5 100644 --- a/src/bindgen/bindings.rs +++ b/src/bindgen/bindings.rs @@ -169,6 +169,10 @@ impl Bindings { out.new_line(); out.write("#include "); out.new_line(); + if self.config.usize_is_size_t { + out.write("#include "); + out.new_line(); + } out.write("#include "); out.new_line(); out.write("#include "); @@ -176,6 +180,10 @@ impl Bindings { } else { out.write("#include "); out.new_line(); + if self.config.usize_is_size_t { + out.write("#include "); + out.new_line(); + } out.write("#include "); out.new_line(); out.write("#include "); diff --git a/src/bindgen/cdecl.rs b/src/bindgen/cdecl.rs index 4046a2b..6b06e35 100644 --- a/src/bindgen/cdecl.rs +++ b/src/bindgen/cdecl.rs @@ -51,17 +51,17 @@ impl CDecl { } } - fn from_type(t: &Type) -> CDecl { + fn from_type(t: &Type, config: &Config) -> CDecl { let mut cdecl = CDecl::new(); - cdecl.build_type(t, false); + cdecl.build_type(t, false, config); cdecl } - fn from_func_arg(t: &Type, array_length: Option<&str>) -> CDecl { + fn from_func_arg(t: &Type, array_length: Option<&str>, config: &Config) -> CDecl { let mut cdecl = CDecl::new(); let length = match array_length { Some(l) => l, - None => return CDecl::from_type(t), + None => return CDecl::from_type(t, config), }; let (ty, is_const) = match t { Type::Ptr { ty, is_const, .. } => (ty, is_const), @@ -71,33 +71,33 @@ impl CDecl { ), }; let ptr_as_array = Type::Array(ty.clone(), ArrayLength::Value(length.to_string())); - cdecl.build_type(&ptr_as_array, *is_const); + cdecl.build_type(&ptr_as_array, *is_const, config); cdecl } - fn from_func(f: &Function, layout_vertical: bool) -> CDecl { + fn from_func(f: &Function, layout_vertical: bool, config: &Config) -> CDecl { let mut cdecl = CDecl::new(); - cdecl.build_func(f, layout_vertical); + cdecl.build_func(f, layout_vertical, config); cdecl } - fn build_func(&mut self, f: &Function, layout_vertical: bool) { + fn build_func(&mut self, f: &Function, layout_vertical: bool, config: &Config) { let args = f .args .iter() .map(|arg| { ( arg.name.clone(), - CDecl::from_func_arg(&arg.ty, arg.array_length.as_deref()), + CDecl::from_func_arg(&arg.ty, arg.array_length.as_deref(), config), ) }) .collect(); self.declarators .push(CDeclarator::Func(args, layout_vertical)); - self.build_type(&f.ret, false); + self.build_type(&f.ret, false, config); } - fn build_type(&mut self, t: &Type, is_const: bool) { + fn build_type(&mut self, t: &Type, is_const: bool, config: &Config) { match t { Type::Path(ref generic) => { if is_const { @@ -138,7 +138,7 @@ impl CDecl { "error generating cdecl for {:?}", t ); - self.type_name = p.to_string(); + self.type_name = p.to_repr_c(config).to_string(); } Type::Ptr { ref ty, @@ -151,17 +151,17 @@ impl CDecl { is_nullable: *is_nullable, is_ref: *is_ref, }); - self.build_type(ty, *ptr_is_const); + self.build_type(ty, *ptr_is_const, config); } Type::Array(ref t, ref constant) => { let len = constant.as_str().to_owned(); self.declarators.push(CDeclarator::Array(len)); - self.build_type(t, is_const); + self.build_type(t, is_const, config); } Type::FuncPtr(ref ret, ref args) => { let args = args .iter() - .map(|(ref name, ref ty)| (name.clone(), CDecl::from_type(ty))) + .map(|(ref name, ref ty)| (name.clone(), CDecl::from_type(ty, config))) .collect(); self.declarators.push(CDeclarator::Ptr { is_const: false, @@ -169,7 +169,7 @@ impl CDecl { is_ref: false, }); self.declarators.push(CDeclarator::Func(args, false)); - self.build_type(ret, false); + self.build_type(ret, false, config); } } } @@ -307,13 +307,13 @@ pub fn write_func( layout_vertical: bool, config: &Config, ) { - CDecl::from_func(f, layout_vertical).write(out, Some(f.path().name()), config); + CDecl::from_func(f, layout_vertical, config).write(out, Some(f.path().name()), config); } pub fn write_field(out: &mut SourceWriter, t: &Type, ident: &str, config: &Config) { - CDecl::from_type(t).write(out, Some(ident), config); + CDecl::from_type(t, config).write(out, Some(ident), config); } pub fn write_type(out: &mut SourceWriter, t: &Type, config: &Config) { - CDecl::from_type(t).write(out, None, config); + CDecl::from_type(t, config).write(out, None, config); } diff --git a/src/bindgen/config.rs b/src/bindgen/config.rs index 9fa762c..5ef3f4c 100644 --- a/src/bindgen/config.rs +++ b/src/bindgen/config.rs @@ -840,6 +840,9 @@ pub struct Config { pub style: Style, /// Default sort key for functions and constants. pub sort_by: SortKey, + /// If this option is true `usize` and `isize` will be converted into `size_t` and `ptrdiff_t` + /// instead of `uintptr_t` and `intptr_t` respectively. + pub usize_is_size_t: bool, /// The configuration options for parsing pub parse: ParseConfig, /// The configuration options for exporting @@ -894,6 +897,7 @@ impl Default for Config { language: Language::Cxx, cpp_compat: false, style: Style::Type, + usize_is_size_t: false, sort_by: SortKey::None, macro_expansion: Default::default(), parse: ParseConfig::default(), diff --git a/src/bindgen/ir/enumeration.rs b/src/bindgen/ir/enumeration.rs index ae846f0..2534a4f 100644 --- a/src/bindgen/ir/enumeration.rs +++ b/src/bindgen/ir/enumeration.rs @@ -9,7 +9,7 @@ use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver; use crate::bindgen::dependencies::Dependencies; use crate::bindgen::ir::{ AnnotationSet, AnnotationValue, Cfg, ConditionWrite, Documentation, GenericParams, GenericPath, - Item, ItemContainer, Path, Repr, ReprStyle, ReprType, Struct, ToCondition, Type, + Item, ItemContainer, Path, Repr, ReprStyle, Struct, ToCondition, Type, }; use crate::bindgen::library::Library; use crate::bindgen::mangle; @@ -595,18 +595,7 @@ impl Item for Enum { impl Source for Enum { fn write(&self, config: &Config, out: &mut SourceWriter) { - let size = self.repr.ty.map(|ty| match ty { - ReprType::USize => "uintptr_t", - ReprType::U64 => "uint64_t", - ReprType::U32 => "uint32_t", - ReprType::U16 => "uint16_t", - ReprType::U8 => "uint8_t", - ReprType::ISize => "intptr_t", - ReprType::I64 => "int64_t", - ReprType::I32 => "int32_t", - ReprType::I16 => "int16_t", - ReprType::I8 => "int8_t", - }); + let size = self.repr.ty.map(|ty| ty.to_primitive().to_repr_c(config)); let condition = self.cfg.to_condition(config); condition.write_before(config, out); diff --git a/src/bindgen/ir/repr.rs b/src/bindgen/ir/repr.rs index dc2b37c..fcd8cf2 100644 --- a/src/bindgen/ir/repr.rs +++ b/src/bindgen/ir/repr.rs @@ -2,6 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use crate::bindgen::ir::ty::PrimitiveType; + #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum ReprStyle { Rust, @@ -29,6 +31,23 @@ pub enum ReprType { ISize, } +impl ReprType { + pub(crate) fn to_primitive(self) -> PrimitiveType { + match self { + ReprType::U8 => PrimitiveType::UInt8, + ReprType::U16 => PrimitiveType::UInt16, + ReprType::U32 => PrimitiveType::UInt32, + ReprType::U64 => PrimitiveType::UInt64, + ReprType::USize => PrimitiveType::USize, + ReprType::I8 => PrimitiveType::Int8, + ReprType::I16 => PrimitiveType::Int16, + ReprType::I32 => PrimitiveType::Int32, + ReprType::I64 => PrimitiveType::Int64, + ReprType::ISize => PrimitiveType::ISize, + } + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum ReprAlign { Packed, diff --git a/src/bindgen/ir/ty.rs b/src/bindgen/ir/ty.rs index 656bfcb..1338b05 100644 --- a/src/bindgen/ir/ty.rs +++ b/src/bindgen/ir/ty.rs @@ -2,7 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use std::fmt; use std::io::Write; use crate::bindgen::cdecl; @@ -123,7 +122,7 @@ impl PrimitiveType { } } - pub fn to_repr_c(&self) -> &'static str { + pub fn to_repr_c(&self, config: &Config) -> &'static str { match *self { PrimitiveType::Void => "void", PrimitiveType::Bool => "bool", @@ -147,11 +146,13 @@ impl PrimitiveType { PrimitiveType::UInt => "unsigned int", PrimitiveType::ULong => "unsigned long", PrimitiveType::ULongLong => "unsigned long long", + PrimitiveType::USize if config.usize_is_size_t => "size_t", PrimitiveType::USize => "uintptr_t", PrimitiveType::UInt8 => "uint8_t", PrimitiveType::UInt16 => "uint16_t", PrimitiveType::UInt32 => "uint32_t", PrimitiveType::UInt64 => "uint64_t", + PrimitiveType::ISize if config.usize_is_size_t => "ptrdiff_t", PrimitiveType::ISize => "intptr_t", PrimitiveType::Int8 => "int8_t", PrimitiveType::Int16 => "int16_t", @@ -178,12 +179,6 @@ impl PrimitiveType { } } -impl fmt::Display for PrimitiveType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_repr_c()) - } -} - // The `U` part of `[T; U]` #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum ArrayLength { diff --git a/template.toml b/template.toml index e997f2d..f6112f5 100644 --- a/template.toml +++ b/template.toml @@ -44,6 +44,7 @@ line-endings = "LF" # also "CR", "CRLF", "Native" style = "both" sort_by = "Name" # default for `fn.sort_by` and `const.sort_by` +usize_is_size_t = true diff --git a/tests/expectations/size-types.c b/tests/expectations/size-types.c new file mode 100644 index 0000000..b3b64c0 --- /dev/null +++ b/tests/expectations/size-types.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include + +enum IE { + IV, +}; +typedef ptrdiff_t IE; + +enum UE { + UV, +}; +typedef size_t UE; + +typedef size_t Usize; + +typedef ptrdiff_t Isize; + +void root(Usize, Isize, UE, IE); diff --git a/tests/expectations/size-types.compat.c b/tests/expectations/size-types.compat.c new file mode 100644 index 0000000..0a1218b --- /dev/null +++ b/tests/expectations/size-types.compat.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include + +enum IE +#ifdef __cplusplus + : ptrdiff_t +#endif // __cplusplus + { + IV, +}; +#ifndef __cplusplus +typedef ptrdiff_t IE; +#endif // __cplusplus + +enum UE +#ifdef __cplusplus + : size_t +#endif // __cplusplus + { + UV, +}; +#ifndef __cplusplus +typedef size_t UE; +#endif // __cplusplus + +typedef size_t Usize; + +typedef ptrdiff_t Isize; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(Usize, Isize, UE, IE); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/size-types.cpp b/tests/expectations/size-types.cpp new file mode 100644 index 0000000..d701a8d --- /dev/null +++ b/tests/expectations/size-types.cpp @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include +#include + +enum class IE : ptrdiff_t { + IV, +}; + +enum class UE : size_t { + UV, +}; + +using Usize = size_t; + +using Isize = ptrdiff_t; + +extern "C" { + +void root(Usize, Isize, UE, IE); + +} // extern "C" diff --git a/tests/rust/size-types.rs b/tests/rust/size-types.rs new file mode 100644 index 0000000..6dfaeb2 --- /dev/null +++ b/tests/rust/size-types.rs @@ -0,0 +1,15 @@ +type Usize = usize; +type Isize = isize; + +#[repr(usize)] +enum UE { + UV, +} + +#[repr(isize)] +enum IE { + IV, +} + +#[no_mangle] +pub extern "C" fn root(_: Usize, _: Isize, _: UE, _: IE) {} diff --git a/tests/rust/size-types.toml b/tests/rust/size-types.toml new file mode 100644 index 0000000..b020c68 --- /dev/null +++ b/tests/rust/size-types.toml @@ -0,0 +1 @@ +usize_is_size_t = true