1 use crate::{ 2 errors::*, 3 objects::{AutoLocal, JObject}, 4 JNIEnv, 5 }; 6 7 #[cfg(doc)] 8 use crate::objects::{JClass, JMethodID}; 9 10 /// Trait for things that can be looked up through the JNI via a descriptor. 11 /// This will be something like the fully-qualified class name 12 /// `java/lang/String` or a tuple containing a class descriptor, method name, 13 /// and method signature. For convenience, this is also implemented for the 14 /// concrete types themselves in addition to their descriptors. 15 /// 16 /// # Safety 17 /// 18 /// Implementations of this trait must return the correct value from the 19 /// `lookup` method. It must not, for example, return a random [`JMethodID`] or 20 /// the [`JClass`] of a class other than the one requested. Returning such an 21 /// incorrect value results in undefined behavior. This requirement also 22 /// applies to the returned value's implementation of `AsRef<T>`. 23 pub unsafe trait Desc<'local, T> { 24 /// The type that this `Desc` returns. 25 type Output: AsRef<T>; 26 27 /// Look up the concrete type from the JVM. 28 /// 29 /// Note that this method does not return exactly `T`. Instead, it returns 30 /// some type that implements `AsRef<T>`. For this reason, it is often 31 /// necessary to use turbofish syntax when calling this method: 32 /// 33 /// ```rust,no_run 34 /// # use jni::{descriptors::Desc, errors::Result, JNIEnv, objects::JClass}; 35 /// # 36 /// # fn example(env: &mut JNIEnv) -> Result<()> { 37 /// // The value returned by `lookup` is not exactly `JClass`. 38 /// let class/*: impl AsRef<JClass> */ = 39 /// Desc::<JClass>::lookup("java/lang/Object", env)?; 40 /// 41 /// // But `&JClass` can be borrowed from it. 42 /// let class: &JClass = class.as_ref(); 43 /// # Ok(()) 44 /// # } 45 /// ``` 46 /// 47 /// **Warning:** Many built-in implementations of this trait return 48 /// [`AutoLocal`] from this method. If you then call [`JObject::as_raw`] on 49 /// the returned object reference, this may result in the reference being 50 /// [deleted][JNIEnv::delete_local_ref] before it is used, causing 51 /// undefined behavior. 52 /// 53 /// For example, don't do this: 54 /// 55 /// ```rust,no_run 56 /// # use jni::{descriptors::Desc, errors::Result, JNIEnv, objects::JClass}; 57 /// # 58 /// # fn some_function<T>(ptr: *mut T) {} 59 /// # 60 /// # fn example(env: &mut JNIEnv) -> Result<()> { 61 /// // Undefined behavior: the `JClass` is dropped before the raw pointer 62 /// // is passed to `some_function`! 63 /// some_function(Desc::<JClass>::lookup("java/lang/Object", env)?.as_raw()); 64 /// # Ok(()) 65 /// # } 66 /// ``` 67 /// 68 /// Instead, do this: 69 /// 70 /// ```rust,no_run 71 /// # use jni::{descriptors::Desc, errors::Result, JNIEnv, objects::JClass}; 72 /// # 73 /// # fn some_function<T>(ptr: *mut T) {} 74 /// # 75 /// # fn example(env: &mut JNIEnv) -> Result<()> { 76 /// let class = Desc::<JClass>::lookup("java/lang/Object", env)?; 77 /// 78 /// some_function(class.as_raw()); 79 /// 80 /// drop(class); 81 /// # Ok(()) 82 /// # } 83 /// ``` 84 /// 85 /// This will still work without the call to `drop` at the end, but calling 86 /// `drop` ensures that the reference is not accidentally dropped earlier 87 /// than it should be. lookup(self, _: &mut JNIEnv<'local>) -> Result<Self::Output>88 fn lookup(self, _: &mut JNIEnv<'local>) -> Result<Self::Output>; 89 } 90 91 unsafe impl<'local, T> Desc<'local, T> for T 92 where 93 T: AsRef<T>, 94 { 95 type Output = Self; 96 lookup(self, _: &mut JNIEnv<'local>) -> Result<T>97 fn lookup(self, _: &mut JNIEnv<'local>) -> Result<T> { 98 Ok(self) 99 } 100 } 101 102 unsafe impl<'local, 't_ref, T> Desc<'local, T> for &'t_ref T 103 where 104 T: AsRef<T>, 105 { 106 type Output = Self; 107 lookup(self, _: &mut JNIEnv<'local>) -> Result<Self::Output>108 fn lookup(self, _: &mut JNIEnv<'local>) -> Result<Self::Output> { 109 Ok(self) 110 } 111 } 112 113 unsafe impl<'local, 'other_local, T> Desc<'local, T> for AutoLocal<'other_local, T> 114 where 115 T: AsRef<T> + Into<JObject<'other_local>>, 116 { 117 type Output = Self; 118 lookup(self, _: &mut JNIEnv<'local>) -> Result<Self::Output>119 fn lookup(self, _: &mut JNIEnv<'local>) -> Result<Self::Output> { 120 Ok(self) 121 } 122 } 123 124 unsafe impl<'local, 'other_local, 'obj_ref, T> Desc<'local, T> 125 for &'obj_ref AutoLocal<'other_local, T> 126 where 127 T: AsRef<T> + Into<JObject<'other_local>>, 128 { 129 type Output = Self; 130 lookup(self, _: &mut JNIEnv<'local>) -> Result<Self::Output>131 fn lookup(self, _: &mut JNIEnv<'local>) -> Result<Self::Output> { 132 Ok(self) 133 } 134 } 135