1 use std::convert::TryFrom;
2 use std::fmt::Debug;
3 
4 use log::trace;
5 
6 use crate::{errors::*, objects::JObject, signature::Primitive, sys::*};
7 
8 /// Rusty version of the JNI C `jvalue` enum. Used in Java method call arguments
9 /// and returns.
10 ///
11 /// `JValueGen` is a generic type, meant to represent both owned and borrowed
12 /// JNI values. The type parameter `O` refers to what kind of object reference
13 /// the `JValueGen` can hold, which is either:
14 ///
15 /// * an owned [`JObject`], used for values returned from a Java method call,
16 ///   or
17 /// * a borrowed `&JObject`, used for parameters passed to a Java method call.
18 ///
19 /// These two cases are represented by the type aliases [`JValueOwned`] and
20 /// [`JValue`], respectively.
21 #[allow(missing_docs)]
22 #[derive(Clone, Copy, Debug)]
23 pub enum JValueGen<O> {
24     Object(O),
25     Byte(jbyte),
26     Char(jchar),
27     Short(jshort),
28     Int(jint),
29     Long(jlong),
30     Bool(jboolean),
31     Float(jfloat),
32     Double(jdouble),
33     Void,
34 }
35 
36 /// An <dfn>owned</dfn> [`JValueGen`].
37 ///
38 /// This type is used for values returned from Java method calls. If the Java
39 /// method returns an object reference, it will take the form of an owned
40 /// [`JObject`].
41 pub type JValueOwned<'local> = JValueGen<JObject<'local>>;
42 
43 /// A <dfn>reference</dfn> [`JValueGen`].
44 ///
45 /// This type is used for parameters passed to Java method calls. If the Java
46 /// method is to be passed an object reference, it takes the form of a borrowed
47 /// <code>&[JObject]</code>.
48 pub type JValue<'local, 'obj_ref> = JValueGen<&'obj_ref JObject<'local>>;
49 
50 impl<O> JValueGen<O> {
51     /// Convert the enum to its jni-compatible equivalent.
as_jni<'local>(&self) -> jvalue where O: AsRef<JObject<'local>> + Debug,52     pub fn as_jni<'local>(&self) -> jvalue
53     where
54         O: AsRef<JObject<'local>> + Debug,
55     {
56         let val: jvalue = match self {
57             JValueGen::Object(obj) => jvalue {
58                 l: obj.as_ref().as_raw(),
59             },
60             JValueGen::Byte(byte) => jvalue { b: *byte },
61             JValueGen::Char(char) => jvalue { c: *char },
62             JValueGen::Short(short) => jvalue { s: *short },
63             JValueGen::Int(int) => jvalue { i: *int },
64             JValueGen::Long(long) => jvalue { j: *long },
65             JValueGen::Bool(boolean) => jvalue { b: *boolean as i8 },
66             JValueGen::Float(float) => jvalue { f: *float },
67             JValueGen::Double(double) => jvalue { d: *double },
68             JValueGen::Void => jvalue {
69                 l: ::std::ptr::null_mut(),
70             },
71         };
72         trace!("converted {:?} to jvalue {:?}", self, unsafe {
73             ::std::mem::transmute::<_, u64>(val)
74         });
75         val
76     }
77 
78     /// Convert the enum to its jni-compatible equivalent.
79     #[deprecated = "Use `as_jni` instead."]
to_jni<'local>(self) -> jvalue where O: AsRef<JObject<'local>> + Debug,80     pub fn to_jni<'local>(self) -> jvalue
81     where
82         O: AsRef<JObject<'local>> + Debug,
83     {
84         self.as_jni()
85     }
86 
87     /// Get the type name for the enum variant.
type_name(&self) -> &'static str88     pub fn type_name(&self) -> &'static str {
89         match *self {
90             JValueGen::Void => "void",
91             JValueGen::Object(_) => "object",
92             JValueGen::Byte(_) => "byte",
93             JValueGen::Char(_) => "char",
94             JValueGen::Short(_) => "short",
95             JValueGen::Int(_) => "int",
96             JValueGen::Long(_) => "long",
97             JValueGen::Bool(_) => "bool",
98             JValueGen::Float(_) => "float",
99             JValueGen::Double(_) => "double",
100         }
101     }
102 
103     /// Get the primitive type for the enum variant. If it's not a primitive
104     /// (i.e. an Object), returns None.
primitive_type(&self) -> Option<Primitive>105     pub fn primitive_type(&self) -> Option<Primitive> {
106         Some(match *self {
107             JValueGen::Object(_) => return None,
108             JValueGen::Void => Primitive::Void,
109             JValueGen::Byte(_) => Primitive::Byte,
110             JValueGen::Char(_) => Primitive::Char,
111             JValueGen::Short(_) => Primitive::Short,
112             JValueGen::Int(_) => Primitive::Int,
113             JValueGen::Long(_) => Primitive::Long,
114             JValueGen::Bool(_) => Primitive::Boolean,
115             JValueGen::Float(_) => Primitive::Float,
116             JValueGen::Double(_) => Primitive::Double,
117         })
118     }
119 
120     /// Try to unwrap to an Object.
l(self) -> Result<O>121     pub fn l(self) -> Result<O> {
122         match self {
123             JValueGen::Object(obj) => Ok(obj),
124             _ => Err(Error::WrongJValueType("object", self.type_name())),
125         }
126     }
127 
128     /// Try to unwrap to a boolean.
z(self) -> Result<bool>129     pub fn z(self) -> Result<bool> {
130         match self {
131             JValueGen::Bool(b) => Ok(b == JNI_TRUE),
132             _ => Err(Error::WrongJValueType("bool", self.type_name())),
133         }
134     }
135 
136     /// Try to unwrap to a byte.
b(self) -> Result<jbyte>137     pub fn b(self) -> Result<jbyte> {
138         match self {
139             JValueGen::Byte(b) => Ok(b),
140             _ => Err(Error::WrongJValueType("jbyte", self.type_name())),
141         }
142     }
143 
144     /// Try to unwrap to a char.
c(self) -> Result<jchar>145     pub fn c(self) -> Result<jchar> {
146         match self {
147             JValueGen::Char(b) => Ok(b),
148             _ => Err(Error::WrongJValueType("jchar", self.type_name())),
149         }
150     }
151 
152     /// Try to unwrap to a double.
d(self) -> Result<jdouble>153     pub fn d(self) -> Result<jdouble> {
154         match self {
155             JValueGen::Double(b) => Ok(b),
156             _ => Err(Error::WrongJValueType("jdouble", self.type_name())),
157         }
158     }
159 
160     /// Try to unwrap to a float.
f(self) -> Result<jfloat>161     pub fn f(self) -> Result<jfloat> {
162         match self {
163             JValueGen::Float(b) => Ok(b),
164             _ => Err(Error::WrongJValueType("jfloat", self.type_name())),
165         }
166     }
167 
168     /// Try to unwrap to an int.
i(self) -> Result<jint>169     pub fn i(self) -> Result<jint> {
170         match self {
171             JValueGen::Int(b) => Ok(b),
172             _ => Err(Error::WrongJValueType("jint", self.type_name())),
173         }
174     }
175 
176     /// Try to unwrap to a long.
j(self) -> Result<jlong>177     pub fn j(self) -> Result<jlong> {
178         match self {
179             JValueGen::Long(b) => Ok(b),
180             _ => Err(Error::WrongJValueType("jlong", self.type_name())),
181         }
182     }
183 
184     /// Try to unwrap to a short.
s(self) -> Result<jshort>185     pub fn s(self) -> Result<jshort> {
186         match self {
187             JValueGen::Short(b) => Ok(b),
188             _ => Err(Error::WrongJValueType("jshort", self.type_name())),
189         }
190     }
191 
192     /// Try to unwrap to a void.
v(self) -> Result<()>193     pub fn v(self) -> Result<()> {
194         match self {
195             JValueGen::Void => Ok(()),
196             _ => Err(Error::WrongJValueType("void", self.type_name())),
197         }
198     }
199 
200     /// Copies or borrows the value in this `JValue`.
201     ///
202     /// If the value is a primitive type, it is copied. If the value is an
203     /// object reference, it is borrowed.
borrow(&self) -> JValueGen<&O>204     pub fn borrow(&self) -> JValueGen<&O> {
205         match self {
206             JValueGen::Object(o) => JValueGen::Object(o),
207             JValueGen::Byte(v) => JValueGen::Byte(*v),
208             JValueGen::Char(v) => JValueGen::Char(*v),
209             JValueGen::Short(v) => JValueGen::Short(*v),
210             JValueGen::Int(v) => JValueGen::Int(*v),
211             JValueGen::Long(v) => JValueGen::Long(*v),
212             JValueGen::Bool(v) => JValueGen::Bool(*v),
213             JValueGen::Float(v) => JValueGen::Float(*v),
214             JValueGen::Double(v) => JValueGen::Double(*v),
215             JValueGen::Void => JValueGen::Void,
216         }
217     }
218 }
219 
220 impl<'obj_ref, O> From<&'obj_ref JValueGen<O>> for JValueGen<&'obj_ref O> {
from(other: &'obj_ref JValueGen<O>) -> Self221     fn from(other: &'obj_ref JValueGen<O>) -> Self {
222         other.borrow()
223     }
224 }
225 
226 impl<'local, T: Into<JObject<'local>>> From<T> for JValueOwned<'local> {
from(other: T) -> Self227     fn from(other: T) -> Self {
228         Self::Object(other.into())
229     }
230 }
231 
232 impl<'local: 'obj_ref, 'obj_ref, T: AsRef<JObject<'local>>> From<&'obj_ref T>
233     for JValue<'local, 'obj_ref>
234 {
from(other: &'obj_ref T) -> Self235     fn from(other: &'obj_ref T) -> Self {
236         Self::Object(other.as_ref())
237     }
238 }
239 
240 impl<'local> TryFrom<JValueOwned<'local>> for JObject<'local> {
241     type Error = Error;
242 
try_from(value: JValueOwned<'local>) -> Result<Self>243     fn try_from(value: JValueOwned<'local>) -> Result<Self> {
244         match value {
245             JValueGen::Object(o) => Ok(o),
246             _ => Err(Error::WrongJValueType("object", value.type_name())),
247         }
248     }
249 }
250 
251 impl<O> From<bool> for JValueGen<O> {
from(other: bool) -> Self252     fn from(other: bool) -> Self {
253         JValueGen::Bool(if other { JNI_TRUE } else { JNI_FALSE })
254     }
255 }
256 
257 // jbool
258 impl<O> From<jboolean> for JValueGen<O> {
from(other: jboolean) -> Self259     fn from(other: jboolean) -> Self {
260         JValueGen::Bool(other)
261     }
262 }
263 
264 impl<O> TryFrom<JValueGen<O>> for jboolean {
265     type Error = Error;
266 
try_from(value: JValueGen<O>) -> Result<Self>267     fn try_from(value: JValueGen<O>) -> Result<Self> {
268         match value {
269             JValueGen::Bool(b) => Ok(b),
270             _ => Err(Error::WrongJValueType("bool", value.type_name())),
271         }
272     }
273 }
274 
275 // jchar
276 impl<O> From<jchar> for JValueGen<O> {
from(other: jchar) -> Self277     fn from(other: jchar) -> Self {
278         JValueGen::Char(other)
279     }
280 }
281 
282 impl<O> TryFrom<JValueGen<O>> for jchar {
283     type Error = Error;
284 
try_from(value: JValueGen<O>) -> Result<Self>285     fn try_from(value: JValueGen<O>) -> Result<Self> {
286         match value {
287             JValueGen::Char(c) => Ok(c),
288             _ => Err(Error::WrongJValueType("char", value.type_name())),
289         }
290     }
291 }
292 
293 // jshort
294 impl<O> From<jshort> for JValueGen<O> {
from(other: jshort) -> Self295     fn from(other: jshort) -> Self {
296         JValueGen::Short(other)
297     }
298 }
299 
300 impl<O> TryFrom<JValueGen<O>> for jshort {
301     type Error = Error;
302 
try_from(value: JValueGen<O>) -> Result<Self>303     fn try_from(value: JValueGen<O>) -> Result<Self> {
304         match value {
305             JValueGen::Short(s) => Ok(s),
306             _ => Err(Error::WrongJValueType("short", value.type_name())),
307         }
308     }
309 }
310 
311 // jfloat
312 impl<O> From<jfloat> for JValueGen<O> {
from(other: jfloat) -> Self313     fn from(other: jfloat) -> Self {
314         JValueGen::Float(other)
315     }
316 }
317 
318 impl<O> TryFrom<JValueGen<O>> for jfloat {
319     type Error = Error;
320 
try_from(value: JValueGen<O>) -> Result<Self>321     fn try_from(value: JValueGen<O>) -> Result<Self> {
322         match value {
323             JValueGen::Float(f) => Ok(f),
324             _ => Err(Error::WrongJValueType("float", value.type_name())),
325         }
326     }
327 }
328 
329 // jdouble
330 impl<O> From<jdouble> for JValueGen<O> {
from(other: jdouble) -> Self331     fn from(other: jdouble) -> Self {
332         JValueGen::Double(other)
333     }
334 }
335 
336 impl<O> TryFrom<JValueGen<O>> for jdouble {
337     type Error = Error;
338 
try_from(value: JValueGen<O>) -> Result<Self>339     fn try_from(value: JValueGen<O>) -> Result<Self> {
340         match value {
341             JValueGen::Double(d) => Ok(d),
342             _ => Err(Error::WrongJValueType("double", value.type_name())),
343         }
344     }
345 }
346 
347 // jint
348 impl<O> From<jint> for JValueGen<O> {
from(other: jint) -> Self349     fn from(other: jint) -> Self {
350         JValueGen::Int(other)
351     }
352 }
353 
354 impl<O> TryFrom<JValueGen<O>> for jint {
355     type Error = Error;
356 
try_from(value: JValueGen<O>) -> Result<Self>357     fn try_from(value: JValueGen<O>) -> Result<Self> {
358         match value {
359             JValueGen::Int(i) => Ok(i),
360             _ => Err(Error::WrongJValueType("int", value.type_name())),
361         }
362     }
363 }
364 
365 // jlong
366 impl<O> From<jlong> for JValueGen<O> {
from(other: jlong) -> Self367     fn from(other: jlong) -> Self {
368         JValueGen::Long(other)
369     }
370 }
371 
372 impl<O> TryFrom<JValueGen<O>> for jlong {
373     type Error = Error;
374 
try_from(value: JValueGen<O>) -> Result<Self>375     fn try_from(value: JValueGen<O>) -> Result<Self> {
376         match value {
377             JValueGen::Long(l) => Ok(l),
378             _ => Err(Error::WrongJValueType("long", value.type_name())),
379         }
380     }
381 }
382 
383 // jbyte
384 impl<O> From<jbyte> for JValueGen<O> {
from(other: jbyte) -> Self385     fn from(other: jbyte) -> Self {
386         JValueGen::Byte(other)
387     }
388 }
389 
390 impl<O> TryFrom<JValueGen<O>> for jbyte {
391     type Error = Error;
392 
try_from(value: JValueGen<O>) -> Result<Self>393     fn try_from(value: JValueGen<O>) -> Result<Self> {
394         match value {
395             JValueGen::Byte(b) => Ok(b),
396             _ => Err(Error::WrongJValueType("byte", value.type_name())),
397         }
398     }
399 }
400 
401 // jvoid
402 impl<O> From<()> for JValueGen<O> {
from(_: ()) -> Self403     fn from(_: ()) -> Self {
404         JValueGen::Void
405     }
406 }
407 
408 impl<O> TryFrom<JValueGen<O>> for () {
409     type Error = Error;
410 
try_from(value: JValueGen<O>) -> Result<Self>411     fn try_from(value: JValueGen<O>) -> Result<Self> {
412         match value {
413             JValueGen::Void => Ok(()),
414             _ => Err(Error::WrongJValueType("void", value.type_name())),
415         }
416     }
417 }
418