toad_jni/java/
field.rs

1use core::marker::PhantomData;
2use std::str::FromStr;
3use std::sync::RwLock;
4
5use java::ResultExt;
6use jni::objects::{JFieldID, JStaticFieldID};
7
8use crate::java;
9
10/// A high-level lens into a Java object field
11pub struct Field<C, T> {
12  name: &'static str,
13  id: RwLock<Option<JFieldID>>,
14  _t: PhantomData<(C, T)>,
15}
16
17impl<C, T> Field<C, T>
18  where C: java::Class,
19        T: java::Object
20{
21  /// Creates a new field lens
22  pub const fn new(name: &'static str) -> Self {
23    Self { name,
24           id: RwLock::new(None),
25           _t: PhantomData }
26  }
27
28  /// Get the value of this field
29  pub fn get(&self, e: &mut java::Env, inst: &C) -> T {
30    let id = self.id.read().unwrap();
31    if id.is_none() {
32      drop(id);
33
34      let mut id = self.id.write().unwrap();
35      *id = Some(e.get_field_id(C::PATH, self.name, T::SIG).unwrap_java(e));
36      drop(id);
37
38      self.get(e, inst)
39    } else {
40      let inst = inst.downcast_ref(e);
41      let val =
42        e.get_field_unchecked(&inst,
43                              id.unwrap(),
44                              jni::signature::ReturnType::from_str(T::SIG.as_str()).unwrap())
45         .unwrap_java(e);
46      T::upcast_value(e, val)
47    }
48  }
49
50  /// Set the value of this field
51  pub fn set(&self, e: &mut java::Env, inst: &C, t: T) {
52    let inst = inst.downcast_ref(e);
53    let t = t.downcast_value(e);
54    e.set_field(inst, self.name, T::SIG, (&t).into())
55     .unwrap_java(e);
56  }
57}
58
59/// A high-level lens into a static Java object field
60pub struct StaticField<C, T> {
61  name: &'static str,
62  id: RwLock<Option<JStaticFieldID>>,
63  _t: PhantomData<(C, T)>,
64}
65
66impl<C, T> StaticField<C, T>
67  where C: java::Class,
68        T: java::Object
69{
70  /// Creates a new static field lens
71  pub const fn new(name: &'static str) -> Self {
72    Self { name,
73           id: RwLock::new(None),
74           _t: PhantomData }
75  }
76
77  /// Get the static field value
78  pub fn get(&self, e: &mut java::Env) -> T {
79    let id = self.id.read().unwrap();
80    if id.is_none() {
81      drop(id);
82
83      let mut id = self.id.write().unwrap();
84      *id = Some(e.get_static_field_id(C::PATH, self.name, T::SIG)
85                  .unwrap_java(e));
86      drop(id);
87
88      self.get(e)
89    } else {
90      let val = e.get_static_field_unchecked(C::PATH, id.unwrap(), T::jni())
91                 .unwrap();
92      T::upcast_value(e, val)
93    }
94  }
95}