gecko-dev/servo/ports/cef/macros.rs

157 строки
6.0 KiB
Rust

/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#![macro_use]
macro_rules! check_ptr_exist {
($var:expr, $member:ident) => (
unsafe { (*CefWrap::to_c($var)).$member.is_some() }
);
}
// Provides the implementation of a CEF class. An example follows:
//
// struct ServoCefThing {
// ...
// }
//
// cef_class_impl! {
// ServoCefThing : CefThing, cef_thing_t {
// // Declare method implementations using the *C* API. (This may change later, once we
// // have associated types in Rust.)
// //
// // Note that if the method returns unit, you must write `-> ()` explicitly. This is
// // due to limitations of Rust's macro system.
// fn foo(&this, a: isize, b: *mut cef_other_thing_t) -> () {
// // Inside here, `a` will have type `isize`, and `b` will have the type
// // `CefOtherThing` -- i.e. the Rust-wrapped version of `cef_other_thing_t`.
// ...
// }
//
// fn bar(&this, a: isize) -> *mut cef_other_thing_t {
// // Return types are automatically unwrapped from the Rust types (e.g.
// // `CefOtherThing`) into the corresponding C types (e.g. `*mut
// // cef_other_thing_t`).
// let x: CefOtherThing = ...;
// x
// }
// }
// }
macro_rules! cef_class_impl(
($class_name:ident : $interface_name:ident, $c_interface_name:ident {
$(
fn $method_name:ident ( & $method_this:ident ,
$( $method_arg_name:ident : $c_method_arg_type:ty ,)* )
-> $method_return_type:ty {$method_body:block}
)*
}) => (
full_cef_class_impl! {
$class_name : $interface_name, $c_interface_name {
$(fn $method_name(&$method_this,
$($method_arg_name : $c_method_arg_type [$c_method_arg_type],)*)
-> $method_return_type {
$method_body
})*
}
}
)
);
macro_rules! full_cef_class_impl(
($class_name:ident : $interface_name:ident, $c_interface_name:ident {
$(
fn $method_name:ident ( & $method_this:ident ,
$( $method_arg_name:ident : $c_method_arg_type:ty [$method_arg_type:ty] ,)* )
-> $method_return_type:ty {$method_body:block}
)*
}) => (
impl $class_name {
pub fn as_cef_interface(self) -> $interface_name {
let cef_object = unsafe {
// Calculate the offset of the reference count. This is the size of the
// structure.
let null: *const $c_interface_name = ::std::ptr::null();
let offset: *const u32 = &(*null).ref_count;
let size = (offset as ::libc::size_t) - (null as ::libc::size_t);
$interface_name::from_c_object_addref(
::eutil::create_cef_object::<$c_interface_name,$class_name>(size))
};
unsafe {
$((*cef_object.c_object()).$method_name = Some($method_name as extern "C" fn(*mut $c_interface_name, $($c_method_arg_type,)*) -> $method_return_type);)*
let extra_slot =
::std::mem::transmute::<&mut u8,
&mut $class_name>(&mut (*cef_object.c_object())
.extra);
::std::ptr::write(extra_slot, self);
}
cef_object
}
}
$(
extern "C" fn $method_name(raw_this: *mut $c_interface_name,
$($method_arg_name: $c_method_arg_type),*)
-> $method_return_type {
let $method_this = unsafe {
$interface_name::from_c_object_addref(raw_this)
};
$(
let $method_arg_name: $method_arg_type = unsafe {
::wrappers::CefWrap::to_rust($method_arg_name)
};
)*
::wrappers::CefWrap::to_c($method_body)
}
)*
impl ::eutil::Downcast<$class_name> for $interface_name {
fn downcast(&self) -> &$class_name {
unsafe {
::std::mem::transmute::<&u8,&$class_name>(&(*self.c_object()).extra)
}
}
}
)
);
macro_rules! cef_static_method_impls(
(
$(
fn $method_name:ident ( $($method_arg_name:ident : $method_arg_type:ty ),* )
-> $method_return_type:ty {$method_body:block}
)*
) => (
$(
#[no_mangle]
pub extern "C" fn $method_name($($method_arg_name: $method_arg_type),*)
-> $method_return_type {
$(
let $method_arg_name = unsafe {
::wrappers::CefWrap::to_rust($method_arg_name)
};
)*
::wrappers::CefWrap::to_c($method_body)
}
)*
)
);
macro_rules! cef_stub_static_method_impls(
(
$(
fn $method_name:ident ( $($method_arg_name:ident : $method_arg_type:ty ),* )
-> $method_return_type:ty
)*
) => (
$(
#[no_mangle]
pub extern "C" fn $method_name($(_: $method_arg_type),*)
-> $method_return_type {
panic!("unimplemented static method: {}", stringify!($method_name))
}
)*
)
);