Skip to main content

jni_bindgen_reflection/
field.rs

1//! [Java SE 7 § 4.5](https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.5):  Parsing APIs and structures for class fields.
2
3use crate::*;
4use crate::io::*;
5
6use bitflags::bitflags;
7
8use std::fmt::{self, Debug, Display, Formatter};
9use std::io::{self, Read};
10
11
12
13bitflags! {
14    #[derive(Default)]
15    /// [Java SE 7 § 4.5](https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.5):  field_info::access_flags
16    pub struct Flags : u16 {
17        /// Declared `public`; may be accessed from outside its package.
18        const PUBLIC        = 0x0001;
19        /// Declared `private`; usable only with the defining class.
20        const PRIVATE       = 0x0002;
21        /// Declared `protectdd`; may be accessed within subclasses.
22        const PROTECTED     = 0x0004;
23        /// Declared `static`.
24        const STATIC        = 0x0008;
25        /// Declared `final`; no subclasses allowed.
26        const FINAL         = 0x0010;
27        /// Declared `volatile`; cannot be cached.
28        const VOLATILE      = 0x0040;
29        /// Declared `transient`; not written or read by a persistent object manager.
30        const TRANSIENT     = 0x0080;
31        /// Declared synthetic; not present in the source code.
32        const SYNTHETIC     = 0x1000;
33        /// Declared as an enum type.
34        const ENUM          = 0x4000;
35    }
36}
37
38impl Flags {
39    pub(crate) fn read(r: &mut impl Read) -> io::Result<Self> {
40        Ok(Self::from_bits_truncate(read_u2(r)?))
41    }
42}
43
44#[derive(Clone, Debug, PartialEq, PartialOrd)]
45pub enum Constant {
46    Integer(i32),
47    Long(i64),
48    Float(f32),
49    Double(f64),
50    String(String),
51}
52
53impl Display for Constant {
54    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
55        match self {
56            Constant::Integer(value) => write!(fmt, "{}", value),
57            Constant::Long(value) => write!(fmt, "{}i64", value),
58
59            Constant::Float(value) if value.is_infinite() && *value < 0.0   => write!(fmt, "__jni_bindgen::std::f32::NEG_INFINITY"),
60            Constant::Float(value) if value.is_infinite()                   => write!(fmt, "__jni_bindgen::std::f32::INFINITY"),
61            Constant::Float(value) if value.is_nan()                        => write!(fmt, "__jni_bindgen::std::f32::NAN"),
62            Constant::Float(value)                                          => write!(fmt, "{}f32", value),
63
64            Constant::Double(value) if value.is_infinite() && *value < 0.0  => write!(fmt, "__jni_bindgen::std::f64::NEG_INFINITY"),
65            Constant::Double(value) if value.is_infinite()                  => write!(fmt, "__jni_bindgen::std::f64::INFINITY"),
66            Constant::Double(value) if value.is_nan()                       => write!(fmt, "__jni_bindgen::std::f64::NAN"),
67            Constant::Double(value)                                         => write!(fmt, "{}f64", value),
68
69            Constant::String(value) => Debug::fmt(value, fmt)
70        }
71    }
72}
73
74
75
76/// [Java SE 7 &sect; 4.5](https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.5):  field_info
77#[derive(Clone, Debug)]
78pub struct Field {
79    pub flags:      Flags,
80    pub name:       String,
81    descriptor:     String,
82    pub deprecated: bool,
83    pub constant:   Option<Constant>,
84    _incomplete:    (),
85}
86
87#[allow(dead_code)]
88impl Field {
89    pub fn new(flags: Flags, name: String, descriptor: String) -> io::Result<Self> {
90        Descriptor::from_str(descriptor.as_str())?;
91
92        Ok(Self {
93            flags,
94            name,
95            descriptor,
96            deprecated: false,
97            constant: None,
98            _incomplete: (),
99        })
100    }
101
102    pub fn descriptor_str(&self) -> &str { self.descriptor.as_str() }
103    pub fn descriptor(&self) -> Descriptor { Descriptor::from_str(self.descriptor.as_str()).unwrap() } // Was already validated in Field::new / Field::read_one
104
105    pub fn is_public(&self)     -> bool { self.flags.contains(Flags::PUBLIC) }
106    pub fn is_private(&self)    -> bool { self.flags.contains(Flags::PRIVATE) }
107    pub fn is_protected(&self)  -> bool { self.flags.contains(Flags::PROTECTED) }
108    pub fn is_static(&self)     -> bool { self.flags.contains(Flags::STATIC) }
109    pub fn is_final(&self)      -> bool { self.flags.contains(Flags::FINAL) }
110    pub fn is_volatile(&self)   -> bool { self.flags.contains(Flags::VOLATILE) }
111    pub fn is_transient(&self)  -> bool { self.flags.contains(Flags::TRANSIENT) }
112    pub fn is_synthetic(&self)  -> bool { self.flags.contains(Flags::SYNTHETIC) }
113    pub fn is_enum(&self)       -> bool { self.flags.contains(Flags::ENUM) }
114
115    pub fn is_constant(&self)   -> bool { self.is_final() && self.is_static() && self.constant.is_some() }
116
117    pub fn access(&self) -> Option<&'static str> {
118        if      self.is_private()   { Some("private") }
119        else if self.is_protected() { Some("protected") }
120        else if self.is_public()    { Some("public") }
121        else                        { None }
122    }
123
124    pub(crate) fn read_one(read: &mut impl Read, constants: &Constants) -> io::Result<Self> {
125        let flags               = Flags::read(read)?;
126        let name                = constants.get_utf8(read_u2(read)?)?.to_owned();
127        let descriptor          = constants.get_utf8(read_u2(read)?)?.to_owned();
128        let attributes_count    = read_u2(read)? as usize;
129
130        Descriptor::from_str(descriptor.as_str())?;
131
132        let mut deprecated      = false;
133        let mut constant        = None;
134        for _ in 0..attributes_count {
135            match Attribute::read(read, constants)? {
136                Attribute::Deprecated { .. }    => { deprecated = true; },
137                Attribute::ConstantValue(value) => { constant = Some(value); },
138                _ => {},
139            }
140        }
141
142        Ok(Self{
143            flags,
144            name,
145            descriptor,
146            deprecated,
147            constant,
148            _incomplete: (),
149        })
150    }
151
152    pub(crate) fn read_list(read: &mut impl Read, constants: &Constants) -> io::Result<Vec<Self>> {
153        let n = read_u2(read)? as usize;
154        let mut fields = Vec::with_capacity(n);
155        for _ in 0..n {
156            fields.push(Self::read_one(read, constants)?);
157        }
158        Ok(fields)
159    }
160}
161
162
163
164#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
165pub enum BasicType<'a> {
166    Byte,
167    Char,
168    Double,
169    Float,
170    Int,
171    Long,
172    Class(class::Id<'a>),
173    Short,
174    Boolean,
175    Void, // Only really crops up for method return types.
176}
177
178
179
180#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
181pub enum Descriptor<'a> {
182    Single(BasicType<'a>),
183    Array { levels: usize, inner: BasicType<'a> },
184}
185
186impl<'a> Descriptor<'a> {
187    /// Consume a Descriptor from a string.  Will set `remaining` to parse the *remainder* of the string.
188    pub(crate) fn read_next(remaining: &mut &'a str) -> io::Result<Descriptor<'a>> {
189        let original = *remaining;
190        let mut array = 0;
191        let mut chars = remaining.chars();
192
193        let leaf = loop {
194            match chars.next() {
195                None => return io_data_err!("Expected basic type before end of string parsing field descriptor: {:?}", original),
196                Some('B') => { *remaining = chars.as_str(); break BasicType::Byte     }
197                Some('C') => { *remaining = chars.as_str(); break BasicType::Char     }
198                Some('D') => { *remaining = chars.as_str(); break BasicType::Double   }
199                Some('F') => { *remaining = chars.as_str(); break BasicType::Float    }
200                Some('I') => { *remaining = chars.as_str(); break BasicType::Int      }
201                Some('J') => { *remaining = chars.as_str(); break BasicType::Long     }
202                Some('L') => {
203                    let chars_str = chars.as_str();
204                    if let Some(semi) = chars_str.find(';') {
205                        *remaining = &chars_str[(semi+1)..];
206                        break BasicType::Class(class::Id(&chars_str[..semi]))
207                    } else {
208                        return io_data_err!("Expected ';' before end of string parsing field descriptor: {:?}", original)
209                    }
210                }
211                Some('S') => { *remaining = chars.as_str(); break BasicType::Short    }
212                Some('Z') => { *remaining = chars.as_str(); break BasicType::Boolean  }
213                Some('V') => { *remaining = chars.as_str(); break BasicType::Void     }
214                Some('[') => { array += 1; }
215                Some(ch)  => return io_data_err!("Unexpected character in field descriptor string: {:?}", ch),
216            }
217        };
218
219        match array {
220            0   => Ok(Descriptor::Single(leaf)),
221            n   => Ok(Descriptor::Array { levels: n, inner: leaf }),
222        }
223    }
224
225    pub(crate) fn from_str(field: &'a str) -> io::Result<Descriptor<'a>> {
226        let mut remaining = field;
227        let next = Self::read_next(&mut remaining)?;
228        if remaining.is_empty() {
229            Ok(next)
230        } else {
231            io_data_err!("Expected one field descriptor, got multiple.\n  Full field: {:?}\n  Unparsed: {:?}\n", field, remaining)
232        }
233    }
234}
235
236#[test] fn descriptor_from_str() {
237    // Single values
238    assert_eq!(Descriptor::from_str("F").unwrap(),                 Descriptor::Single(BasicType::Float));
239    assert_eq!(Descriptor::from_str("Ljava/foo/Bar;").unwrap(),    Descriptor::Single(BasicType::Class(class::Id("java/foo/Bar"))));
240
241    // Arrays
242    assert_eq!(Descriptor::from_str("[[F").unwrap(),               Descriptor::Array { levels: 2, inner: BasicType::Float });
243    assert_eq!(Descriptor::from_str("[[[Ljava/foo/Bar;").unwrap(), Descriptor::Array { levels: 3, inner: BasicType::Class(class::Id("java/foo/Bar")) });
244
245    // Erroneous input
246    assert!(Descriptor::from_str("").is_err());                               // No type
247    assert!(Descriptor::from_str("[[").is_err());                             // No type for array
248    assert!(Descriptor::from_str("Ljava/foo/Bar").is_err());                  // Missing semicolon
249    assert!(Descriptor::from_str("Ljava/foo/Bar;F").is_err());                // More after semicolon
250    assert!(Descriptor::from_str("Ljava/foo/Bar;Ljava/foo/Bar;").is_err());   // More after semicolon
251
252    // Multiple inputs
253    let mut class_float = "Ljava/foo/Bar;F";
254    assert_eq!(Descriptor::read_next(&mut class_float).unwrap(),    Descriptor::Single(BasicType::Class(class::Id("java/foo/Bar"))));
255    assert_eq!(Descriptor::read_next(&mut class_float).unwrap(),    Descriptor::Single(BasicType::Float));
256    assert_eq!(class_float, "");
257    assert!(   Descriptor::read_next(&mut class_float).is_err());
258
259    let mut class_class = "Ljava/foo/Bar;Ljava/foo/Bar;";
260    assert_eq!(Descriptor::read_next(&mut class_class).unwrap(),    Descriptor::Single(BasicType::Class(class::Id("java/foo/Bar"))));
261    assert_eq!(Descriptor::read_next(&mut class_class).unwrap(),    Descriptor::Single(BasicType::Class(class::Id("java/foo/Bar"))));
262    assert_eq!(class_class, "");
263    assert!(   Descriptor::read_next(&mut class_class).is_err());
264}