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