@@ -121,6 +121,29 @@ pub(crate) struct MethodInfo {
121121 pub ( crate ) is_outline : bool ,
122122}
123123
124+ /// Supported rewrite frame actions.
125+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
126+ pub ( crate ) enum RewriteAction < ' s > {
127+ RemoveInnerFrames ( usize ) ,
128+ /// Placeholder to retain unsupported action strings for future handling.
129+ Unknown ( & ' s str ) ,
130+ }
131+
132+ /// Supported rewrite frame conditions.
133+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
134+ pub ( crate ) enum RewriteCondition < ' s > {
135+ Throws ( & ' s str ) ,
136+ /// Placeholder to retain unsupported condition strings for future handling.
137+ Unknown ( & ' s str ) ,
138+ }
139+
140+ /// A rewrite frame rule attached to a method mapping.
141+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
142+ pub ( crate ) struct RewriteRule < ' s > {
143+ pub ( crate ) conditions : Vec < RewriteCondition < ' s > > ,
144+ pub ( crate ) actions : Vec < RewriteAction < ' s > > ,
145+ }
146+
124147/// A member record in a Proguard file.
125148#[ derive( Clone , Debug ) ]
126149pub ( crate ) struct Member < ' s > {
@@ -136,6 +159,51 @@ pub(crate) struct Member<'s> {
136159 pub ( crate ) original_endline : Option < usize > ,
137160 /// Optional outline callsite positions map attached to this member.
138161 pub ( crate ) outline_callsite_positions : Option < HashMap < usize , usize > > ,
162+ /// Optional rewrite rules attached to this member.
163+ pub ( crate ) rewrite_rules : Vec < RewriteRule < ' s > > ,
164+ }
165+
166+ fn parse_rewrite_rule < ' s > ( conditions : & [ & ' s str ] , actions : & [ & ' s str ] ) -> Option < RewriteRule < ' s > > {
167+ if conditions. is_empty ( ) || actions. is_empty ( ) {
168+ return None ;
169+ }
170+
171+ let mut parsed_conditions = Vec :: with_capacity ( conditions. len ( ) ) ;
172+ for condition in conditions {
173+ let condition = condition. trim ( ) ;
174+ if condition. is_empty ( ) {
175+ return None ;
176+ }
177+ if let Some ( rest) = condition. strip_prefix ( "throws(" ) {
178+ let descriptor = rest. strip_suffix ( ')' ) ?;
179+ if descriptor. is_empty ( ) {
180+ return None ;
181+ }
182+ parsed_conditions. push ( RewriteCondition :: Throws ( descriptor) ) ;
183+ } else {
184+ parsed_conditions. push ( RewriteCondition :: Unknown ( condition) ) ;
185+ }
186+ }
187+
188+ let mut parsed_actions = Vec :: with_capacity ( actions. len ( ) ) ;
189+ for action in actions {
190+ let action = action. trim ( ) ;
191+ if action. is_empty ( ) {
192+ return None ;
193+ }
194+ if let Some ( rest) = action. strip_prefix ( "removeInnerFrames(" ) {
195+ let count_str = rest. strip_suffix ( ')' ) ?;
196+ let count = count_str. parse ( ) . ok ( ) ?;
197+ parsed_actions. push ( RewriteAction :: RemoveInnerFrames ( count) ) ;
198+ } else {
199+ parsed_actions. push ( RewriteAction :: Unknown ( action) ) ;
200+ }
201+ }
202+
203+ Some ( RewriteRule {
204+ conditions : parsed_conditions,
205+ actions : parsed_actions,
206+ } )
139207}
140208
141209/// A collection of member records for a particular class
@@ -196,6 +264,7 @@ impl<'s> ParsedProguardMapping<'s> {
196264 // Consume R8 headers attached to this class.
197265 while let Some ( ProguardRecord :: R8Header ( r8_header) ) = records. peek ( ) {
198266 match r8_header {
267+ R8Header :: RewriteFrame { .. } => { }
199268 R8Header :: SourceFile { file_name } => {
200269 current_class. source_file = Some ( file_name)
201270 }
@@ -251,6 +320,7 @@ impl<'s> ParsedProguardMapping<'s> {
251320 . entry ( ( current_class_obfuscated, ObfuscatedName ( obfuscated) ) )
252321 . or_default ( ) ;
253322
323+ let mut rewrite_rules: Vec < RewriteRule < ' s > > = Vec :: new ( ) ;
254324 let method = MethodKey {
255325 // Save the receiver name, keeping track of whether it's the current class
256326 // (i.e. the one to which this member record belongs) or another class.
@@ -276,6 +346,14 @@ impl<'s> ParsedProguardMapping<'s> {
276346 R8Header :: Outline => {
277347 method_info. is_outline = true ;
278348 }
349+ R8Header :: RewriteFrame {
350+ conditions,
351+ actions,
352+ } => {
353+ if let Some ( rule) = parse_rewrite_rule ( conditions, actions) {
354+ rewrite_rules. push ( rule) ;
355+ }
356+ }
279357 R8Header :: OutlineCallsite {
280358 positions,
281359 outline : _,
@@ -302,6 +380,7 @@ impl<'s> ParsedProguardMapping<'s> {
302380 original_startline,
303381 original_endline,
304382 outline_callsite_positions,
383+ rewrite_rules,
305384 } ;
306385
307386 members. all . push ( member. clone ( ) ) ;
0 commit comments