Skip to content

Commit

Permalink
Adds custom_const_pointer_type and custom_mut_pointer_type options.
Browse files Browse the repository at this point in the history
These options allow specifying an alternate type to use where pointer
types would otherwise be used. This is useful for binding to a
WebAssembly guest, as well as for certain kinds of serialization and
deserialization.

Resolves rust-lang#2023.
  • Loading branch information
remexre authored and Nathan Ringo committed Jan 5, 2024
1 parent d0c2b1e commit fb06c50
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 25 deletions.
26 changes: 26 additions & 0 deletions bindgen/codegen/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,4 +352,30 @@ pub(crate) mod ast_ty {
})
.collect()
}

pub(crate) fn to_ptr(
ctx: &BindgenContext,
ty: syn::Type,
is_const: bool,
) -> syn::Type {
if is_const {
if let Some(wrapper) =
ctx.options().custom_const_pointer_type.as_ref()
{
let wrapper = ctx.rust_ident_raw(wrapper);
syn::parse_quote! { #wrapper<#ty> }
} else {
syn::parse_quote! { *const #ty }
}
} else {
if let Some(wrapper) =
ctx.options().custom_mut_pointer_type.as_ref()
{
let wrapper = ctx.rust_ident_raw(wrapper);
syn::parse_quote! { #wrapper<#ty> }
} else {
syn::parse_quote! { *mut #ty }
}
}
}
}
38 changes: 13 additions & 25 deletions bindgen/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ pub(crate) mod bitfield_unit;
mod bitfield_unit_tests;

use self::dyngen::DynamicItems;
use self::helpers::ast_ty::to_ptr;
use self::helpers::attributes;

use self::struct_layout::StructLayoutTracker;

use super::BindgenOptions;
Expand Down Expand Up @@ -390,22 +392,6 @@ impl<'a> ops::DerefMut for CodegenResult<'a> {
}
}

/// A trait to convert a rust type into a pointer, optionally const, to the same
/// type.
trait ToPtr {
fn to_ptr(self, is_const: bool) -> syn::Type;
}

impl ToPtr for syn::Type {
fn to_ptr(self, is_const: bool) -> syn::Type {
if is_const {
syn::parse_quote! { *const #self }
} else {
syn::parse_quote! { *mut #self }
}
}
}

/// An extension trait for `syn::Type` that lets us append any implicit
/// template parameters that exist for some type, if necessary.
trait WithImplicitTemplateParams {
Expand Down Expand Up @@ -1984,10 +1970,10 @@ impl CodeGenerator for CompInfo {
let vtable = Vtable::new(item.id(), self);
vtable.codegen(ctx, result, item);

let vtable_type = vtable
let vtable_item_type = vtable
.try_to_rust_ty(ctx, &())
.expect("vtable to Rust type conversion is infallible")
.to_ptr(true);
.expect("vtable to Rust type conversion is infallible");
let vtable_type = to_ptr(ctx, vtable_item_type, true);

fields.push(quote! {
pub vtable_: #vtable_type ,
Expand Down Expand Up @@ -3850,7 +3836,7 @@ impl TryToRustTy for Type {
TypeKind::Void => Ok(c_void(ctx)),
// TODO: we should do something smart with nullptr, or maybe *const
// c_void is enough?
TypeKind::NullPtr => Ok(c_void(ctx).to_ptr(true)),
TypeKind::NullPtr => Ok(to_ptr(ctx, c_void(ctx), true)),
TypeKind::Int(ik) => {
Ok(int_kind_rust_type(ctx, ik, self.layout(ctx)))
}
Expand Down Expand Up @@ -3897,7 +3883,7 @@ impl TryToRustTy for Type {
TypeKind::BlockPointer(..) => {
if self.is_block_pointer() && !ctx.options().generate_block {
let void = c_void(ctx);
return Ok(void.to_ptr(/* is_const = */ false));
return Ok(to_ptr(ctx, void, /* is_const = */ false));
}

if item.is_opaque(ctx, &()) &&
Expand Down Expand Up @@ -3959,7 +3945,7 @@ impl TryToRustTy for Type {
{
Ok(ty)
} else {
Ok(ty.to_ptr(is_const))
Ok(to_ptr(ctx, ty, is_const))
}
}
TypeKind::TypeParam => {
Expand Down Expand Up @@ -5257,8 +5243,6 @@ pub(crate) mod utils {
ctx: &BindgenContext,
ty: &TypeId,
) -> syn::Type {
use super::ToPtr;

let arg_item = ctx.resolve_item(ty);
let arg_ty = arg_item.kind().expect_type();

Expand All @@ -5277,7 +5261,11 @@ pub(crate) mod utils {
} else {
t.to_rust_ty_or_opaque(ctx, &())
};
stream.to_ptr(ctx.resolve_type(t).is_const())
super::helpers::ast_ty::to_ptr(
ctx,
stream,
ctx.resolve_type(t).is_const(),
)
}
TypeKind::Pointer(inner) => {
let inner = ctx.resolve_item(inner);
Expand Down
22 changes: 22 additions & 0 deletions bindgen/options/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2059,5 +2059,27 @@ options! {
}
},
as_args: "--emit-diagnostics",
},
/// A type to use for const pointers.
custom_const_pointer_type: Option<String> {
methods: {
/// Sets the given type to be used instead of const pointers.
pub fn custom_const_pointer_type<T: Into<String>>(mut self, custom_const_pointer_type: Option<T>) -> Self {
self.options.custom_const_pointer_type = custom_const_pointer_type.map(|s| s.into());
self
}
},
as_args: "--custom-const-pointer-type",
},
/// A type to use for mut pointers.
custom_mut_pointer_type: Option<String> {
methods: {
/// Sets the given type to be used instead of mut pointers.
pub fn custom_mut_pointer_type<T: Into<String>>(mut self, custom_mut_pointer_type: Option<T>) -> Self {
self.options.custom_mut_pointer_type = custom_mut_pointer_type.map(|s| s.into());
self
}
},
as_args: "--custom-mut-pointer-type",
}
}

0 comments on commit fb06c50

Please sign in to comment.