1 use crate::sys::jfieldID; 2 3 /// Wrapper around [`jfieldID`] that implements `Send` + `Sync` since method IDs 4 /// are valid across threads (not tied to a `JNIEnv`). 5 /// 6 /// There is no lifetime associated with these since they aren't garbage 7 /// collected like objects and their lifetime is not implicitly connected with 8 /// the scope in which they are queried. 9 /// 10 /// It matches C's representation of the raw pointer, so it can be used in any 11 /// of the extern function argument positions that would take a [`jfieldID`]. 12 /// 13 /// # Safety 14 /// 15 /// According to the JNI spec field IDs may be invalidated when the 16 /// corresponding class is unloaded. 17 /// 18 /// Since this constraint can't be encoded as a Rust lifetime, and to avoid the 19 /// excessive cost of having every Method ID be associated with a global 20 /// reference to the corresponding class then it is the developers 21 /// responsibility to ensure they hold some class reference for the lifetime of 22 /// cached method IDs. 23 #[repr(transparent)] 24 #[derive(Copy, Clone)] 25 pub struct JFieldID { 26 internal: jfieldID, 27 } 28 29 // Field IDs are valid across threads (not tied to a JNIEnv) 30 unsafe impl Send for JFieldID {} 31 unsafe impl Sync for JFieldID {} 32 33 impl JFieldID { 34 /// Creates a [`JFieldID`] that wraps the given `raw` [`jfieldID`] 35 /// 36 /// # Safety 37 /// 38 /// Expects a valid, non-`null` ID from_raw(raw: jfieldID) -> Self39 pub unsafe fn from_raw(raw: jfieldID) -> Self { 40 debug_assert!(!raw.is_null(), "from_raw fieldID argument"); 41 Self { internal: raw } 42 } 43 44 /// Unwrap to the internal jni type. into_raw(self) -> jfieldID45 pub fn into_raw(self) -> jfieldID { 46 self.internal 47 } 48 } 49 50 impl AsRef<JFieldID> for JFieldID { as_ref(&self) -> &JFieldID51 fn as_ref(&self) -> &JFieldID { 52 self 53 } 54 } 55 56 impl AsMut<JFieldID> for JFieldID { as_mut(&mut self) -> &mut JFieldID57 fn as_mut(&mut self) -> &mut JFieldID { 58 self 59 } 60 } 61