Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

View File

@@ -0,0 +1,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) })
}
}

View File

@@ -0,0 +1,134 @@
use crate::{
errors::*,
objects::{AutoLocal, JObject},
JNIEnv,
};
#[cfg(doc)]
use crate::objects::{JClass, JMethodID};
/// Trait for things that can be looked up through the JNI via a descriptor.
/// This will be something like the fully-qualified class name
/// `java/lang/String` or a tuple containing a class descriptor, method name,
/// and method signature. For convenience, this is also implemented for the
/// concrete types themselves in addition to their descriptors.
///
/// # Safety
///
/// Implementations of this trait must return the correct value from the
/// `lookup` method. It must not, for example, return a random [`JMethodID`] or
/// the [`JClass`] of a class other than the one requested. Returning such an
/// incorrect value results in undefined behavior. This requirement also
/// applies to the returned value's implementation of `AsRef<T>`.
pub unsafe trait Desc<'local, T> {
/// The type that this `Desc` returns.
type Output: AsRef<T>;
/// Look up the concrete type from the JVM.
///
/// Note that this method does not return exactly `T`. Instead, it returns
/// some type that implements `AsRef<T>`. For this reason, it is often
/// necessary to use turbofish syntax when calling this method:
///
/// ```rust,no_run
/// # use jni::{descriptors::Desc, errors::Result, JNIEnv, objects::JClass};
/// #
/// # fn example(env: &mut JNIEnv) -> Result<()> {
/// // The value returned by `lookup` is not exactly `JClass`.
/// let class/*: impl AsRef<JClass> */ =
/// Desc::<JClass>::lookup("java/lang/Object", env)?;
///
/// // But `&JClass` can be borrowed from it.
/// let class: &JClass = class.as_ref();
/// # Ok(())
/// # }
/// ```
///
/// **Warning:** Many built-in implementations of this trait return
/// [`AutoLocal`] from this method. If you then call [`JObject::as_raw`] on
/// the returned object reference, this may result in the reference being
/// [deleted][JNIEnv::delete_local_ref] before it is used, causing
/// undefined behavior.
///
/// For example, don't do this:
///
/// ```rust,no_run
/// # use jni::{descriptors::Desc, errors::Result, JNIEnv, objects::JClass};
/// #
/// # fn some_function<T>(ptr: *mut T) {}
/// #
/// # fn example(env: &mut JNIEnv) -> Result<()> {
/// // Undefined behavior: the `JClass` is dropped before the raw pointer
/// // is passed to `some_function`!
/// some_function(Desc::<JClass>::lookup("java/lang/Object", env)?.as_raw());
/// # Ok(())
/// # }
/// ```
///
/// Instead, do this:
///
/// ```rust,no_run
/// # use jni::{descriptors::Desc, errors::Result, JNIEnv, objects::JClass};
/// #
/// # fn some_function<T>(ptr: *mut T) {}
/// #
/// # fn example(env: &mut JNIEnv) -> Result<()> {
/// let class = Desc::<JClass>::lookup("java/lang/Object", env)?;
///
/// some_function(class.as_raw());
///
/// drop(class);
/// # Ok(())
/// # }
/// ```
///
/// This will still work without the call to `drop` at the end, but calling
/// `drop` ensures that the reference is not accidentally dropped earlier
/// than it should be.
fn lookup(self, _: &mut JNIEnv<'local>) -> Result<Self::Output>;
}
unsafe impl<'local, T> Desc<'local, T> for T
where
T: AsRef<T>,
{
type Output = Self;
fn lookup(self, _: &mut JNIEnv<'local>) -> Result<T> {
Ok(self)
}
}
unsafe impl<'local, 't_ref, T> Desc<'local, T> for &'t_ref T
where
T: AsRef<T>,
{
type Output = Self;
fn lookup(self, _: &mut JNIEnv<'local>) -> Result<Self::Output> {
Ok(self)
}
}
unsafe impl<'local, 'other_local, T> Desc<'local, T> for AutoLocal<'other_local, T>
where
T: AsRef<T> + Into<JObject<'other_local>>,
{
type Output = Self;
fn lookup(self, _: &mut JNIEnv<'local>) -> Result<Self::Output> {
Ok(self)
}
}
unsafe impl<'local, 'other_local, 'obj_ref, T> Desc<'local, T>
for &'obj_ref AutoLocal<'other_local, T>
where
T: AsRef<T> + Into<JObject<'other_local>>,
{
type Output = Self;
fn lookup(self, _: &mut JNIEnv<'local>) -> Result<Self::Output> {
Ok(self)
}
}

View File

