• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::convert::TryFrom;
2 use std::mem::transmute;
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 #[allow(missing_docs)]
11 #[derive(Clone, Copy, Debug)]
12 pub enum JValue<'a> {
13     Object(JObject<'a>),
14     Byte(jbyte),
15     Char(jchar),
16     Short(jshort),
17     Int(jint),
18     Long(jlong),
19     Bool(jboolean),
20     Float(jfloat),
21     Double(jdouble),
22     Void,
23 }
24 
25 impl<'a> From<JValue<'a>> for jvalue {
from(other: JValue) -> jvalue26     fn from(other: JValue) -> jvalue {
27         other.to_jni()
28     }
29 }
30 
31 impl<'a> JValue<'a> {
32     /// Convert the enum to its jni-compatible equivalent.
to_jni(self) -> jvalue33     pub fn to_jni(self) -> jvalue {
34         let val: jvalue = match self {
35             JValue::Object(obj) => jvalue {
36                 l: unsafe { transmute(obj) },
37             },
38             JValue::Byte(byte) => jvalue { b: byte },
39             JValue::Char(char) => jvalue { c: char },
40             JValue::Short(short) => jvalue { s: short },
41             JValue::Int(int) => jvalue { i: int },
42             JValue::Long(long) => jvalue { j: long },
43             JValue::Bool(boolean) => jvalue { b: boolean as i8 },
44             JValue::Float(float) => jvalue { f: float },
45             JValue::Double(double) => jvalue { d: double },
46             JValue::Void => jvalue {
47                 l: ::std::ptr::null_mut(),
48             },
49         };
50         trace!("converted {:?} to jvalue {:?}", self, unsafe {
51             ::std::mem::transmute::<_, u64>(val)
52         });
53         val
54     }
55 
56     /// Get the type name for the enum variant.
type_name(&self) -> &'static str57     pub fn type_name(&self) -> &'static str {
58         match *self {
59             JValue::Void => "void",
60             JValue::Object(_) => "object",
61             JValue::Byte(_) => "byte",
62             JValue::Char(_) => "char",
63             JValue::Short(_) => "short",
64             JValue::Int(_) => "int",
65             JValue::Long(_) => "long",
66             JValue::Bool(_) => "bool",
67             JValue::Float(_) => "float",
68             JValue::Double(_) => "double",
69         }
70     }
71 
72     /// Get the primitive type for the enum variant. If it's not a primitive
73     /// (i.e. an Object), returns None.
primitive_type(&self) -> Option<Primitive>74     pub fn primitive_type(&self) -> Option<Primitive> {
75         Some(match *self {
76             JValue::Object(_) => return None,
77             JValue::Void => Primitive::Void,
78             JValue::Byte(_) => Primitive::Byte,
79             JValue::Char(_) => Primitive::Char,
80             JValue::Short(_) => Primitive::Short,
81             JValue::Int(_) => Primitive::Int,
82             JValue::Long(_) => Primitive::Long,
83             JValue::Bool(_) => Primitive::Boolean,
84             JValue::Float(_) => Primitive::Float,
85             JValue::Double(_) => Primitive::Double,
86         })
87     }
88 
89     /// Try to unwrap to an Object.
l(self) -> Result<JObject<'a>>90     pub fn l(self) -> Result<JObject<'a>> {
91         match self {
92             JValue::Object(obj) => Ok(obj),
93             _ => Err(Error::WrongJValueType("object", self.type_name())),
94         }
95     }
96 
97     /// Try to unwrap to a boolean.
z(self) -> Result<bool>98     pub fn z(self) -> Result<bool> {
99         match self {
100             JValue::Bool(b) => Ok(b == JNI_TRUE),
101             _ => Err(Error::WrongJValueType("bool", self.type_name())),
102         }
103     }
104 
105     /// Try to unwrap to a byte.
b(self) -> Result<jbyte>106     pub fn b(self) -> Result<jbyte> {
107         match self {
108             JValue::Byte(b) => Ok(b),
109             _ => Err(Error::WrongJValueType("jbyte", self.type_name())),
110         }
111     }
112 
113     /// Try to unwrap to a char.
c(self) -> Result<jchar>114     pub fn c(self) -> Result<jchar> {
115         match self {
116             JValue::Char(b) => Ok(b),
117             _ => Err(Error::WrongJValueType("jchar", self.type_name())),
118         }
119     }
120 
121     /// Try to unwrap to a double.
d(self) -> Result<jdouble>122     pub fn d(self) -> Result<jdouble> {
123         match self {
124             JValue::Double(b) => Ok(b),
125             _ => Err(Error::WrongJValueType("jdouble", self.type_name())),
126         }
127     }
128 
129     /// Try to unwrap to a float.
f(self) -> Result<jfloat>130     pub fn f(self) -> Result<jfloat> {
131         match self {
132             JValue::Float(b) => Ok(b),
133             _ => Err(Error::WrongJValueType("jfloat", self.type_name())),
134         }
135     }
136 
137     /// Try to unwrap to an int.
i(self) -> Result<jint>138     pub fn i(self) -> Result<jint> {
139         match self {
140             JValue::Int(b) => Ok(b),
141             _ => Err(Error::WrongJValueType("jint", self.type_name())),
142         }
143     }
144 
145     /// Try to unwrap to a long.
j(self) -> Result<jlong>146     pub fn j(self) -> Result<jlong> {
147         match self {
148             JValue::Long(b) => Ok(b),
149             _ => Err(Error::WrongJValueType("jlong", self.type_name())),
150         }
151     }
152 
153     /// Try to unwrap to a short.
s(self) -> Result<jshort>154     pub fn s(self) -> Result<jshort> {
155         match self {
156             JValue::Short(b) => Ok(b),
157             _ => Err(Error::WrongJValueType("jshort", self.type_name())),
158         }
159     }
160 
161     /// Try to unwrap to a void.
v(self) -> Result<()>162     pub fn v(self) -> Result<()> {
163         match self {
164             JValue::Void => Ok(()),
165             _ => Err(Error::WrongJValueType("void", self.type_name())),
166         }
167     }
168 }
169 
170 impl<'a, T: Into<JObject<'a>>> From<T> for JValue<'a> {
from(other: T) -> Self171     fn from(other: T) -> Self {
172         JValue::Object(other.into())
173     }
174 }
175 
176 impl<'a> TryFrom<JValue<'a>> for JObject<'a> {
177     type Error = Error;
178 
try_from(value: JValue<'a>) -> Result<Self>179     fn try_from(value: JValue<'a>) -> Result<Self> {
180         match value {
181             JValue::Object(o) => Ok(o),
182             _ => Err(Error::WrongJValueType("object", value.type_name())),
183         }
184     }
185 }
186 
187 impl<'a> From<bool> for JValue<'a> {
from(other: bool) -> Self188     fn from(other: bool) -> Self {
189         JValue::Bool(if other { JNI_TRUE } else { JNI_FALSE })
190     }
191 }
192 
193 // jbool
194 impl<'a> From<jboolean> for JValue<'a> {
from(other: jboolean) -> Self195     fn from(other: jboolean) -> Self {
196         JValue::Bool(other)
197     }
198 }
199 
200 impl<'a> TryFrom<JValue<'a>> for jboolean {
201     type Error = Error;
202 
try_from(value: JValue<'a>) -> Result<Self>203     fn try_from(value: JValue<'a>) -> Result<Self> {
204         match value {
205             JValue::Bool(b) => Ok(b),
206             _ => Err(Error::WrongJValueType("bool", value.type_name())),
207         }
208     }
209 }
210 
211 // jchar
212 impl<'a> From<jchar> for JValue<'a> {
from(other: jchar) -> Self213     fn from(other: jchar) -> Self {
214         JValue::Char(other)
215     }
216 }
217 
218 impl<'a> TryFrom<JValue<'a>> for jchar {
219     type Error = Error;
220 
try_from(value: JValue<'a>) -> Result<Self>221     fn try_from(value: JValue<'a>) -> Result<Self> {
222         match value {
223             JValue::Char(c) => Ok(c),
224             _ => Err(Error::WrongJValueType("char", value.type_name())),
225         }
226     }
227 }
228 
229 // jshort
230 impl<'a> From<jshort> for JValue<'a> {
from(other: jshort) -> Self231     fn from(other: jshort) -> Self {
232         JValue::Short(other)
233     }
234 }
235 
236 impl<'a> TryFrom<JValue<'a>> for jshort {
237     type Error = Error;
238 
try_from(value: JValue<'a>) -> Result<Self>239     fn try_from(value: JValue<'a>) -> Result<Self> {
240         match value {
241             JValue::Short(s) => Ok(s),
242             _ => Err(Error::WrongJValueType("short", value.type_name())),
243         }
244     }
245 }
246 
247 // jfloat
248 impl<'a> From<jfloat> for JValue<'a> {
from(other: jfloat) -> Self249     fn from(other: jfloat) -> Self {
250         JValue::Float(other)
251     }
252 }
253 
254 impl<'a> TryFrom<JValue<'a>> for jfloat {
255     type Error = Error;
256 
try_from(value: JValue<'a>) -> Result<Self>257     fn try_from(value: JValue<'a>) -> Result<Self> {
258         match value {
259             JValue::Float(f) => Ok(f),
260             _ => Err(Error::WrongJValueType("float", value.type_name())),
261         }
262     }
263 }
264 
265 // jdouble
266 impl<'a> From<jdouble> for JValue<'a> {
from(other: jdouble) -> Self267     fn from(other: jdouble) -> Self {
268         JValue::Double(other)
269     }
270 }
271 
272 impl<'a> TryFrom<JValue<'a>> for jdouble {
273     type Error = Error;
274 
try_from(value: JValue<'a>) -> Result<Self>275     fn try_from(value: JValue<'a>) -> Result<Self> {
276         match value {
277             JValue::Double(d) => Ok(d),
278             _ => Err(Error::WrongJValueType("double", value.type_name())),
279         }
280     }
281 }
282 
283 // jint
284 impl<'a> From<jint> for JValue<'a> {
from(other: jint) -> Self285     fn from(other: jint) -> Self {
286         JValue::Int(other)
287     }
288 }
289 
290 impl<'a> TryFrom<JValue<'a>> for jint {
291     type Error = Error;
292 
try_from(value: JValue<'a>) -> Result<Self>293     fn try_from(value: JValue<'a>) -> Result<Self> {
294         match value {
295             JValue::Int(i) => Ok(i),
296             _ => Err(Error::WrongJValueType("int", value.type_name())),
297         }
298     }
299 }
300 
301 // jlong
302 impl<'a> From<jlong> for JValue<'a> {
from(other: jlong) -> Self303     fn from(other: jlong) -> Self {
304         JValue::Long(other)
305     }
306 }
307 
308 impl<'a> TryFrom<JValue<'a>> for jlong {
309     type Error = Error;
310 
try_from(value: JValue<'a>) -> Result<Self>311     fn try_from(value: JValue<'a>) -> Result<Self> {
312         match value {
313             JValue::Long(l) => Ok(l),
314             _ => Err(Error::WrongJValueType("long", value.type_name())),
315         }
316     }
317 }
318 
319 // jbyte
320 impl<'a> From<jbyte> for JValue<'a> {
from(other: jbyte) -> Self321     fn from(other: jbyte) -> Self {
322         JValue::Byte(other)
323     }
324 }
325 
326 impl<'a> TryFrom<JValue<'a>> for jbyte {
327     type Error = Error;
328 
try_from(value: JValue<'a>) -> Result<Self>329     fn try_from(value: JValue<'a>) -> Result<Self> {
330         match value {
331             JValue::Byte(b) => Ok(b),
332             _ => Err(Error::WrongJValueType("byte", value.type_name())),
333         }
334     }
335 }
336 
337 // jvoid
338 impl<'a> From<()> for JValue<'a> {
from(_: ()) -> Self339     fn from(_: ()) -> Self {
340         JValue::Void
341     }
342 }
343 
344 impl<'a> TryFrom<JValue<'a>> for () {
345     type Error = Error;
346 
try_from(value: JValue<'a>) -> Result<Self>347     fn try_from(value: JValue<'a>) -> Result<Self> {
348         match value {
349             JValue::Void => Ok(()),
350             _ => Err(Error::WrongJValueType("void", value.type_name())),
351         }
352     }
353 }
354