| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 1 | #![allow( |
| David Tolnay | 30d214c | 2020-03-15 23:54:34 -0700 | [diff] [blame] | 2 | clippy::inherent_to_string, |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 3 | clippy::large_enum_variant, |
| 4 | clippy::new_without_default, |
| 5 | clippy::or_fun_call, |
| 6 | clippy::toplevel_ref_arg, |
| 7 | clippy::useless_let_if_seq |
| 8 | )] |
| 9 | |
| 10 | extern crate proc_macro; |
| 11 | |
| David Tolnay | f3a9afa | 2020-10-08 23:22:12 -0700 | [diff] [blame^] | 12 | mod derive; |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 13 | mod expand; |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 14 | mod syntax; |
| David Tolnay | d09e012 | 2020-05-04 02:34:23 -0700 | [diff] [blame] | 15 | mod type_id; |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 16 | |
| David Tolnay | 05ef6ff | 2020-08-29 11:27:05 -0700 | [diff] [blame] | 17 | use crate::syntax::file::Module; |
| David Tolnay | 0841930 | 2020-04-19 20:38:20 -0700 | [diff] [blame] | 18 | use crate::syntax::namespace::Namespace; |
| David Tolnay | a8d94a1 | 2020-09-06 23:28:18 -0700 | [diff] [blame] | 19 | use crate::syntax::qualified::QualifiedName; |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 20 | use proc_macro::TokenStream; |
| David Tolnay | a8d94a1 | 2020-09-06 23:28:18 -0700 | [diff] [blame] | 21 | use syn::parse::{Parse, ParseStream, Result}; |
| 22 | use syn::parse_macro_input; |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 23 | |
| 24 | /// `#[cxx::bridge] mod ffi { ... }` |
| 25 | /// |
| 26 | /// Refer to the crate-level documentation for the explanation of how this macro |
| 27 | /// is intended to be used. |
| 28 | /// |
| 29 | /// The only additional thing to note here is namespace support — if the |
| 30 | /// types and functions on the `extern "C"` side of our bridge are in a |
| 31 | /// namespace, specify that namespace as an argument of the cxx::bridge |
| 32 | /// attribute macro. |
| 33 | /// |
| 34 | /// ``` |
| 35 | /// #[cxx::bridge(namespace = mycompany::rust)] |
| 36 | /// # mod ffi {} |
| 37 | /// ``` |
| 38 | /// |
| 39 | /// The types and functions from the `extern "Rust"` side of the bridge will be |
| 40 | /// placed into that same namespace in the generated C++ code. |
| 41 | #[proc_macro_attribute] |
| 42 | pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream { |
| 43 | let _ = syntax::error::ERRORS; |
| 44 | |
| 45 | let namespace = parse_macro_input!(args as Namespace); |
| David Tolnay | 3c64a4e | 2020-08-29 14:07:38 -0700 | [diff] [blame] | 46 | let mut ffi = parse_macro_input!(input as Module); |
| 47 | ffi.namespace = namespace; |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 48 | |
| David Tolnay | 3c64a4e | 2020-08-29 14:07:38 -0700 | [diff] [blame] | 49 | expand::bridge(ffi) |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 50 | .unwrap_or_else(|err| err.to_compile_error()) |
| 51 | .into() |
| 52 | } |
| David Tolnay | d09e012 | 2020-05-04 02:34:23 -0700 | [diff] [blame] | 53 | |
| 54 | #[proc_macro] |
| 55 | pub fn type_id(input: TokenStream) -> TokenStream { |
| David Tolnay | a8d94a1 | 2020-09-06 23:28:18 -0700 | [diff] [blame] | 56 | struct TypeId(QualifiedName); |
| 57 | |
| 58 | impl Parse for TypeId { |
| 59 | fn parse(input: ParseStream) -> Result<Self> { |
| 60 | QualifiedName::parse_quoted_or_unquoted(input).map(TypeId) |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | let arg = parse_macro_input!(input as TypeId); |
| 65 | type_id::expand(arg.0).into() |
| David Tolnay | d09e012 | 2020-05-04 02:34:23 -0700 | [diff] [blame] | 66 | } |