sn_ffi_utils/vec.rs
1// Copyright 2019 MaidSafe.net limited.
2//
3// This SAFE Network Software is licensed to you under the MIT license <LICENSE-MIT
4// http://opensource.org/licenses/MIT> or the Modified BSD license <LICENSE-BSD
5// https://opensource.org/licenses/BSD-3-Clause>, at your option. This file may not be copied,
6// modified, or distributed except according to those terms. Please review the Licences for the
7// specific language governing permissions and limitations relating to use of the SAFE Network
8// Software.
9
10use std::mem;
11use std::ptr;
12use std::slice;
13
14/// Provides FFI-safe pointers, as opposed to raw `as_ptr()` in `Vec` and `String` which can return
15/// values such as `0x01` that can cause segmentation faults with the automatic pointer
16/// dereferencing on the front-end side (e.g. in Node.js).
17pub trait SafePtr {
18 /// Resulting pointer type.
19 type Ptr;
20
21 /// Returns a pointer that guarantees safe dereferencing on the front-end side.
22 fn as_safe_ptr(&self) -> *const Self::Ptr;
23}
24
25impl<T> SafePtr for Vec<T> {
26 type Ptr = T;
27
28 fn as_safe_ptr(&self) -> *const T {
29 if self.is_empty() {
30 ptr::null()
31 } else {
32 self.as_ptr()
33 }
34 }
35}
36
37/// Consumes a `Vec` and transfers ownership of the data to a C caller, returning (pointer, size).
38///
39/// The pointer which this function returns must be returned to Rust and reconstituted using
40/// `vec_from_raw_parts` to be properly deallocated. Specifically, one should not use the standard C
41/// `free()` function to deallocate this data.
42///
43/// Failure to call `vec_from_raw_parts` will lead to a memory leak.
44pub fn vec_into_raw_parts<T>(v: Vec<T>) -> (*mut T, usize) {
45 let mut b = v.into_boxed_slice();
46 let ptr = b.as_mut_ptr();
47 let len = b.len();
48 mem::forget(b);
49 (ptr, len)
50}
51
52/// Retakes ownership of a `Vec` that was transferred to C via `vec_into_raw_parts`.
53///
54/// # Safety
55///
56/// Unsafe. See documentation for `slice::from_raw_parts_mut` and `Box::from_raw`.
57pub unsafe fn vec_from_raw_parts<T>(ptr: *mut T, len: usize) -> Vec<T> {
58 Box::from_raw(slice::from_raw_parts_mut(ptr, len)).into_vec()
59}
60
61/// Converts a pointer and length to `Vec` by cloning the contents.
62/// Note: This does NOT free the memory pointed to by `ptr`.
63///
64/// # Safety
65///
66/// Unsafe. See documentation for `slice::from_raw_parts`.
67pub unsafe fn vec_clone_from_raw_parts<T: Clone>(ptr: *const T, len: usize) -> Vec<T> {
68 slice::from_raw_parts(ptr, len).to_vec()
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn vec_conversions() {
77 for _ in 0..5 {
78 let v = vec!["foo", "bar"];
79
80 for _ in 0..5 {
81 let (ptr, len) = vec_into_raw_parts(v.clone());
82 let v2 = unsafe { vec_clone_from_raw_parts(ptr, len) };
83 assert_eq!(v, v2);
84 let v3 = unsafe { vec_from_raw_parts(ptr, len) };
85 assert_eq!(v, v3);
86 }
87 }
88 }
89}