@@ -78,8 +78,11 @@ impl From<std::num::TryFromIntError> for SyntaxError {
7878
7979#[ derive( PartialEq ,  Eq ) ]  
8080enum  Token < ' a >  { 
81+     /// Decimal number 
8182     Number ( & ' a  str ) , 
83+     /// `;` 
8284     Semicolon , 
85+     /// `:` 
8386     Colon , 
8487    /// `i` which represents an instruction that goes into a function 
8588     In , 
@@ -175,7 +178,7 @@ pub type SourceMap = Vec<SourceElement>;
175178/// A single element in a [`SourceMap`]. 
176179/// 
177180/// Solidity reference: <https://docs.soliditylang.org/en/latest/internals/source_mappings.html#source-mappings> 
178- #[ derive( Clone ,  Debug ,   PartialEq ,  Eq ,  Hash ) ]  
181+ #[ derive( Clone ,  PartialEq ,  Eq ,  Hash ) ]  
179182pub  struct  SourceElement  { 
180183    offset :  u32 , 
181184    length :  u32 , 
@@ -184,12 +187,37 @@ pub struct SourceElement {
184187    jump_and_modifier_depth :  u32 , 
185188} 
186189
190+ impl  fmt:: Debug  for  SourceElement  { 
191+     fn  fmt ( & self ,  f :  & mut  fmt:: Formatter < ' _ > )  -> fmt:: Result  { 
192+         f. debug_struct ( "SourceElement" ) 
193+             . field ( "offset" ,  & self . offset ( ) ) 
194+             . field ( "length" ,  & self . length ( ) ) 
195+             . field ( "index" ,  & self . index_i32 ( ) ) 
196+             . field ( "jump" ,  & self . jump ( ) ) 
197+             . field ( "modifier_depth" ,  & self . modifier_depth ( ) ) 
198+             . field ( "formatted" ,  & format_args ! ( "{self}" ) ) 
199+             . finish ( ) 
200+     } 
201+ } 
202+ 
203+ impl  Default  for  SourceElement  { 
204+     fn  default ( )  -> Self  { 
205+         Self :: new ( ) 
206+     } 
207+ } 
208+ 
187209impl  SourceElement  { 
188210    /// Creates a new source element with default values. 
189-      pub  fn  new_invalid ( )  -> Self  { 
211+      pub  fn  new ( )  -> Self  { 
190212        Self  {  offset :  0 ,  length :  0 ,  index :  -1 ,  jump_and_modifier_depth :  0  } 
191213    } 
192214
215+     /// Creates a new source element with default values. 
216+      #[ deprecated = "use `new` instead" ]  
217+     pub  fn  new_invalid ( )  -> Self  { 
218+         Self :: new ( ) 
219+     } 
220+ 
193221    /// The byte-offset to the start of the range in the source file. 
194222     #[ inline]  
195223    pub  fn  offset ( & self )  -> u32  { 
@@ -295,10 +323,10 @@ impl fmt::Display for SourceElementBuilder {
295323        } 
296324
297325        if  let  Some ( s)  = self . offset  { 
298-             if  self . index  == Some ( None )  { 
326+             if  s ==  0  &&  self . index  == Some ( None )  { 
299327                f. write_str ( "-1" ) ?; 
300328            }  else  { 
301-                 s . fmt ( f ) ?; 
329+                 write ! ( f ,   "{s}" ) ?; 
302330            } 
303331        } 
304332        if  self . length . is_none ( ) 
@@ -311,10 +339,10 @@ impl fmt::Display for SourceElementBuilder {
311339        f. write_char ( ':' ) ?; 
312340
313341        if  let  Some ( s)  = self . length  { 
314-             if  self . index  == Some ( None )  { 
342+             if  s ==  0  &&  self . index  == Some ( None )  { 
315343                f. write_str ( "-1" ) ?; 
316344            }  else  { 
317-                 s . fmt ( f ) ?; 
345+                 write ! ( f ,   "{s}" ) ?; 
318346            } 
319347        } 
320348        if  self . index . is_none ( )  && self . jump . is_none ( )  && self . modifier_depth . is_none ( )  { 
@@ -324,15 +352,15 @@ impl fmt::Display for SourceElementBuilder {
324352
325353        if  let  Some ( s)  = self . index  { 
326354            let  s = s. map ( |s| s as  i64 ) . unwrap_or ( -1 ) ; 
327-             s . fmt ( f ) ?; 
355+             write ! ( f ,   "{s}" ) ?; 
328356        } 
329357        if  self . jump . is_none ( )  && self . modifier_depth . is_none ( )  { 
330358            return  Ok ( ( ) ) ; 
331359        } 
332360        f. write_char ( ':' ) ?; 
333361
334362        if  let  Some ( s)  = self . jump  { 
335-             s . fmt ( f ) ?; 
363+             write ! ( f ,   "{s}" ) ?; 
336364        } 
337365        if  self . modifier_depth . is_none ( )  { 
338366            return  Ok ( ( ) ) ; 
@@ -353,17 +381,11 @@ impl fmt::Display for SourceElementBuilder {
353381
354382impl  SourceElementBuilder  { 
355383    fn  finish ( self ,  prev :  Option < SourceElement > )  -> Result < SourceElement ,  SyntaxError >  { 
356-         let  no_prev = prev. is_none ( ) ; 
357-         let  mut  element = prev. unwrap_or_else ( SourceElement :: new_invalid) ; 
384+         let  mut  element = prev. unwrap_or_default ( ) ; 
358385        macro_rules!  get_field { 
359386            ( | $field: ident | $e: expr)  => { 
360387                if  let  Some ( $field)  = self . $field { 
361388                    $e; 
362-                 }  else if  no_prev { 
363-                     return  Err ( SyntaxError :: new( 
364-                         None , 
365-                         format!( "no previous {}" ,  stringify!( $field) ) , 
366-                     ) ) ; 
367389                } 
368390            } ; 
369391        } 
@@ -498,9 +520,9 @@ impl<'input> Parser<'input> {
498520        #[ cfg( test) ]  
499521        if  let  Some ( out)  = self . output . as_mut ( )  { 
500522            if  self . last_element . is_some ( )  { 
501-                 let  _ =  out. write_char ( ';' ) ; 
523+                 out. write_char ( ';' ) . unwrap ( ) ; 
502524            } 
503-             let  _ = out . write_str ( & builder. to_string ( ) ) ; 
525+             write ! ( out ,   "{ builder}" ) . unwrap ( ) ; 
504526        } 
505527
506528        let  element = builder. finish ( self . last_element . take ( ) ) ?; 
@@ -554,29 +576,53 @@ pub fn parse(input: &str) -> Result<SourceMap, SyntaxError> {
554576mod  tests { 
555577    use  super :: * ; 
556578
579+     fn  parse_test ( input :  & str )  { 
580+         match  parse_test_ ( input)  { 
581+             Ok ( _)  => { } 
582+             Err ( e)  => panic ! ( "{e}" ) , 
583+         } 
584+     } 
585+ 
586+     fn  parse_test_ ( input :  & str )  -> Result < SourceMap ,  SyntaxError >  { 
587+         let  mut  s = String :: new ( ) ; 
588+         let  mut  p = Parser :: new ( input) ; 
589+         p. output  = Some ( & mut  s) ; 
590+         let  sm = p. collect :: < Result < SourceMap ,  _ > > ( ) ?; 
591+         if  s != input { 
592+             return  Err ( SyntaxError :: new ( 
593+                 None , 
594+                 format ! ( "mismatched output:\n    actual: {s:?}\n  expected: {input:?}\n        sm: {sm:#?}" ) , 
595+             ) ) ; 
596+         } 
597+         Ok ( sm) 
598+     } 
599+ 
600+     #[ test]  
601+     fn  empty ( )  { 
602+         parse_test ( "" ) ; 
603+     } 
604+ 
557605    #[ test]  
558-     fn  can_parse_source_maps ( )  { 
606+     fn  source_maps ( )  { 
559607        // all source maps from the compiler output test data 
560608        let  source_maps = include_str ! ( "../../../../test-data/out-source-maps.txt" ) ; 
561609
562610        for  ( line,  s)  in  source_maps. lines ( ) . enumerate ( )  { 
563-             parse ( s) . unwrap_or_else ( |e| panic ! ( "Failed to parse line {line}: {e}" ) ) ; 
611+             let  line = line + 1 ; 
612+             parse_test_ ( s) . unwrap_or_else ( |e| panic ! ( "Failed to parse line {line}: {e}\n {s:?}" ) ) ; 
564613        } 
565614    } 
566615
567616    #[ test]  
568-     fn  can_parse_foundry_cheatcodes_sol_maps ( )  { 
617+     fn  cheatcodes ( )  { 
569618        let  s = include_str ! ( "../../../../test-data/cheatcodes.sol-sourcemap.txt" ) ; 
570-         let  mut  out = String :: new ( ) ; 
571-         let  mut  parser = Parser :: new ( s) ; 
572-         parser. output  = Some ( & mut  out) ; 
573-         let  _map = parser. collect :: < Result < SourceMap ,  _ > > ( ) . unwrap ( ) ; 
574-         assert_eq ! ( out,  s) ; 
619+         parse_test ( s) ; 
575620    } 
576621
622+     // https://github.com/foundry-rs/foundry/issues/8986 
577623    #[ test]  
578-     fn  can_parse_empty ( )  { 
579-         let  s = Parser :: new ( "" ) . collect :: < Result < SourceMap ,   _ > > ( ) . unwrap ( ) ; 
580-         assert_eq ! ( s . len ( ) ,   0 ) ; 
624+     fn  univ4_deployer ( )  { 
625+         let  s = ":::-:0;;1888:10801:91;2615:100;;;2679:3;2615:100;;;;2700:4;2615:100;;;;-1:-1:-1;2615:100:91;;;;2546:169;;;-1:-1:-1;;2546:169:91;;;;;;;;;;;2615:100;2546:169;;;2615:100;2797:101;;;;;;;;;-1:-1:-1;;2797:101:91;;;;;;;;2546:169;2721:177;;;;;;;;;;;;;;;;;;2957:101;1888:10801;2957:101;2797;2957;;;-1:-1:-1;;2957:101:91;;;;356:29:89;2957:101:91;;;;2904:154;;;-1:-1:-1;;2904:154:91;;;;;;;;;;;;-1:-1:-1;;;;;;2904:154:91;;;;;;;;4018:32;;;;;4048:2;4018:32;;;4056:74;;;-1:-1:-1;;;;;4056:74:91;;;;;;;;1888:10801;;;;;;;;;;;;;;;;" ; 
626+         parse_test ( s ) ; 
581627    } 
582628} 
0 commit comments