jni_bindgen_reflection/
class.rs1use crate::*;
7use crate::io::*;
8
9use bitflags::bitflags;
10
11use std::io::{self, Read};
12
13
14
15bitflags! {
16 #[derive(Default)]
17 pub struct Flags : u16 {
19 const PUBLIC = 0x0001;
21 const STATIC = 0x0008;
23 const FINAL = 0x0010;
25 const SUPER = 0x0020;
27 const INTERFACE = 0x0200;
29 const ABSTRACT = 0x0400;
31 const SYNTHETIC = 0x1000;
33 const ANNOTATION = 0x2000;
35 const ENUM = 0x4000;
37 }
38}
39
40impl Flags {
41 pub(crate) fn read(r: &mut impl Read) -> io::Result<Self> {
42 Ok(Self::from_bits_truncate(read_u2(r)?))
43 }
44}
45
46
47
48#[repr(C)]
50#[derive(Clone, Copy, Debug, Default)]
51struct Header {
52 pub magic: [u8; 4],
53 pub minor_version: u16,
54 pub major_version: version::Major,
55}
56
57impl Header {
58 pub(crate) fn read(reader: &mut impl Read) -> io::Result<Header> {
59 let mut h = Header::default();
60 reader.read_exact(&mut h.magic)?;
61 if h.magic != [0xCA, 0xFE, 0xBA, 0xBE] { return io_data_err!("Invalid header magic, not a class file"); }
62 h.minor_version = read_u2(reader)?;
63 h.major_version = version::Major(read_u2(reader)?);
64 Ok(h)
65 }
66}
67
68
69
70#[derive(Clone, Debug, Default)]
71pub struct Class {
72 pub flags: Flags,
73 pub path: IdBuf,
74 pub super_path: Option<IdBuf>,
75 pub interfaces: Vec<IdBuf>,
76 pub fields: Vec<Field>,
77 pub methods: Vec<Method>,
78 pub deprecated: bool,
79}
80
81#[allow(dead_code)]
82impl Class {
83 pub fn read(read: &mut impl Read) -> io::Result<Self> {
85 let _header = Header::read(read)?;
86 let constants = Constants::read(read)?;
87 let flags = Flags::read(read)?;
88 let path = IdBuf::new(constants.get_class(read_u2(read)?)?.to_owned());
89 let super_path = constants.get_optional_class(read_u2(read)?)?.map(|s| IdBuf::new(s.to_owned()));
90
91 let interfaces_count = read_u2(read)? as usize;
92 let mut interfaces = Vec::with_capacity(interfaces_count);
93 for _ in 0..interfaces_count {
94 interfaces.push(IdBuf::new(constants.get_class(read_u2(read)?)?.to_owned()));
95 }
96
97 let fields = Field::read_list(read, &constants)?;
98 let methods = Method::read_list(read, &constants)?;
99
100 let attributes_count = read_u2(read)?;
101 let mut deprecated = false;
102 for _ in 0..attributes_count {
103 match Attribute::read(read, &constants)? {
104 Attribute::Deprecated { .. } => { deprecated = true; },
105 _ => {},
106 }
107 }
108
109 Ok(Self {
110 flags,
111 path,
112 super_path,
113 interfaces,
114 fields,
115 methods,
116 deprecated,
117 })
118 }
119
120 pub fn is_public(&self) -> bool { self.flags.contains(Flags::PUBLIC) }
121 pub fn is_static(&self) -> bool { self.flags.contains(Flags::STATIC) }
122 pub fn is_final(&self) -> bool { self.flags.contains(Flags::FINAL) }
123 pub fn is_super(&self) -> bool { self.flags.contains(Flags::SUPER) }
124 pub fn is_interface(&self) -> bool { self.flags.contains(Flags::INTERFACE) }
125 pub fn is_abstract(&self) -> bool { self.flags.contains(Flags::ABSTRACT) }
126 pub fn is_synthetic(&self) -> bool { self.flags.contains(Flags::SYNTHETIC) }
127 pub fn is_annotation(&self) -> bool { self.flags.contains(Flags::ANNOTATION) }
128 pub fn is_enum(&self) -> bool { self.flags.contains(Flags::ENUM) }
129}
130
131
132
133#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
134pub struct IdBuf(String);
135
136impl IdBuf {
137 pub fn new(s: String) -> Self { Self(s) }
138 pub fn as_str(&self) -> &str { self.0.as_str() }
139 pub fn as_id(&self) -> Id { Id(self.0.as_str()) }
140 #[allow(dead_code)] pub fn iter(&self) -> IdIter { IdIter::new(self.0.as_str()) }
141}
142
143#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
146pub struct Id<'a>(pub &'a str);
147
148impl<'a> Id<'a> {
149 pub fn as_str(&self) -> &'a str { self.0 }
150 pub fn iter(&self) -> IdIter<'a> { IdIter::new(self.0) }
151}
152
153#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
154pub enum IdPart<'a> {
155 Namespace(&'a str),
156 ContainingClass(&'a str),
157 LeafClass(&'a str),
158}
159
160pub struct IdIter<'a> {
161 rest: &'a str,
162}
163
164impl<'a> IdIter<'a> {
165 pub fn new(path: &'a str) -> Self { IdIter { rest: path } }
166}
167
168impl<'a> Iterator for IdIter<'a> {
169 type Item = IdPart<'a>;
170 fn next(&mut self) -> Option<Self::Item> {
171 if let Some(slash) = self.rest.find('/') {
172 let (namespace, rest) = self.rest.split_at(slash);
173 self.rest = &rest[1..];
174 return Some(IdPart::Namespace(namespace));
175 }
176
177 if let Some(dollar) = self.rest.find('$') {
178 let (class, rest) = self.rest.split_at(dollar);
179 self.rest = &rest[1..];
180 return Some(IdPart::ContainingClass(class));
181 }
182
183 if !self.rest.is_empty() {
184 let class = self.rest;
185 self.rest = "";
186 return Some(IdPart::LeafClass(class));
187 }
188
189 None
190 }
191}
192
193#[test] fn id_iter_test() {
194 assert_eq!(Id("").iter().collect::<Vec<IdPart>>(), &[]);
195
196 assert_eq!(Id("Bar").iter().collect::<Vec<IdPart>>(), &[
197 IdPart::LeafClass("Bar"),
198 ]);
199
200 assert_eq!(Id("java/foo/Bar").iter().collect::<Vec<IdPart>>(), &[
201 IdPart::Namespace("java"),
202 IdPart::Namespace("foo"),
203 IdPart::LeafClass("Bar"),
204 ]);
205
206 assert_eq!(Id("java/foo/Bar$Inner").iter().collect::<Vec<IdPart>>(), &[
207 IdPart::Namespace("java"),
208 IdPart::Namespace("foo"),
209 IdPart::ContainingClass("Bar"),
210 IdPart::LeafClass("Inner"),
211 ]);
212
213 assert_eq!(Id("java/foo/Bar$Inner$MoreInner").iter().collect::<Vec<IdPart>>(), &[
214 IdPart::Namespace("java"),
215 IdPart::Namespace("foo"),
216 IdPart::ContainingClass("Bar"),
217 IdPart::ContainingClass("Inner"),
218 IdPart::LeafClass("MoreInner"),
219 ]);
220}