java-spaghetti 0.2.0

Glue code to accompany the java-spaghetti code generator for binding to JVM APIs from Rust
Documentation
//! Common glue code between Rust and JNI, used in autogenerated `java-spaghetti` glue code.
//!
//! See also the [Android JNI tips](https://developer.android.com/training/articles/perf-jni) documentation as well as the
//! [Java Native Interface Specification](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html).

use std::fmt;
use std::ptr::null_mut;

/// public jni-sys reexport.
pub use ::jni_sys as sys;
use sys::{jobject, jvalue};

mod refs {
    mod arg;
    mod global;
    mod local;
    mod ref_;
    mod return_;

    pub use arg::*;
    pub use global::*;
    pub use local::*;
    pub use ref_::*;
    pub use return_::*;
}

mod array;
mod as_jvalue;
mod env;
mod jni_type;
mod string_chars;
mod vm;

pub use array::*;
pub use as_jvalue::*;
pub use env::*;
pub use jni_type::JniType;
pub use refs::*;
pub use string_chars::*;
pub use vm::*;

/// Error returned on failed `.cast()`.`
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct CastError;

impl std::error::Error for CastError {}
impl fmt::Display for CastError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("Cast failed")
    }
}

/// A marker type indicating this is a valid exception type that all exceptions thrown by java should be compatible with
pub trait ThrowableType: ReferenceType {}

/// You should generally not be interacting with this type directly, but it must be public for codegen.
/// This is hideously unsafe to implement:
///
/// 1) You assert the type is a #[repr(transparent)] wrapper around ObjectAndEnv.
/// 2) You assert the type cannot exist with a dangling object or env.
///     2.1) Do not implement Copy or Clone.
///     2.2) Do not allow value access.
///     2.3) Do not allow &mut T access.
///     2.4) Only allow &T access, which cannot be moved from.
#[doc(hidden)]
pub unsafe trait ReferenceType: JniType + 'static {}

/// Marker trait indicating `Self` can be assigned to `T`.
///
/// This is true when `T` is a superclass or superinterface of `Self`.
pub unsafe trait AssignableTo<T: ReferenceType>: ReferenceType {}

/// A type is always assignable to itself.
unsafe impl<T: ReferenceType> AssignableTo<T> for T {}

#[repr(C)] // Given how frequently we transmute to/from this, we'd better keep a consistent layout.
#[doc(hidden)] // You should generally not be interacting with this type directly, but it must be public for codegen.
#[derive(Copy, Clone)]
pub struct ObjectAndEnv {
    pub object: jni_sys::jobject,
    pub env: *mut jni_sys::JNIEnv,
}

pub unsafe trait AsArg<T>: Sized {
    fn as_arg(&self) -> jobject;
    fn as_arg_jvalue(&self) -> jvalue {
        jvalue { l: self.as_arg() }
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Null;

unsafe impl<T: ReferenceType, U: AsArg<T>> AsArg<T> for &U {
    fn as_arg(&self) -> jobject {
        U::as_arg(self)
    }
}

unsafe impl<T: ReferenceType, U: AsArg<T>> AsArg<T> for &mut U {
    fn as_arg(&self) -> jobject {
        U::as_arg(self)
    }
}

unsafe impl<T: ReferenceType> AsArg<T> for Null {
    fn as_arg(&self) -> jobject {
        null_mut()
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Ref<'_, U> {
    fn as_arg(&self) -> jobject {
        self.as_raw()
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Option<Ref<'_, U>> {
    fn as_arg(&self) -> jobject {
        self.map(|r| r.as_raw()).unwrap_or(null_mut())
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Option<&Ref<'_, U>> {
    fn as_arg(&self) -> jobject {
        self.map(|r| r.as_raw()).unwrap_or(null_mut())
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Local<'_, U> {
    fn as_arg(&self) -> jobject {
        self.as_raw()
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Option<Local<'_, U>> {
    fn as_arg(&self) -> jobject {
        self.as_ref().map(|r| r.as_raw()).unwrap_or(null_mut())
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Option<&Local<'_, U>> {
    fn as_arg(&self) -> jobject {
        self.map(|r| r.as_raw()).unwrap_or(null_mut())
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Global<U> {
    fn as_arg(&self) -> jobject {
        self.as_raw()
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Option<Global<U>> {
    fn as_arg(&self) -> jobject {
        self.as_ref().map(|r| r.as_raw()).unwrap_or(null_mut())
    }
}

unsafe impl<T: ReferenceType, U: AssignableTo<T>> AsArg<T> for Option<&Global<U>> {
    fn as_arg(&self) -> jobject {
        self.map(|r| r.as_raw()).unwrap_or(null_mut())
    }
}