• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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