1 use log::debug; 2 3 use crate::sys::jsize; 4 use crate::wrapper::objects::ReleaseMode; 5 use crate::{errors::*, objects::JObject, JNIEnv}; 6 use std::os::raw::c_void; 7 use std::ptr::NonNull; 8 9 /// Auto-release wrapper for pointer-based primitive arrays. 10 /// 11 /// This wrapper is used to wrap pointers returned by GetPrimitiveArrayCritical. 12 /// While wrapped, the object can be accessed via the `From` impl. 13 /// 14 /// AutoPrimitiveArray provides automatic array release through a call to 15 /// ReleasePrimitiveArrayCritical when it goes out of scope. 16 pub struct AutoPrimitiveArray<'a: 'b, 'b> { 17 obj: JObject<'a>, 18 ptr: NonNull<c_void>, 19 mode: ReleaseMode, 20 is_copy: bool, 21 env: &'b JNIEnv<'a>, 22 } 23 24 impl<'a, 'b> AutoPrimitiveArray<'a, 'b> { new( env: &'b JNIEnv<'a>, obj: JObject<'a>, ptr: *mut c_void, mode: ReleaseMode, is_copy: bool, ) -> Result<Self>25 pub(crate) fn new( 26 env: &'b JNIEnv<'a>, 27 obj: JObject<'a>, 28 ptr: *mut c_void, 29 mode: ReleaseMode, 30 is_copy: bool, 31 ) -> Result<Self> { 32 Ok(AutoPrimitiveArray { 33 obj, 34 ptr: NonNull::new(ptr).ok_or(Error::NullPtr("Non-null ptr expected"))?, 35 mode, 36 is_copy, 37 env, 38 }) 39 } 40 41 /// Get a reference to the wrapped pointer as_ptr(&self) -> *mut c_void42 pub fn as_ptr(&self) -> *mut c_void { 43 self.ptr.as_ptr() 44 } 45 release_primitive_array_critical(&mut self, mode: i32) -> Result<()>46 fn release_primitive_array_critical(&mut self, mode: i32) -> Result<()> { 47 jni_unchecked!( 48 self.env.get_native_interface(), 49 ReleasePrimitiveArrayCritical, 50 *self.obj, 51 self.ptr.as_mut(), 52 mode 53 ); 54 Ok(()) 55 } 56 57 /// Don't copy the changes to the array on release (if it is a copy). 58 /// This has no effect if the array is not a copy. 59 /// This method is useful to change the release mode of an array originally created 60 /// with `ReleaseMode::CopyBack`. discard(&mut self)61 pub fn discard(&mut self) { 62 self.mode = ReleaseMode::NoCopyBack; 63 } 64 65 /// Indicates if the array is a copy or not is_copy(&self) -> bool66 pub fn is_copy(&self) -> bool { 67 self.is_copy 68 } 69 70 /// Returns the array size size(&self) -> Result<jsize>71 pub fn size(&self) -> Result<jsize> { 72 self.env.get_array_length(*self.obj) 73 } 74 } 75 76 impl<'a, 'b> Drop for AutoPrimitiveArray<'a, 'b> { drop(&mut self)77 fn drop(&mut self) { 78 let res = self.release_primitive_array_critical(self.mode as i32); 79 match res { 80 Ok(()) => {} 81 Err(e) => debug!("error releasing primitive array: {:#?}", e), 82 } 83 } 84 } 85 86 impl<'a> From<&'a AutoPrimitiveArray<'a, '_>> for *mut c_void { from(other: &'a AutoPrimitiveArray) -> *mut c_void87 fn from(other: &'a AutoPrimitiveArray) -> *mut c_void { 88 other.as_ptr() 89 } 90 } 91