Marcel Hlopko | 884ae7f | 2021-08-18 13:58:22 +0000 | [diff] [blame] | 1 | // 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 Hlopko | 45fba97 | 2021-08-23 19:52:20 +0000 | [diff] [blame] | 5 | use std::boxed::Box; |
Marcel Hlopko | 884ae7f | 2021-08-18 13:58:22 +0000 | [diff] [blame] | 6 | use std::panic::catch_unwind; |
| 7 | use std::process; |
| 8 | use std::slice; |
| 9 | |
Googler | f427e6a | 2021-10-01 07:59:59 +0000 | [diff] [blame] | 10 | /// Returns an `FfiU8SliceBox` containing a copy of the data in `ffi_u8_slice`. |
| 11 | /// The returned `FfiU8SliceBox` must be freed by calling `FreeFfiU8SliceBox()`. |
Lukasz Anforowicz | dd9ae0f | 2022-02-17 15:52:53 +0000 | [diff] [blame] | 12 | /// |
| 13 | /// # Safety |
| 14 | /// |
| 15 | /// Expectations: |
Devin Jeanpierre | 1b8f4a1 | 2022-03-22 21:29:42 +0000 | [diff] [blame] | 16 | /// * function expects that param `input` is a FfiU8Slice for a valid array |
| 17 | /// of bytes with the given size. |
Lukasz Anforowicz | dd9ae0f | 2022-02-17 15:52:53 +0000 | [diff] [blame] | 18 | /// * 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 |
Googler | f427e6a | 2021-10-01 07:59:59 +0000 | [diff] [blame] | 26 | #[no_mangle] |
| 27 | pub unsafe extern "C" fn AllocFfiU8SliceBox(input: FfiU8Slice) -> FfiU8SliceBox { |
| 28 | FfiU8SliceBox::from_boxed_slice(Box::<[u8]>::from(input.as_slice())) |
| 29 | } |
| 30 | |
Marcel Hlopko | 884ae7f | 2021-08-18 13:58:22 +0000 | [diff] [blame] | 31 | /// Frees `FfiU8SliceBox` allocated by Rust. |
Lukasz Anforowicz | dd9ae0f | 2022-02-17 15:52:53 +0000 | [diff] [blame] | 32 | /// |
| 33 | /// # Safety |
| 34 | /// |
| 35 | /// Expectations: |
| 36 | /// * function expects that param `sb` is a valid FfiU8SliceBox that has been |
| 37 | /// allocated earlier by AllocFfiU8SliceBox. |
Devin Jeanpierre | 1b8f4a1 | 2022-03-22 21:29:42 +0000 | [diff] [blame] | 38 | /// * function expects that there are no remaining references to |
| 39 | /// FfiU8SliceBox |
Lukasz Anforowicz | dd9ae0f | 2022-02-17 15:52:53 +0000 | [diff] [blame] | 40 | /// |
| 41 | /// Ownership: |
| 42 | /// * function takes ownership of the param `sb` and frees its memory. |
Marcel Hlopko | 884ae7f | 2021-08-18 13:58:22 +0000 | [diff] [blame] | 43 | #[no_mangle] |
| 44 | pub 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)] |
| 52 | pub struct FfiU8Slice { |
| 53 | ptr: *const u8, |
| 54 | size: usize, |
| 55 | } |
| 56 | |
| 57 | impl FfiU8Slice { |
Googler | f427e6a | 2021-10-01 07:59:59 +0000 | [diff] [blame] | 58 | /// 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 Hlopko | 884ae7f | 2021-08-18 13:58:22 +0000 | [diff] [blame] | 63 | /// Borrows data pointed to by this `FfiU8Slice` as a slice. |
| 64 | pub fn as_slice(&self) -> &[u8] { |
| 65 | // Safety: |
Michael Forster | bee8448 | 2021-10-13 08:35:38 +0000 | [diff] [blame] | 66 | // Instances of `FfiU8Slice` are only created by FFI functions, which are unsafe |
| 67 | // themselves so it's their responsibility to maintain safety. |
Marcel Hlopko | 884ae7f | 2021-08-18 13:58:22 +0000 | [diff] [blame] | 68 | unsafe { slice::from_raw_parts(self.ptr, self.size) } |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | #[repr(C)] |
| 73 | pub struct FfiU8SliceBox { |
| 74 | ptr: *const u8, |
| 75 | size: usize, |
| 76 | } |
| 77 | |
| 78 | impl 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 Forster | bee8448 | 2021-10-13 08:35:38 +0000 | [diff] [blame] | 87 | // 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 Hlopko | 884ae7f | 2021-08-18 13:58:22 +0000 | [diff] [blame] | 90 | unsafe { Box::from_raw(slice::from_raw_parts_mut(self.ptr as *mut u8, self.size)) } |
| 91 | } |
| 92 | } |
| 93 | |
Googler | 69e0963 | 2023-03-03 12:18:35 -0800 | [diff] [blame] | 94 | /// Whether or not the generated binding will have doc comments indicating their |
| 95 | /// source location. |
| 96 | #[repr(C)] |
Devin Jeanpierre | ab8732a | 2023-03-22 19:09:03 -0700 | [diff] [blame] | 97 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
Googler | 69e0963 | 2023-03-03 12:18:35 -0800 | [diff] [blame] | 98 | pub enum SourceLocationDocComment { |
| 99 | Disabled, |
| 100 | Enabled, |
| 101 | } |
| 102 | |
Marcel Hlopko | 884ae7f | 2021-08-18 13:58:22 +0000 | [diff] [blame] | 103 | #[cfg(test)] |
| 104 | mod 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 | } |