1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
use crate::{
    descriptors::Desc,
    errors::*,
    objects::{AutoLocal, GlobalRef, JClass, JObject},
    strings::JNIString,
    JNIEnv,
};

unsafe impl<'local, T> Desc<'local, JClass<'local>> for T
where
    T: Into<JNIString>,
{
    type Output = AutoLocal<'local, JClass<'local>>;

    fn lookup(self, env: &mut JNIEnv<'local>) -> Result<Self::Output> {
        Ok(AutoLocal::new(env.find_class(self)?, env))
    }
}

// Note: We don't implement `Desc<JClass>` for `&JObject` as a transmute like for `GlobalRef`
//
// Considering that the APIs that return a class return a `JClass` it shouldn't
// usually be necessary unless the `JClass` got type erased (like with GlobalRef)
//
// Implementing `Desc<JClass>` for `&JObject` as a simple cast would also make
// it a lot easier to mistakenly pass an object instance in places where a class
// is required.

/// This conversion assumes that the `GlobalRef` is a pointer to a class object.

// TODO: Generify `GlobalRef` and get rid of this `impl`. The transmute is
// sound-ish at the moment (`JClass` is currently `repr(transparent)`
// around `JObject`), but that may change in the future. Moreover, this
// doesn't check if the global reference actually refers to a
// `java.lang.Class` object.
unsafe impl<'local, 'obj_ref> Desc<'local, JClass<'static>> for &'obj_ref GlobalRef {
    type Output = &'obj_ref JClass<'static>;

    fn lookup(self, _: &mut JNIEnv<'local>) -> Result<Self::Output> {
        let obj: &JObject<'static> = self.as_ref();
        Ok(unsafe { std::mem::transmute(obj) })
    }
}