jnino 0.1.1

Java Native Interface to rust Native Objects
Documentation
pub use derive_jface::JFace;
use jni::{objects::JClass, JNIEnv};
pub type Jr<T> = Result<T, Box<dyn std::error::Error>>;
pub fn unit() {}
pub fn hide<T>(_: T) {}

pub trait Throwable<T> {
  fn throw<L: FnOnce() -> T>(self, jenv: JNIEnv, or_else: L) -> T;
}
impl<T> Throwable<T> for Jr<T> {
  fn throw<L: FnOnce() -> T>(self, jenv: JNIEnv, or_else: L) -> T {
    match self {
      Ok(it) => it,
      Err(e) => {
        let _ = jenv.throw(e.to_string()).map_err(|e| log::warn!("can't throw: {}", e));
        or_else()
      }
    }
  }
}

pub trait JFace: Sized {
  fn mut_raw<'a>(jenv: &JNIEnv<'a>, jclass: JClass<'a>) -> Jr<Option<&'a mut Self>> {
    let r = jenv.get_field(jclass, "ptr", "J")?.j()? as isize;
    unsafe {
      let r: usize = std::mem::transmute(r);
      let r: *mut Self = r as _;
      if let Some(r) = r.as_mut() {
        Ok(Some(r))
      } else {
        Ok(None)
      }
    }
  }
  fn box_raw<'a>(jenv: &JNIEnv<'a>, jclass: JClass<'a>) -> Jr<Option<Box<Self>>> {
    Self::mut_raw(jenv, jclass).and_then(|it| {
      it.map(|it| unsafe {
        jenv.set_field(jclass, "ptr", "J", 0.into()).map_err(Box::new)?;
        Ok(Box::from_raw(it))
      })
      .transpose()
    })
  }
  fn jni(self) -> *mut Self {
    Box::into_raw(Box::new(self))
  }
}

pub trait JRConv<T> {
  fn jni(self) -> Jr<*mut T>;
}
impl<T: JFace, E: Into<Box<dyn std::error::Error>>> JRConv<T> for Result<T, E> {
  fn jni(self) -> Jr<*mut T> {
    self.map_err(Into::into).map(JFace::jni)
  }
}