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