jni_bindgen_reflection/
method.rs1use crate::*;
4use crate::io::*;
5pub use field::BasicType;
6pub use field::Descriptor as Type;
7
8use bitflags::bitflags;
9
10use std::io::{self, Read};
11
12
13
14bitflags! {
15 #[derive(Default)]
16 pub struct Flags : u16 {
18 const PUBLIC = 0x0001;
20 const PRIVATE = 0x0002;
22 const PROTECTED = 0x0004;
24 const STATIC = 0x0008;
26 const FINAL = 0x0010;
28 const SYNCRONIZED = 0x0020;
30 const BRIDGE = 0x0040;
32 const VARARGS = 0x0080;
34 const NATIVE = 0x0100;
36 const ABSTRACT = 0x0400;
38 const STRICT = 0x0800;
40 const SYNTHETIC = 0x1000;
42 }
43}
44
45impl Flags {
46 pub fn read(r: &mut impl Read) -> io::Result<Self> {
47 Ok(Self::from_bits_truncate(read_u2(r)?))
48 }
49}
50
51
52
53#[derive(Clone, Debug)]
55pub struct Method {
56 pub flags: Flags,
57 pub name: String,
58 descriptor: String,
59 pub deprecated: bool,
60 _incomplete: (),
61}
62
63#[allow(dead_code)]
64impl Method {
65 pub fn new(flags: Flags, name: String, descriptor: String) -> io::Result<Self> {
66 method::Descriptor::new(descriptor.as_str())?;
67 Ok(Self {
68 flags,
69 name,
70 descriptor,
71 deprecated: false,
72 _incomplete: (),
73 })
74 }
75
76 pub fn descriptor_str(&self) -> &str { self.descriptor.as_str() }
77 pub fn descriptor(&self) -> Descriptor { Descriptor::new(self.descriptor.as_str()).unwrap() } pub fn is_public (&self) -> bool { self.flags.contains(Flags::PUBLIC ) }
80 pub fn is_private (&self) -> bool { self.flags.contains(Flags::PRIVATE ) }
81 pub fn is_protected (&self) -> bool { self.flags.contains(Flags::PROTECTED ) }
82 pub fn is_static (&self) -> bool { self.flags.contains(Flags::STATIC ) }
83 pub fn is_final (&self) -> bool { self.flags.contains(Flags::FINAL ) }
84 pub fn is_syncronized (&self) -> bool { self.flags.contains(Flags::SYNCRONIZED ) }
85 pub fn is_bridge (&self) -> bool { self.flags.contains(Flags::BRIDGE ) }
86 pub fn is_varargs (&self) -> bool { self.flags.contains(Flags::VARARGS ) }
87 pub fn is_native (&self) -> bool { self.flags.contains(Flags::NATIVE ) }
88 pub fn is_abstract (&self) -> bool { self.flags.contains(Flags::ABSTRACT ) }
89 pub fn is_strict (&self) -> bool { self.flags.contains(Flags::STRICT ) }
90 pub fn is_synthetic (&self) -> bool { self.flags.contains(Flags::SYNTHETIC ) }
91
92 pub fn is_constructor (&self) -> bool { self.name == "<init>" }
93 pub fn is_static_init (&self) -> bool { self.name == "<clinit>" }
94
95 pub fn access(&self) -> Option<&'static str> {
96 if self.is_private() { Some("private") }
97 else if self.is_protected() { Some("protected") }
98 else if self.is_public() { Some("public") }
99 else { None }
100 }
101
102 pub(crate) fn read_one(read: &mut impl Read, constants: &Constants) -> io::Result<Self> {
103 let flags = Flags::read(read)?;
104 let name = constants.get_utf8(read_u2(read)?)?.to_owned();
105 let descriptor = constants.get_utf8(read_u2(read)?)?.to_owned();
106 let attributes_count = read_u2(read)? as usize;
107
108 method::Descriptor::new(descriptor.as_str())?;
109
110 let mut deprecated = false;
111 for _ in 0..attributes_count {
112 match Attribute::read(read, constants)? {
113 Attribute::Deprecated { .. } => { deprecated = true; },
114 _ => {},
115 }
116 }
117
118 Ok(Self{
119 flags,
120 name,
121 descriptor,
122 deprecated,
123 _incomplete: (),
124 })
125 }
126
127 pub(crate) fn read_list(read: &mut impl Read, constants: &Constants) -> io::Result<Vec<Self>> {
128 let n = read_u2(read)? as usize;
129 let mut methods = Vec::with_capacity(n);
130 for _ in 0..n {
131 methods.push(Self::read_one(read, constants)?);
132 }
133 Ok(methods)
134 }
135}
136
137
138
139#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
140pub struct Descriptor<'a> {
141 string: &'a str,
142 end_paren: usize,
143}
144
145impl<'a> Descriptor<'a> {
146 pub fn new(desc: &'a str) -> io::Result<Descriptor<'a>> {
147 if !desc.starts_with('(') { return io_data_err!("Method descriptor didn't start with '(': {:?}", desc); }
148 let end_paren = if let Some(i) = desc.rfind(')') { i } else { return io_data_err!("Method descriptor doesn't contain a ')' terminating the arguments list: {:?}", desc); };
149 let (arguments, return_) = desc.split_at(end_paren);
150
151 Type::from_str(&return_[1..])?; let mut args = &arguments[1..]; while !args.is_empty() {
154 Type::read_next(&mut args)?;
155 }
156
157 Ok(Descriptor { string: desc, end_paren })
158 }
159
160 #[allow(dead_code)]
161 pub fn as_str(&self) -> &'a str { self.string }
162 pub fn return_type(&self) -> Type<'a> { Type::from_str(&self.string[(1+self.end_paren)..]).unwrap() } pub fn arguments(&self) -> ArgumentsIter { ArgumentsIter(&self.string[1..self.end_paren]) }
164}
165
166pub struct ArgumentsIter<'a>(&'a str);
167
168impl<'a> Iterator for ArgumentsIter<'a> {
169 type Item = Type<'a>;
170 fn next(&mut self) -> Option<Self::Item> {
171 if self.0.is_empty() {
172 None
173 } else {
174 Some(Type::read_next(&mut self.0).unwrap()) }
176 }
177}
178
179#[test] fn jni_descriptor_from_str() {
180 let d = Descriptor::new("(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;").unwrap();
181 assert_eq!(d.return_type(), Type::Single(BasicType::Class(class::Id("android/database/Cursor"))));
182 let mut d = d.arguments();
183 assert_eq!(d.next(), Some(Type::Single(BasicType::Class(class::Id("android/net/Uri")))));
184 assert_eq!(d.next(), Some(Type::Array { levels: 1, inner: BasicType::Class(class::Id("java/lang/String")) }));
185 assert_eq!(d.next(), Some(Type::Single(BasicType::Class(class::Id("java/lang/String")))));
186 assert_eq!(d.next(), Some(Type::Array { levels: 1, inner: BasicType::Class(class::Id("java/lang/String")) }));
187 assert_eq!(d.next(), Some(Type::Single(BasicType::Class(class::Id("java/lang/String")))));
188 assert_eq!(d.next(), None);
189 assert_eq!(d.next(), None);
190
191 let d = Descriptor::new("(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Landroid/os/CancellationSignal;)Landroid/database/Cursor;").unwrap();
192 assert_eq!(d.return_type(), Type::Single(BasicType::Class(class::Id("android/database/Cursor"))));
193 let mut d = d.arguments();
194 assert_eq!(d.next(), Some(Type::Single(BasicType::Class(class::Id("android/net/Uri")))));
195 assert_eq!(d.next(), Some(Type::Array { levels: 1, inner: BasicType::Class(class::Id("java/lang/String")) }));
196 assert_eq!(d.next(), Some(Type::Single(BasicType::Class(class::Id("java/lang/String")))));
197 assert_eq!(d.next(), Some(Type::Array { levels: 1, inner: BasicType::Class(class::Id("java/lang/String")) }));
198 assert_eq!(d.next(), Some(Type::Single(BasicType::Class(class::Id("java/lang/String")))));
199 assert_eq!(d.next(), Some(Type::Single(BasicType::Class(class::Id("android/os/CancellationSignal")))));
200 assert_eq!(d.next(), None);
201 assert_eq!(d.next(), None);
202
203 let d = Descriptor::new("(Landroid/net/Uri;[Ljava/lang/String;Landroid/os/Bundle;Landroid/os/CancellationSignal;)Landroid/database/Cursor;").unwrap();
204 assert_eq!(d.return_type(), Type::Single(BasicType::Class(class::Id("android/database/Cursor"))));
205 let mut d = d.arguments();
206 assert_eq!(d.next(), Some(Type::Single(BasicType::Class(class::Id("android/net/Uri")))));
207 assert_eq!(d.next(), Some(Type::Array { levels: 1, inner: BasicType::Class(class::Id("java/lang/String")) }));
208 assert_eq!(d.next(), Some(Type::Single(BasicType::Class(class::Id("android/os/Bundle")))));
209 assert_eq!(d.next(), Some(Type::Single(BasicType::Class(class::Id("android/os/CancellationSignal")))));
210 assert_eq!(d.next(), None);
211 assert_eq!(d.next(), None);
212
213 let d = Descriptor::new("([Ljava/lang/String;)V").unwrap();
214 assert_eq!(d.return_type(), Type::Single(BasicType::Void));
215 let mut d = d.arguments();
216 assert_eq!(d.next(), Some(Type::Array { levels: 1, inner: BasicType::Class(class::Id("java/lang/String")) }));
217 assert_eq!(d.next(), None);
218 assert_eq!(d.next(), None);
219
220 let d = Descriptor::new("()V").unwrap();
221 assert_eq!(d.return_type(), Type::Single(BasicType::Void));
222 let mut d = d.arguments();
223 assert_eq!(d.next(), None);
224 assert_eq!(d.next(), None);
225}