Bug 1452620 - Add an FfiVec structure. r?Gankro draft
authorKartikaya Gupta <kgupta@mozilla.com>
Tue, 10 Apr 2018 17:26:53 -0400
changeset 779947 dcff36504495645bd51c366533156cc99ed1b8e0
parent 779792 678d8879488d996057af4549272df130fd6101f7
child 779948 2f7bb998a74aa5c2c6e7a2f57ca3a2a9992451ca
push id105919
push userkgupta@mozilla.com
push dateTue, 10 Apr 2018 21:27:12 +0000
reviewersGankro
bugs1452620
milestone61.0a1
Bug 1452620 - Add an FfiVec structure. r?Gankro This structure makes it more ergonomic to access vectors from C++. A Vec<T> can be converted to FfiVec<T> which can safely cross the FFI boundary. That provides an easy to use read-only access mechanism to the vector contents. The FfiVec must be returned to rust code to be freed properly. MozReview-Commit-ID: AdIyEsjrPSZ
gfx/webrender_bindings/src/bindings.rs
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -154,16 +154,49 @@ impl WrVecU8 {
 
     fn push_bytes(&mut self, bytes: &[u8]) {
         let mut vec = self.flush_into_vec();
         vec.extend_from_slice(bytes);
         *self = Self::from_vec(vec);
     }
 }
 
+#[repr(C)]
+pub struct FfiVec<T> {
+    // We use a *const instead of a *mut because we don't want the C++ side
+    // to be mutating this. It is strictly read-only from C++
+    data: *const T,
+    length: usize,
+    capacity: usize,
+}
+
+impl<T> FfiVec<T> {
+    fn from_vec(v: Vec<T>) -> FfiVec<T> {
+        let ret = FfiVec {
+            data: v.as_ptr(),
+            length: v.len(),
+            capacity: v.capacity(),
+        };
+        mem::forget(v);
+        ret
+    }
+}
+
+impl<T> Drop for FfiVec<T> {
+    fn drop(&mut self) {
+        // turn the stuff back into a Vec and let it be freed normally
+        let _ = unsafe {
+            Vec::from_raw_parts(
+                self.data as *mut T,
+                self.length,
+                self.capacity
+            )
+        };
+    }
+}
 
 #[no_mangle]
 pub extern "C" fn wr_vec_u8_push_bytes(v: &mut WrVecU8, bytes: ByteSlice) {
     v.push_bytes(bytes.as_slice());
 }
 
 #[no_mangle]
 pub extern "C" fn wr_vec_u8_free(v: WrVecU8) {