1use jni::objects::{JObject, JObjectArray, JPrimitiveArray, JString, TypeArray};
2
3
4pub fn from_java_static<'j, T: FromJava<'j>>(env: &mut jni::JNIEnv<'j>, val: T::From) -> Result<T, jni::errors::Error> {
7 T::from_java(env, val)
8}
9
10pub trait FromJava<'j> : Sized {
12 type From : Sized;
14 fn from_java(env: &mut jni::JNIEnv<'j>, value: Self::From) -> Result<Self, jni::errors::Error>;
16}
17
18macro_rules! auto_from_java {
19 ($t: ty, $j: ty) => {
20 impl<'j> FromJava<'j> for $t {
21 type From = $j;
22
23 #[inline]
24 fn from_java(_: &mut jni::JNIEnv, value: Self::From) -> Result<Self, jni::errors::Error> {
25 Ok(value)
26 }
27 }
28 };
29}
30
31auto_from_java!(i8, jni::sys::jbyte);
32auto_from_java!(i16, jni::sys::jshort);
33auto_from_java!(i32, jni::sys::jint);
34auto_from_java!(i64, jni::sys::jlong);
35auto_from_java!(f32, jni::sys::jfloat);
36auto_from_java!(f64, jni::sys::jdouble);
37auto_from_java!(JObject<'j>, JObject<'j>);
38auto_from_java!(JString<'j>, JString<'j>);
39auto_from_java!(JObjectArray<'j>, JObjectArray<'j>);
40
41impl<'j, T: TypeArray> FromJava<'j> for JPrimitiveArray<'j, T> {
42 type From = JPrimitiveArray<'j, T>;
43
44 #[inline]
45 fn from_java(_: &mut jni::JNIEnv, value: Self::From) -> Result<Self, jni::errors::Error> {
46 Ok(value)
47 }
48}
49
50impl<'j> FromJava<'j> for char {
51 type From = jni::sys::jchar;
52
53 #[inline]
54 fn from_java(_: &mut jni::JNIEnv, value: Self::From) -> Result<Self, jni::errors::Error> {
55 char::from_u32(value.into()).ok_or_else(|| jni::errors::Error::WrongJValueType("char", "invalid u16"))
56 }
57}
58
59impl<'j> FromJava<'j> for bool {
60 type From = jni::sys::jboolean;
61
62 #[inline]
63 fn from_java(_: &mut jni::JNIEnv, value: Self::From) -> Result<Self, jni::errors::Error> {
64 Ok(value != 0)
65 }
66}
67
68impl<'j> FromJava<'j> for String {
69 type From = JString<'j>;
70
71 fn from_java(env: &mut jni::JNIEnv<'j>, value: Self::From) -> Result<Self, jni::errors::Error> {
72 if value.is_null() { return Err(jni::errors::Error::NullPtr("string can't be null")) };
73 Ok(env.get_string(&value)?.into())
74 }
75}
76
77impl<'j, T> FromJava<'j> for Option<T>
78where
79 T: FromJava<'j, From: AsRef<JObject<'j>>>,
80{
81 type From = T::From;
82
83 fn from_java(env: &mut jni::JNIEnv<'j>, value: Self::From) -> Result<Self, jni::errors::Error> {
84 if value.as_ref().is_null() { return Ok(None) };
85 Ok(Some(T::from_java(env, value)?))
86 }
87}
88
89impl<'j, T: FromJava<'j, From = JObject<'j>>> FromJava<'j> for Vec<T> {
90 type From = JObjectArray<'j>;
91
92 fn from_java(env: &mut jni::JNIEnv<'j>, value: Self::From) -> Result<Self, jni::errors::Error> {
93 let len = env.get_array_length(&value)?;
94 let mut out = Vec::new();
95 for i in 0..len {
96 let el = env.get_object_array_element(&value, i)?;
97 out.push(T::from_java(env, el)?);
98 }
99 Ok(out)
100 }
101}
102
103macro_rules! auto_from_java_primitive_array {
104 ($primitive:ty, $fn:ident) => {
105 impl<'j> FromJava<'j> for Vec<$primitive> {
106 type From = JPrimitiveArray<'j, $primitive>;
107
108 fn from_java(env: &mut jni::JNIEnv<'j>, value: Self::From) -> Result<Self, jni::errors::Error> {
109 let len = env.get_array_length(&value)?.max(0) as usize; let mut out = vec![<$primitive>::default(); len];
111 env.$fn(value, 0, &mut out)?;
112 Ok(out)
113 }
114 }
115 };
116}
117
118auto_from_java_primitive_array!(i8, get_byte_array_region);
119auto_from_java_primitive_array!(i16, get_short_array_region);
120auto_from_java_primitive_array!(i32, get_int_array_region);
121auto_from_java_primitive_array!(i64, get_long_array_region);
122auto_from_java_primitive_array!(f32, get_float_array_region);
123auto_from_java_primitive_array!(f64, get_double_array_region);
124
125impl<'j> FromJava<'j> for Vec<bool> {
126 type From = JPrimitiveArray<'j, u8>;
127
128 fn from_java(env: &mut jni::JNIEnv<'j>, value: Self::From) -> Result<Self, jni::errors::Error> {
129 let len = env.get_array_length(&value)?.max(0) as usize; let mut out = vec![<u8>::default(); len];
131 env.get_boolean_array_region(value, 0, &mut out)?;
132 Ok(out.into_iter().map(|x| x != 0).collect())
133 }
134}
135
136impl<'j> FromJava<'j> for Vec<char> {
137 type From = JPrimitiveArray<'j, u16>;
138
139 fn from_java(env: &mut jni::JNIEnv<'j>, value: Self::From) -> Result<Self, jni::errors::Error> {
140 let len = env.get_array_length(&value)?.max(0) as usize; let mut out = vec![<u16>::default(); len];
142 env.get_char_array_region(value, 0, &mut out)?;
143 Ok(
144 out
145 .into_iter()
146 .map(|x| char::from_u32(x.into()).unwrap_or_default())
147 .collect()
148 )
149 }
150}
151
152#[cfg(feature = "uuid")]
153impl<'j> FromJava<'j> for uuid::Uuid {
154 type From = JObject<'j>;
155 fn from_java(env: &mut jni::JNIEnv<'j>, uuid: Self::From) -> Result<Self, jni::errors::Error> {
156 let lsb = u64::from_ne_bytes(
157 env.call_method(&uuid, "getLeastSignificantBits", "()J", &[])?
158 .j()?
159 .to_ne_bytes()
160 );
161
162 let msb = u64::from_ne_bytes(
163 env.call_method(&uuid, "getMostSignificantBits", "()J", &[])?
164 .j()?
165 .to_ne_bytes()
166 );
167
168 Ok(uuid::Uuid::from_u64_pair(msb, lsb))
169 }
170}