blob: 443eec71c5393247f76e8b865a1cb35a821ce2ab [file] [log] [blame] [edit]
// 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())
}