| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 1 | #![allow( |
| David Tolnay | 05aa672 | 2020-12-29 15:06:36 -0800 | [diff] [blame] | 2 | clippy::cast_sign_loss, |
| 3 | clippy::default_trait_access, |
| 4 | clippy::doc_markdown, |
| 5 | clippy::enum_glob_use, |
| 6 | clippy::filter_map, |
| David Tolnay | 30d214c | 2020-03-15 23:54:34 -0700 | [diff] [blame] | 7 | clippy::inherent_to_string, |
| David Tolnay | 05aa672 | 2020-12-29 15:06:36 -0800 | [diff] [blame] | 8 | clippy::items_after_statements, |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 9 | clippy::large_enum_variant, |
| David Tolnay | 05aa672 | 2020-12-29 15:06:36 -0800 | [diff] [blame] | 10 | clippy::match_bool, |
| 11 | clippy::match_same_arms, |
| 12 | clippy::module_name_repetitions, |
| 13 | clippy::needless_pass_by_value, |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 14 | clippy::new_without_default, |
| David Tolnay | ef665fd | 2020-11-15 17:25:31 -0800 | [diff] [blame] | 15 | clippy::nonminimal_bool, |
| David Tolnay | 05aa672 | 2020-12-29 15:06:36 -0800 | [diff] [blame] | 16 | clippy::option_if_let_else, |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 17 | clippy::or_fun_call, |
| David Tolnay | 05aa672 | 2020-12-29 15:06:36 -0800 | [diff] [blame] | 18 | clippy::redundant_else, |
| 19 | clippy::shadow_unrelated, |
| 20 | clippy::similar_names, |
| David Tolnay | 982158b | 2020-11-27 15:58:49 -0800 | [diff] [blame] | 21 | clippy::single_match, |
| David Tolnay | 05aa672 | 2020-12-29 15:06:36 -0800 | [diff] [blame] | 22 | clippy::single_match_else, |
| David Tolnay | edff9c0 | 2020-11-27 20:53:56 -0800 | [diff] [blame] | 23 | clippy::too_many_arguments, |
| David Tolnay | 05aa672 | 2020-12-29 15:06:36 -0800 | [diff] [blame] | 24 | clippy::too_many_lines, |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 25 | clippy::toplevel_ref_arg, |
| 26 | clippy::useless_let_if_seq |
| 27 | )] |
| 28 | |
| 29 | extern crate proc_macro; |
| 30 | |
| David Tolnay | d8ad970 | 2020-11-27 12:43:59 -0800 | [diff] [blame] | 31 | mod derive; |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 32 | mod expand; |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 33 | mod syntax; |
| David Tolnay | d09e012 | 2020-05-04 02:34:23 -0700 | [diff] [blame] | 34 | mod type_id; |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 35 | |
| David Tolnay | 05ef6ff | 2020-08-29 11:27:05 -0700 | [diff] [blame] | 36 | use crate::syntax::file::Module; |
| David Tolnay | 0841930 | 2020-04-19 20:38:20 -0700 | [diff] [blame] | 37 | use crate::syntax::namespace::Namespace; |
| David Tolnay | a8d94a1 | 2020-09-06 23:28:18 -0700 | [diff] [blame] | 38 | use crate::syntax::qualified::QualifiedName; |
| David Tolnay | 3403ae8 | 2021-02-11 22:34:50 -0800 | [diff] [blame^] | 39 | use crate::type_id::Crate; |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 40 | use proc_macro::TokenStream; |
| Adrian Taylor | 3e5cff4 | 2020-10-29 19:48:45 -0700 | [diff] [blame] | 41 | use syn::parse::{Parse, ParseStream, Parser, Result}; |
| David Tolnay | a8d94a1 | 2020-09-06 23:28:18 -0700 | [diff] [blame] | 42 | use syn::parse_macro_input; |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 43 | |
| 44 | /// `#[cxx::bridge] mod ffi { ... }` |
| 45 | /// |
| 46 | /// Refer to the crate-level documentation for the explanation of how this macro |
| 47 | /// is intended to be used. |
| 48 | /// |
| 49 | /// The only additional thing to note here is namespace support — if the |
| David Tolnay | c72a9f6 | 2020-11-11 10:56:26 -0800 | [diff] [blame] | 50 | /// types and functions on the `extern "C++"` side of our bridge are in a |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 51 | /// namespace, specify that namespace as an argument of the cxx::bridge |
| 52 | /// attribute macro. |
| 53 | /// |
| 54 | /// ``` |
| David Tolnay | 7907966 | 2020-11-01 09:11:55 -0800 | [diff] [blame] | 55 | /// #[cxx::bridge(namespace = "mycompany::rust")] |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 56 | /// # mod ffi {} |
| 57 | /// ``` |
| 58 | /// |
| 59 | /// The types and functions from the `extern "Rust"` side of the bridge will be |
| 60 | /// placed into that same namespace in the generated C++ code. |
| 61 | #[proc_macro_attribute] |
| 62 | pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream { |
| 63 | let _ = syntax::error::ERRORS; |
| 64 | |
| Adrian Taylor | 3e5cff4 | 2020-10-29 19:48:45 -0700 | [diff] [blame] | 65 | let namespace = match Namespace::parse_bridge_attr_namespace.parse(args) { |
| David Tolnay | d7a3a18 | 2020-11-01 20:45:14 -0800 | [diff] [blame] | 66 | Ok(namespace) => namespace, |
| Adrian Taylor | 3e5cff4 | 2020-10-29 19:48:45 -0700 | [diff] [blame] | 67 | Err(err) => return err.to_compile_error().into(), |
| 68 | }; |
| David Tolnay | 3c64a4e | 2020-08-29 14:07:38 -0700 | [diff] [blame] | 69 | let mut ffi = parse_macro_input!(input as Module); |
| 70 | ffi.namespace = namespace; |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 71 | |
| David Tolnay | 3c64a4e | 2020-08-29 14:07:38 -0700 | [diff] [blame] | 72 | expand::bridge(ffi) |
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 73 | .unwrap_or_else(|err| err.to_compile_error()) |
| 74 | .into() |
| 75 | } |
| David Tolnay | d09e012 | 2020-05-04 02:34:23 -0700 | [diff] [blame] | 76 | |
| 77 | #[proc_macro] |
| 78 | pub fn type_id(input: TokenStream) -> TokenStream { |
| David Tolnay | cedd855 | 2021-02-11 22:29:07 -0800 | [diff] [blame] | 79 | struct TypeId { |
| David Tolnay | 3403ae8 | 2021-02-11 22:34:50 -0800 | [diff] [blame^] | 80 | krate: Crate, |
| David Tolnay | cedd855 | 2021-02-11 22:29:07 -0800 | [diff] [blame] | 81 | path: QualifiedName, |
| 82 | } |
| David Tolnay | a8d94a1 | 2020-09-06 23:28:18 -0700 | [diff] [blame] | 83 | |
| 84 | impl Parse for TypeId { |
| 85 | fn parse(input: ParseStream) -> Result<Self> { |
| David Tolnay | 3403ae8 | 2021-02-11 22:34:50 -0800 | [diff] [blame^] | 86 | let krate = input.parse().map(Crate::DollarCrate)?; |
| David Tolnay | cedd855 | 2021-02-11 22:29:07 -0800 | [diff] [blame] | 87 | let path = QualifiedName::parse_quoted_or_unquoted(input)?; |
| 88 | Ok(TypeId { krate, path }) |
| David Tolnay | a8d94a1 | 2020-09-06 23:28:18 -0700 | [diff] [blame] | 89 | } |
| 90 | } |
| 91 | |
| 92 | let arg = parse_macro_input!(input as TypeId); |
| David Tolnay | cedd855 | 2021-02-11 22:29:07 -0800 | [diff] [blame] | 93 | type_id::expand(arg.path).into() |
| David Tolnay | d09e012 | 2020-05-04 02:34:23 -0700 | [diff] [blame] | 94 | } |