forked from Dirbaio/java-spaghetti
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclass.rs
More file actions
100 lines (87 loc) · 2.99 KB
/
class.rs
File metadata and controls
100 lines (87 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
use std::marker::PhantomPinned;
use std::pin::Pin;
pub use cafebabe::ClassAccessFlags;
use cafebabe::attributes::AttributeData;
use cafebabe::descriptors::ClassName;
use super::Id;
#[derive(Debug)]
pub struct JavaClass {
#[allow(unused)]
raw_bytes: Pin<Box<(Vec<u8>, PhantomPinned)>>,
inner: cafebabe::ClassFile<'static>,
}
impl JavaClass {
pub fn read(raw_bytes: Vec<u8>) -> Result<Self, cafebabe::ParseError> {
let pinned = Box::pin((raw_bytes, PhantomPinned));
// SAFETY: `get<'a>(&'a self)` restricts the lifetime parameter of
// the returned referenced `ClassFile`.
let fake_static = unsafe { std::slice::from_raw_parts(pinned.0.as_ptr(), pinned.0.len()) };
let inner = cafebabe::parse_class(fake_static)?;
Ok(Self {
raw_bytes: pinned,
inner,
})
}
// It is probably not possible to implement `Deref` safely.
pub fn get<'a>(&'a self) -> &'a cafebabe::ClassFile<'a> {
// SAFETY: casts `self.inner` into `cafebabe::ClassFile<'a>` forcefully.
// `cafebabe::parse_class` takes immutable &'a [u8], why is the returned
// `ClassFile<'a>` invariant over `'a`?
unsafe { &*(&raw const (self.inner)).cast() }
}
fn flags(&self) -> ClassAccessFlags {
self.get().access_flags
}
pub fn is_public(&self) -> bool {
self.flags().contains(ClassAccessFlags::PUBLIC)
}
pub fn is_final(&self) -> bool {
self.flags().contains(ClassAccessFlags::FINAL)
}
pub fn is_static(&self) -> bool {
(self.flags().bits() & 0x0008) != 0
}
#[allow(unused)]
pub fn is_super(&self) -> bool {
self.flags().contains(ClassAccessFlags::SUPER)
}
pub fn is_interface(&self) -> bool {
self.flags().contains(ClassAccessFlags::INTERFACE)
}
#[allow(unused)]
pub fn is_abstract(&self) -> bool {
self.flags().contains(ClassAccessFlags::ABSTRACT)
}
#[allow(unused)]
pub fn is_synthetic(&self) -> bool {
self.flags().contains(ClassAccessFlags::SYNTHETIC)
}
#[allow(unused)]
pub fn is_annotation(&self) -> bool {
self.flags().contains(ClassAccessFlags::ANNOTATION)
}
pub fn is_enum(&self) -> bool {
self.flags().contains(ClassAccessFlags::ENUM)
}
pub fn path(&self) -> Id<'_> {
Id(self.get().this_class.as_ref())
}
pub fn super_path(&self) -> Option<Id<'_>> {
self.get().super_class.as_ref().map(|class| Id(class))
}
pub fn interfaces(&self) -> std::slice::Iter<'_, ClassName<'_>> {
self.get().interfaces.iter()
}
pub fn fields(&self) -> std::slice::Iter<'_, cafebabe::FieldInfo<'_>> {
self.get().fields.iter()
}
pub fn methods(&self) -> std::slice::Iter<'_, cafebabe::MethodInfo<'_>> {
self.get().methods.iter()
}
pub fn deprecated(&self) -> bool {
self.get()
.attributes
.iter()
.any(|attr| matches!(attr.data, AttributeData::Deprecated))
}
}