blob: ee75fdf9ccdf0477f6cd7eb53d14233b610550f5 [file] [log] [blame]
Marcel Hlopko884ae7f2021-08-18 13:58:22 +00001// Part of the Crubit project, under the Apache License v2.0 with LLVM
2// Exceptions. See /LICENSE for license information.
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
Marcel Hlopko45fba972021-08-23 19:52:20 +00005use std::boxed::Box;
Marcel Hlopko884ae7f2021-08-18 13:58:22 +00006use std::panic::catch_unwind;
7use std::process;
8use std::slice;
9
Googlerf427e6a2021-10-01 07:59:59 +000010/// Returns an `FfiU8SliceBox` containing a copy of the data in `ffi_u8_slice`.
11/// The returned `FfiU8SliceBox` must be freed by calling `FreeFfiU8SliceBox()`.
Lukasz Anforowiczdd9ae0f2022-02-17 15:52:53 +000012///
13/// # Safety
14///
15/// Expectations:
Devin Jeanpierre1b8f4a12022-03-22 21:29:42 +000016/// * function expects that param `input` is a FfiU8Slice for a valid array
17/// of bytes with the given size.
Lukasz Anforowiczdd9ae0f2022-02-17 15:52:53 +000018/// * function expects that param `input` doesn't change during the call, but
19/// it is okay if it changes afterwards (because the data from `input` will
20/// be copied/boxed into heap).
21///
22/// Ownership:
23/// * function doesn't take ownership of (in other words it borrows) the
24/// param `input`
25/// * function passes ownership of the returned value to the caller
Googlerf427e6a2021-10-01 07:59:59 +000026#[no_mangle]
27pub unsafe extern "C" fn AllocFfiU8SliceBox(input: FfiU8Slice) -> FfiU8SliceBox {
28 FfiU8SliceBox::from_boxed_slice(Box::<[u8]>::from(input.as_slice()))
29}
30
Marcel Hlopko884ae7f2021-08-18 13:58:22 +000031/// Frees `FfiU8SliceBox` allocated by Rust.
Lukasz Anforowiczdd9ae0f2022-02-17 15:52:53 +000032///
33/// # Safety
34///
35/// Expectations:
36/// * function expects that param `sb` is a valid FfiU8SliceBox that has been
37/// allocated earlier by AllocFfiU8SliceBox.
Devin Jeanpierre1b8f4a12022-03-22 21:29:42 +000038/// * function expects that there are no remaining references to
39/// FfiU8SliceBox
Lukasz Anforowiczdd9ae0f2022-02-17 15:52:53 +000040///
41/// Ownership:
42/// * function takes ownership of the param `sb` and frees its memory.
Marcel Hlopko884ae7f2021-08-18 13:58:22 +000043#[no_mangle]
44pub unsafe extern "C" fn FreeFfiU8SliceBox(sb: FfiU8SliceBox) {
45 catch_unwind(|| {
46 let _ = sb.into_boxed_slice();
47 })
48 .unwrap_or_else(|_| process::abort())
49}
50
51#[repr(C)]
52pub struct FfiU8Slice {
53 ptr: *const u8,
54 size: usize,
55}
56
57impl FfiU8Slice {
Googlerf427e6a2021-10-01 07:59:59 +000058 /// Returns an FfiU8Slice pointing to the data of `slice`.
59 pub fn from_slice(slice: &[u8]) -> FfiU8Slice {
60 FfiU8Slice { ptr: slice.as_ptr(), size: slice.len() }
61 }
62
Marcel Hlopko884ae7f2021-08-18 13:58:22 +000063 /// Borrows data pointed to by this `FfiU8Slice` as a slice.
64 pub fn as_slice(&self) -> &[u8] {
65 // Safety:
Michael Forsterbee84482021-10-13 08:35:38 +000066 // Instances of `FfiU8Slice` are only created by FFI functions, which are unsafe
67 // themselves so it's their responsibility to maintain safety.
Marcel Hlopko884ae7f2021-08-18 13:58:22 +000068 unsafe { slice::from_raw_parts(self.ptr, self.size) }
69 }
70}
71
72#[repr(C)]
73pub struct FfiU8SliceBox {
74 ptr: *const u8,
75 size: usize,
76}
77
78impl FfiU8SliceBox {
79 pub fn from_boxed_slice(bytes: Box<[u8]>) -> FfiU8SliceBox {
80 let slice = Box::leak(bytes);
81 FfiU8SliceBox { ptr: slice.as_mut_ptr(), size: slice.len() }
82 }
83
84 /// Consumes self and returns boxed slice.
85 pub fn into_boxed_slice(self) -> Box<[u8]> {
86 // Safety:
Michael Forsterbee84482021-10-13 08:35:38 +000087 // Instances of `FfiU8SliceBox` are either created by `from_boxed_slice`, which
88 // is safe, or by FFI functions, which are unsafe themselves so it's
89 // their responsibility to maintain safety.
Marcel Hlopko884ae7f2021-08-18 13:58:22 +000090 unsafe { Box::from_raw(slice::from_raw_parts_mut(self.ptr as *mut u8, self.size)) }
91 }
92}
93
Googler69e09632023-03-03 12:18:35 -080094/// Whether or not the generated binding will have doc comments indicating their
95/// source location.
96#[repr(C)]
Devin Jeanpierreab8732a2023-03-22 19:09:03 -070097#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
Googler69e09632023-03-03 12:18:35 -080098pub enum SourceLocationDocComment {
99 Disabled,
100 Enabled,
101}
102
Marcel Hlopko884ae7f2021-08-18 13:58:22 +0000103#[cfg(test)]
104mod tests {
105 use super::*;
106
107 #[test]
108 fn test_from_into_ffi_u8_slice_box() {
109 let slice = Box::<[u8]>::from(*b"Hello World!");
110 let ffi_slice = FfiU8SliceBox::from_boxed_slice(slice.clone());
111 assert_eq!(ffi_slice.into_boxed_slice(), slice);
112 }
113}