| Adrian Taylor | 9fc0846 | 2020-08-14 10:51:00 -0700 | [diff] [blame] | 1 | //! The CXX code generator for constructing and compiling C++ code. |
| 2 | //! |
| 3 | //! This is intended to be embedded into higher-level code generators. |
| 4 | |
| 5 | mod gen; |
| 6 | mod syntax; |
| 7 | |
| Adrian Taylor | 0926f64 | 2020-08-25 13:08:06 -0700 | [diff] [blame] | 8 | pub use crate::gen::Opt; |
| Adrian Taylor | 9fc0846 | 2020-08-14 10:51:00 -0700 | [diff] [blame] | 9 | use proc_macro2::TokenStream; |
| 10 | |
| David Tolnay | 366c41a | 2020-08-29 22:28:21 -0700 | [diff] [blame^] | 11 | pub use crate::gen::{Error, Result}; |
| 12 | |
| 13 | /// Results of code generation. |
| 14 | pub struct GeneratedCode { |
| 15 | /// The bytes of a C++ header file. |
| 16 | pub header: Vec<u8>, |
| 17 | /// The bytes of a C++ implementation file (e.g. .cc, cpp etc.) |
| 18 | pub cxx: Vec<u8>, |
| 19 | } |
| Adrian Taylor | 9fc0846 | 2020-08-14 10:51:00 -0700 | [diff] [blame] | 20 | |
| 21 | /// Generate C++ bindings code from a Rust token stream. This should be a Rust |
| 22 | /// token stream which somewhere contains a `#[cxx::bridge] mod {}`. |
| Adrian Taylor | 0926f64 | 2020-08-25 13:08:06 -0700 | [diff] [blame] | 23 | pub fn generate_header_and_cc(rust_source: TokenStream, opt: Opt) -> Result<GeneratedCode> { |
| David Tolnay | 366c41a | 2020-08-29 22:28:21 -0700 | [diff] [blame^] | 24 | let syntax = syn::parse2(rust_source)?; |
| 25 | match gen::generate(syntax, opt, true, true) { |
| 26 | Ok((Some(header), Some(cxx))) => Ok(GeneratedCode { header, cxx }), |
| 27 | Err(err) => Err(err), |
| 28 | _ => panic!("Unexpected generation"), |
| 29 | } |
| Adrian Taylor | 9fc0846 | 2020-08-14 10:51:00 -0700 | [diff] [blame] | 30 | } |
| Adrian Taylor | 593eddb | 2020-08-21 23:46:08 -0700 | [diff] [blame] | 31 | |
| 32 | #[cfg(test)] |
| 33 | mod test { |
| 34 | use quote::quote; |
| 35 | |
| 36 | #[test] |
| 37 | fn test_positive() { |
| 38 | let rs = quote! { |
| 39 | #[cxx::bridge] |
| 40 | mod ffi { |
| 41 | extern "C" { |
| 42 | fn in_C(); |
| 43 | } |
| 44 | extern "Rust" { |
| 45 | fn in_rs(); |
| 46 | } |
| 47 | } |
| 48 | }; |
| 49 | let code = crate::generate_header_and_cc(rs).unwrap(); |
| 50 | assert!(code.cxx.len() > 0); |
| 51 | assert!(code.header.len() > 0); |
| 52 | } |
| 53 | |
| 54 | #[test] |
| 55 | fn test_negative() { |
| 56 | let rs = quote! {}; |
| 57 | assert!(crate::generate_header_and_cc(rs).is_err()) |
| 58 | } |
| 59 | } |