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}