summaryrefslogtreecommitdiffstats
path: root/ffi-macros/src/lib.rs
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-01-23 17:27:06 +0100
committerJustus Winter <justus@sequoia-pgp.org>2019-01-25 14:04:26 +0100
commit71ea3a7f02cc59c5e891c25edbe270e2d9d9d71d (patch)
treef518a31f491e6f6816b4014bbe7bc9768bfdc20d /ffi-macros/src/lib.rs
parentd1e68e97496d0541f3ddd0483f62e185e870c9e4 (diff)
openpgp-ffi: Derive conversion functions.
- This is a framework for dealing with ownership and references at the FFI boundary. Previously, we used macros to do that. This change introduces a more idiomatic interface, we use traits converting from raw pointers of a wrapper type to objects, references, or mutable references to a wrapped type. - For now, we use the wrapped type as wrapper type. We merely introduce a new mechanism replacing the macro-based one. - This patch also converts all the derived functions. - The following patches will convert all the functions that are already using the ffi_wrapper_type. Once this conversion is done, we can introduce our own wrapper type.
Diffstat (limited to 'ffi-macros/src/lib.rs')
-rw-r--r--ffi-macros/src/lib.rs93
1 files changed, 78 insertions, 15 deletions
diff --git a/ffi-macros/src/lib.rs b/ffi-macros/src/lib.rs
index 4c5df357..fd2bff2c 100644
--- a/ffi-macros/src/lib.rs
+++ b/ffi-macros/src/lib.rs
@@ -1,5 +1,7 @@
//! Common macros for Sequoia's FFI crates.
+#![recursion_limit="256"]
+
use std::collections::HashMap;
extern crate lazy_static;
@@ -172,6 +174,7 @@ pub fn ffi_wrapper_type(args: TokenStream, input: TokenStream) -> TokenStream {
let default_derives: &[DeriveFn] = &[
derive_free,
+ derive_conversion_traits,
];
let mut impls = TokenStream2::new();
for dfn in derive.into_iter().chain(default_derives.iter()) {
@@ -235,6 +238,74 @@ fn derive_functions() -> &'static HashMap<&'static str, DeriveFn>
&MAP
}
+/// Derives prefix_name_conversion_trait.
+fn derive_conversion_traits(_: proc_macro2::Span, _: &str, _: &str,
+ ty: &syn::Type)
+ -> TokenStream2
+{
+ quote! {
+ use MoveFromRaw;
+ impl MoveFromRaw<#ty> for *mut #ty {
+ fn move_from_raw(self) -> #ty {
+ *ffi_param_move!(self)
+ }
+ }
+
+ use RefRaw;
+ impl RefRaw<#ty> for *const #ty {
+ fn ref_raw(self) -> &'static #ty {
+ ffi_param_ref!(self)
+ }
+ }
+
+ use RefMutRaw;
+ impl RefMutRaw<#ty> for *mut #ty {
+ fn ref_mut_raw(self) -> &'static mut #ty {
+ ffi_param_ref_mut!(self)
+ }
+ }
+
+ use MoveIntoRaw;
+ impl MoveIntoRaw<*mut #ty> for #ty {
+ fn move_into_raw(self) -> *mut #ty {
+ Box::into_raw(Box::new(self))
+ }
+ }
+
+ impl MoveIntoRaw<Option<::std::ptr::NonNull<#ty>>>
+ for Option<#ty>
+ {
+ fn move_into_raw(self) -> Option<::std::ptr::NonNull<#ty>> {
+ self.map(|mut v| {
+ let ptr = Box::into_raw(Box::new(v));
+ ::std::ptr::NonNull::new(ptr).unwrap()
+ })
+ }
+ }
+
+ use MoveResultIntoRaw;
+ impl MoveResultIntoRaw<Option<::std::ptr::NonNull<#ty>>>
+ for ::failure::Fallible<#ty>
+ {
+ fn move_into_raw(self, errp: Option<&mut *mut ::failure::Error>)
+ -> Option<::std::ptr::NonNull<#ty>> {
+ match self {
+ Ok(v) => {
+ let ptr = Box::into_raw(Box::new(v));
+ Some(::std::ptr::NonNull::new(ptr).unwrap())
+ },
+ Err(e) => {
+ if let Some(errp) = errp {
+ *errp = box_raw!(e);
+ }
+ None
+ },
+ }
+ }
+ }
+ }
+}
+
/// Derives prefix_name_free.
fn derive_free(span: proc_macro2::Span, prefix: &str, name: &str,
ty: &syn::Type)
@@ -246,10 +317,8 @@ fn derive_free(span: proc_macro2::Span, prefix: &str, name: &str,
/// Frees this object.
#[::ffi_catch_abort] #[no_mangle]
pub extern "system" fn #ident (this: Option<&mut #ty>) {
- if let Some(ptr) = this {
- unsafe {
- drop(Box::from_raw(ptr))
- }
+ if let Some(ref_) = this {
+ drop((ref_ as *mut #wrapper).move_from_raw())
}
}
}
@@ -267,8 +336,7 @@ fn derive_clone(span: proc_macro2::Span, prefix: &str, name: &str,
#[::ffi_catch_abort] #[no_mangle]
pub extern "system" fn #ident (this: *const #ty)
-> *mut #ty {
- let this = ffi_param_ref!(this);
- box_raw!(this.clone())
+ this.ref_raw().clone().move_into_raw()
}
}
}
@@ -286,9 +354,7 @@ fn derive_equal(span: proc_macro2::Span, prefix: &str, name: &str,
pub extern "system" fn #ident (a: *const #ty,
b: *const #ty)
-> bool {
- let a = ffi_param_ref!(a);
- let b = ffi_param_ref!(b);
- a == b
+ a.ref_raw() == b.ref_raw()
}
}
}
@@ -307,8 +373,7 @@ fn derive_to_string(span: proc_macro2::Span, prefix: &str, name: &str,
#[::ffi_catch_abort] #[no_mangle]
pub extern "system" fn #ident (this: *const #ty)
-> *mut ::libc::c_char {
- let this = ffi_param_ref!(this);
- ffi_return_string!(format!("{}", this))
+ ffi_return_string!(format!("{}", this.ref_raw()))
}
}
}
@@ -326,8 +391,7 @@ fn derive_debug(span: proc_macro2::Span, prefix: &str, name: &str,
#[::ffi_catch_abort] #[no_mangle]
pub extern "system" fn #ident (this: *const #ty)
-> *mut ::libc::c_char {
- let this = ffi_param_ref!(this);
- ffi_return_string!(format!("{:?}", this))
+ ffi_return_string!(format!("{:?}", this.ref_raw()))
}
}
}
@@ -346,9 +410,8 @@ fn derive_hash(span: proc_macro2::Span, prefix: &str, name: &str,
-> ::libc::uint64_t {
use ::std::hash::{Hash, Hasher};
- let this = ffi_param_ref!(this);
let mut hasher = ::build_hasher();
- this.hash(&mut hasher);
+ this.ref_raw().hash(&mut hasher);
hasher.finish()
}
}