@@ -0,0 +1,57 @@
use crate::{
descriptors::Desc,
errors::*,
objects::{AutoLocal, JClass, JObject, JThrowable, JValue},
strings::JNIString,
JNIEnv,
};
const DEFAULT_EXCEPTION_CLASS: &str = "java/lang/RuntimeException";
unsafe impl<'local, 'other_local, C, M> Desc<'local, JThrowable<'local>> for (C, M)
where
C: Desc<'local, JClass<'other_local>>,
M: Into<JNIString>,
{
type Output = AutoLocal<'local, JThrowable<'local>>;
fn lookup(self, env: &mut JNIEnv<'local>) -> Result<Self::Output> {
let jmsg: AutoLocal<JObject> = env.auto_local(env.new_string(self.1)?.into());
let obj: JThrowable = env
.new_object(self.0, "(Ljava/lang/String;)V", &[JValue::from(&jmsg)])?
.into();
Ok(env.auto_local(obj))
}
}
unsafe impl<'local> Desc<'local, JThrowable<'local>> for Exception {
type Output = AutoLocal<'local, JThrowable<'local>>;
fn lookup(self, env: &mut JNIEnv<'local>) -> Result<Self::Output> {
Desc::<JThrowable>::lookup((self.class, self.msg), env)
}
}
unsafe impl<'local, 'str_ref> Desc<'local, JThrowable<'local>> for &'str_ref str {
type Output = AutoLocal<'local, JThrowable<'local>>;
fn lookup(self, env: &mut JNIEnv<'local>) -> Result<Self::Output> {
Desc::<JThrowable>::lookup((DEFAULT_EXCEPTION_CLASS, self), env)
}
}
unsafe impl<'local> Desc<'local, JThrowable<'local>> for String {
type Output = AutoLocal<'local, JThrowable<'local>>;
fn lookup(self, env: &mut JNIEnv<'local>) -> Result<Self::Output> {
Desc::<JThrowable>::lookup((DEFAULT_EXCEPTION_CLASS, self), env)
}
}
unsafe impl<'local> Desc<'local, JThrowable<'local>> for JNIString {
type Output = AutoLocal<'local, JThrowable<'local>>;
fn lookup(self, env: &mut JNIEnv<'local>) -> Result<Self::Output> {
Desc::<JThrowable>::lookup((DEFAULT_EXCEPTION_CLASS, self), env)
}
}

View File

@@ -0,0 +1,33 @@
use crate::{
descriptors::Desc,
errors::*,
objects::{JClass, JFieldID, JStaticFieldID},
strings::JNIString,
JNIEnv,
};
unsafe impl<'local, 'other_local, T, U, V> Desc<'local, JFieldID> for (T, U, V)
where
T: Desc<'local, JClass<'other_local>>,
U: Into<JNIString>,
V: Into<JNIString>,
{
type Output = JFieldID;
fn lookup(self, env: &mut JNIEnv<'local>) -> Result<Self::Output> {
env.get_field_id(self.0, self.1, self.2)
}
}
unsafe impl<'local, 'other_local, T, U, V> Desc<'local, JStaticFieldID> for (T, U, V)
where
T: Desc<'local, JClass<'other_local>>,
U: Into<JNIString>,
V: Into<JNIString>,
{
type Output = JStaticFieldID;
fn lookup(self, env: &mut JNIEnv<'local>) -> Result<Self::Output> {
env.get_static_field_id(self.0, self.1, self.2)
}
}

View File

@@ -0,0 +1,45 @@
use crate::{
descriptors::Desc,
errors::*,
objects::{JClass, JMethodID, JStaticMethodID},
strings::JNIString,
JNIEnv,
};
unsafe impl<'local, 'other_local, T, U, V> Desc<'local, JMethodID> for (T, U, V)
where
T: Desc<'local, JClass<'other_local>>,
U: Into<JNIString>,
V: Into<JNIString>,
{
type Output = JMethodID;
fn lookup(self, env: &mut JNIEnv<'local>) -> Result<Self::Output> {
env.get_method_id(self.0, self.1, self.2)
}
}
unsafe impl<'local, 'other_local, T, Signature> Desc<'local, JMethodID> for (T, Signature)
where
T: Desc<'local, JClass<'other_local>>,
Signature: Into<JNIString>,
{
type Output = JMethodID;
fn lookup(self, env: &mut JNIEnv<'local>) -> Result<Self::Output> {
Desc::<JMethodID>::lookup((self.0, "<init>", self.1), env)
}
}
unsafe impl<'local, 'other_local, T, U, V> Desc<'local, JStaticMethodID> for (T, U, V)
where
T: Desc<'local, JClass<'other_local>>,
U: Into<JNIString>,
V: Into<JNIString>,
{
type Output = JStaticMethodID;
fn lookup(self, env: &mut JNIEnv<'local>) -> Result<Self::Output> {
env.get_static_method_id(self.0, self.1, self.2)
}
}

View File

@@ -0,0 +1,14 @@
mod desc;
pub use self::desc::*;
mod class_desc;
pub use self::class_desc::*;
mod method_desc;
pub use self::method_desc::*;
mod field_desc;
pub use self::field_desc::*;
mod exception_desc;
pub use self::exception_desc::*;