| // Part of the Crubit project, under the Apache License v2.0 with LLVM |
| // Exceptions. See /LICENSE for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| |
| use database::code_snippet::{Bindings, FfiBindings}; |
| use error_report::{ErrorReport, ErrorReporting, FatalErrors}; |
| use ffi_types::{Environment, FfiU8Slice, FfiU8SliceBox}; |
| use generate_bindings::generate_bindings; |
| use std::ffi::OsString; |
| use std::panic::catch_unwind; |
| use std::process; |
| |
| /// Deserializes IR from `json` and generates bindings source code. |
| /// |
| /// This function aborts on error. |
| /// |
| /// # Safety |
| /// |
| /// Expectations: |
| /// * `json` should be a FfiU8Slice for a valid array of bytes with the given |
| /// size. |
| /// * `crubit_support_path_format` should be a FfiU8Slice for a valid array |
| /// of bytes representing an UTF8-encoded string |
| /// * `rustfmt_exe_path` and `rustfmt_config_path` should both be a |
| /// FfiU8Slice for a valid array of bytes representing an UTF8-encoded |
| /// string (without the UTF-8 requirement, it seems that Rust doesn't offer |
| /// a way to convert to OsString on Windows) |
| /// * `json`, `crubit_support_path_format`, `rustfmt_exe_path`, and |
| /// `rustfmt_config_path` shouldn't change during the call. |
| /// |
| /// Ownership: |
| /// * function doesn't take ownership of (in other words it borrows) the |
| /// input params: `json`, `crubit_support_path_format`, `rustfmt_exe_path`, |
| /// and `rustfmt_config_path` |
| /// * function passes ownership of the returned value to the caller |
| #[unsafe(no_mangle)] |
| pub unsafe extern "C" fn GenerateBindingsImpl( |
| json: FfiU8Slice, |
| crubit_support_path_format: FfiU8Slice, |
| clang_format_exe_path: FfiU8Slice, |
| rustfmt_exe_path: FfiU8Slice, |
| rustfmt_config_path: FfiU8Slice, |
| generate_error_report: bool, |
| environment: Environment, |
| ) -> FfiBindings { |
| let json: &[u8] = json.as_slice(); |
| let crubit_support_path_format: &str = |
| std::str::from_utf8(crubit_support_path_format.as_slice()).unwrap(); |
| let clang_format_exe_path: OsString = |
| std::str::from_utf8(clang_format_exe_path.as_slice()).unwrap().into(); |
| let rustfmt_exe_path: OsString = |
| std::str::from_utf8(rustfmt_exe_path.as_slice()).unwrap().into(); |
| let rustfmt_config_path: OsString = |
| std::str::from_utf8(rustfmt_config_path.as_slice()).unwrap().into(); |
| catch_unwind(|| { |
| let error_report: Option<ErrorReport>; |
| let errors: &dyn ErrorReporting = if generate_error_report { |
| error_report = Some(ErrorReport::new()); |
| error_report.as_ref().unwrap() |
| } else { |
| error_report = None; |
| &error_report::IgnoreErrors |
| }; |
| let fatal_errors = FatalErrors::new(); |
| let Bindings { rs_api, rs_api_impl } = generate_bindings( |
| json, |
| crubit_support_path_format, |
| &clang_format_exe_path, |
| &rustfmt_exe_path, |
| &rustfmt_config_path, |
| errors, |
| &fatal_errors, |
| environment, |
| ) |
| .unwrap(); |
| FfiBindings { |
| rs_api: FfiU8SliceBox::from_boxed_slice(rs_api.into_bytes().into_boxed_slice()), |
| rs_api_impl: FfiU8SliceBox::from_boxed_slice( |
| rs_api_impl.into_bytes().into_boxed_slice(), |
| ), |
| error_report: FfiU8SliceBox::from_boxed_slice( |
| error_report |
| .map(|s| s.to_json_string().into_bytes().into_boxed_slice()) |
| .unwrap_or_else(|| Box::new([])), |
| ), |
| fatal_errors: FfiU8SliceBox::from_boxed_slice( |
| fatal_errors.take_string().into_bytes().into_boxed_slice(), |
| ), |
| } |
| }) |
| .unwrap_or_else(|_| process::abort()) |
| } |