This is an automated email from the ASF dual-hosted git repository.

uwe pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/master by this push:
     new 6633cc9  ARROW-2433: [Rust] Add Builder.push_slice(&[T])
6633cc9 is described below

commit 6633cc94c84f9ecc516f03175da56361cf4bd67f
Author: Andy Grove <andygrov...@gmail.com>
AuthorDate: Tue Apr 10 10:56:29 2018 +0200

    ARROW-2433: [Rust] Add Builder.push_slice(&[T])
    
    This PR also fixes another instance of memory not being released.
    
    Author: Andy Grove <andygrov...@gmail.com>
    
    Closes #1871 from andygrove/push_slice and squashes the following commits:
    
    40a6c30 <Andy Grove> Add Builder.push_slice()
    31ef90b <Andy Grove> Merge remote-tracking branch 'upstream/master'
    2f87c70 <Andy Grove> Fix build - add missing import
---
 rust/src/builder.rs | 86 ++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 72 insertions(+), 14 deletions(-)

diff --git a/rust/src/builder.rs b/rust/src/builder.rs
index 1744b4e..15f492d 100644
--- a/rust/src/builder.rs
+++ b/rust/src/builder.rs
@@ -16,6 +16,7 @@
 // under the License.
 
 use libc;
+use std::cmp;
 use std::mem;
 use std::ptr;
 use std::slice;
@@ -53,6 +54,14 @@ impl<T> Builder<T> {
         }
     }
 
+    pub fn len(&self) -> usize {
+        self.len
+    }
+
+    pub fn capacity(&self) -> usize {
+        self.capacity
+    }
+
     /// Get the internal byte-aligned memory buffer as a mutable slice
     pub fn slice_mut(&self, start: usize, end: usize) -> &mut [T] {
         assert!(start <= end);
@@ -72,20 +81,8 @@ impl<T> Builder<T> {
     pub fn push(&mut self, v: T) {
         assert!(!self.data.is_null());
         if self.len == self.capacity {
-            let sz = mem::size_of::<T>();
-            let new_capacity = self.capacity * 2;
-            unsafe {
-                let old_buffer = self.data;
-                let new_buffer = allocate_aligned((new_capacity * sz) as 
i64).unwrap();
-                libc::memcpy(
-                    mem::transmute::<*const u8, *mut libc::c_void>(new_buffer),
-                    mem::transmute::<*const T, *const 
libc::c_void>(old_buffer),
-                    self.len * sz,
-                );
-                self.capacity = new_capacity;
-                self.data = mem::transmute::<*const u8, *mut T>(new_buffer);
-                mem::drop(old_buffer);
-            }
+            let new_capacity = self.capacity;
+            self.grow(new_capacity * 2);
         }
         assert!(self.len < self.capacity);
         unsafe {
@@ -94,6 +91,45 @@ impl<T> Builder<T> {
         self.len += 1;
     }
 
+    /// push a slice of type T, growing the internal buffer as needed
+    pub fn push_slice(&mut self, slice: &[T]) {
+        self.reserve(slice.len());
+        let sz = mem::size_of::<T>();
+        unsafe {
+            libc::memcpy(
+                mem::transmute::<*mut T, *mut 
libc::c_void>(self.data.offset(self.len() as isize)),
+                mem::transmute::<*const T, *const 
libc::c_void>(slice.as_ptr()),
+                slice.len() * sz,
+            );
+        }
+        self.len += slice.len();
+    }
+
+    /// Reserve memory for n elements of type T
+    pub fn reserve(&mut self, n: usize) {
+        if self.len + n > self.capacity {
+            let new_capacity = cmp::max(self.capacity * 2, n);
+            self.grow(new_capacity);
+        }
+    }
+
+    /// Grow the buffer to the new size n (number of elements of type T)
+    fn grow(&mut self, new_capacity: usize) {
+        let sz = mem::size_of::<T>();
+        unsafe {
+            let old_buffer = self.data;
+            let new_buffer = allocate_aligned((new_capacity * sz) as 
i64).unwrap();
+            libc::memcpy(
+                mem::transmute::<*const u8, *mut libc::c_void>(new_buffer),
+                mem::transmute::<*const T, *const libc::c_void>(old_buffer),
+                self.len * sz,
+            );
+            self.capacity = new_capacity;
+            self.data = mem::transmute::<*const u8, *mut T>(new_buffer);
+            libc::free(mem::transmute::<*mut T, *mut 
libc::c_void>(old_buffer));
+        }
+    }
+
     /// Build a Buffer from the existing memory
     pub fn finish(&mut self) -> Buffer<T> {
         assert!(!self.data.is_null());
@@ -162,4 +198,26 @@ mod tests {
         }
     }
 
+    #[test]
+    fn test_reserve() {
+        let mut b: Builder<u8> = Builder::with_capacity(2);
+        assert_eq!(2, b.capacity());
+        b.reserve(2);
+        assert_eq!(2, b.capacity());
+        b.reserve(3);
+        assert_eq!(4, b.capacity());
+    }
+
+    #[test]
+    fn test_push_slice() {
+        let mut b: Builder<u8> = Builder::new();
+        b.push_slice("Hello, ".as_bytes());
+        b.push_slice("World!".as_bytes());
+        let buffer = b.finish();
+        assert_eq!(13, buffer.len());
+
+        let s = String::from_utf8(buffer.iter().collect::<Vec<u8>>()).unwrap();
+        assert_eq!("Hello, World!", s);
+    }
+
 }

-- 
To stop receiving notification emails like this one, please contact
u...@apache.org.

Reply via email to