ferro_babe/model/
stack_map.rs1use rust_asm::class_reader::{
2 StackMapFrame as RawStackMapFrame, VerificationTypeInfo as RawVerificationType,
3};
4use rust_asm::constant_pool::CpInfo;
5
6use super::ConstantPoolIndex;
7
8#[derive(Debug, Clone, Copy)]
14pub struct StackMapFrame<'a> {
15 inner: &'a RawStackMapFrame,
16 constant_pool: &'a [CpInfo],
17}
18
19impl<'a> StackMapFrame<'a> {
20 pub(crate) const fn new(inner: &'a RawStackMapFrame, constant_pool: &'a [CpInfo]) -> Self {
21 Self {
22 inner,
23 constant_pool,
24 }
25 }
26
27 #[must_use]
29 pub const fn offset_delta(&self) -> u16 {
30 match self.inner {
31 RawStackMapFrame::SameFrame { offset_delta }
32 | RawStackMapFrame::SameLocals1StackItemFrame { offset_delta, .. }
33 | RawStackMapFrame::SameLocals1StackItemFrameExtended { offset_delta, .. }
34 | RawStackMapFrame::ChopFrame { offset_delta, .. }
35 | RawStackMapFrame::SameFrameExtended { offset_delta }
36 | RawStackMapFrame::AppendFrame { offset_delta, .. }
37 | RawStackMapFrame::FullFrame { offset_delta, .. } => *offset_delta,
38 }
39 }
40
41 #[must_use]
43 pub const fn kind(&self) -> StackMapFrameKind {
44 match self.inner {
45 RawStackMapFrame::SameFrame { .. } => StackMapFrameKind::Same,
46 RawStackMapFrame::SameLocals1StackItemFrame { .. }
47 | RawStackMapFrame::SameLocals1StackItemFrameExtended { .. } => {
48 StackMapFrameKind::SameLocalsOneStackItem
49 }
50 RawStackMapFrame::ChopFrame { k, .. } => StackMapFrameKind::Chop { count: *k },
51 RawStackMapFrame::SameFrameExtended { .. } => StackMapFrameKind::SameExtended,
52 RawStackMapFrame::AppendFrame { .. } => StackMapFrameKind::Append,
53 RawStackMapFrame::FullFrame { .. } => StackMapFrameKind::Full,
54 }
55 }
56
57 #[must_use]
62 pub fn locals(&self) -> Option<VerificationTypes<'a>> {
63 let values = match self.inner {
64 RawStackMapFrame::AppendFrame { locals, .. }
65 | RawStackMapFrame::FullFrame { locals, .. } => locals,
66 _ => return None,
67 };
68 Some(VerificationTypes::new(values, self.constant_pool))
69 }
70
71 #[must_use]
75 pub fn stack(&self) -> Option<VerificationTypes<'a>> {
76 match self.inner {
77 RawStackMapFrame::SameLocals1StackItemFrame { stack, .. }
78 | RawStackMapFrame::SameLocals1StackItemFrameExtended { stack, .. } => {
79 Some(VerificationTypes::single(stack, self.constant_pool))
80 }
81 RawStackMapFrame::FullFrame { stack, .. } => {
82 Some(VerificationTypes::new(stack, self.constant_pool))
83 }
84 _ => None,
85 }
86 }
87}
88
89#[derive(Debug, Clone, Copy, PartialEq, Eq)]
91pub enum StackMapFrameKind {
92 Same,
94 SameLocalsOneStackItem,
96 Chop {
98 count: u8,
100 },
101 SameExtended,
103 Append,
105 Full,
107}
108
109#[derive(Debug, Clone, Copy)]
111pub struct VerificationTypes<'a> {
112 values: &'a [RawVerificationType],
113 constant_pool: &'a [CpInfo],
114}
115
116impl<'a> VerificationTypes<'a> {
117 const fn new(values: &'a [RawVerificationType], constant_pool: &'a [CpInfo]) -> Self {
118 Self {
119 values,
120 constant_pool,
121 }
122 }
123
124 const fn single(value: &'a RawVerificationType, constant_pool: &'a [CpInfo]) -> Self {
125 Self::new(std::slice::from_ref(value), constant_pool)
126 }
127
128 #[must_use]
130 pub const fn len(&self) -> usize {
131 self.values.len()
132 }
133
134 #[must_use]
136 pub const fn is_empty(&self) -> bool {
137 self.values.is_empty()
138 }
139
140 pub fn iter(&self) -> impl ExactSizeIterator<Item = VerificationType<'a>> + '_ {
142 self.values
143 .iter()
144 .map(|value| VerificationType::from_raw(value, self.constant_pool))
145 }
146}
147
148#[derive(Debug, Clone, Copy, PartialEq, Eq)]
150pub enum VerificationType<'a> {
151 Top,
153 Integer,
155 Float,
157 Long,
159 Double,
161 Null,
163 UninitializedThis,
165 Object {
167 internal_name: Option<&'a str>,
169 constant_pool_index: ConstantPoolIndex,
171 },
172 Uninitialized {
174 offset: u16,
176 },
177}
178
179impl<'a> VerificationType<'a> {
180 fn from_raw(value: &'a RawVerificationType, constant_pool: &'a [CpInfo]) -> Self {
181 match value {
182 RawVerificationType::Top => Self::Top,
183 RawVerificationType::Integer => Self::Integer,
184 RawVerificationType::Float => Self::Float,
185 RawVerificationType::Long => Self::Long,
186 RawVerificationType::Double => Self::Double,
187 RawVerificationType::Null => Self::Null,
188 RawVerificationType::UninitializedThis => Self::UninitializedThis,
189 RawVerificationType::Object { cpool_index } => Self::Object {
190 internal_name: class_name(constant_pool, *cpool_index),
191 constant_pool_index: ConstantPoolIndex::new(*cpool_index),
192 },
193 RawVerificationType::Uninitialized { offset } => {
194 Self::Uninitialized { offset: *offset }
195 }
196 }
197 }
198}
199
200fn class_name(constant_pool: &[CpInfo], index: u16) -> Option<&str> {
201 let CpInfo::Class { name_index } = constant_pool.get(usize::from(index))? else {
202 return None;
203 };
204 let CpInfo::Utf8(name) = constant_pool.get(usize::from(*name_index))? else {
205 return None;
206 };
207 Some(name)
208}