1+ use std:: ops:: AddAssign ;
2+
13use anyhow:: { bail, Result } ;
24use prost:: Message ;
35use serde_json:: error:: Category ;
@@ -6,18 +8,21 @@ use serde_json::error::Category;
68include ! ( concat!( env!( "OUT_DIR" ) , "/objdiff.report.rs" ) ) ;
79include ! ( concat!( env!( "OUT_DIR" ) , "/objdiff.report.serde.rs" ) ) ;
810
11+ pub const REPORT_VERSION : u32 = 1 ;
12+
913impl Report {
1014 pub fn parse ( data : & [ u8 ] ) -> Result < Self > {
1115 if data. is_empty ( ) {
1216 bail ! ( std:: io:: Error :: from( std:: io:: ErrorKind :: UnexpectedEof ) ) ;
1317 }
14- if data[ 0 ] == b'{' {
18+ let report = if data[ 0 ] == b'{' {
1519 // Load as JSON
16- Self :: from_json ( data) . map_err ( anyhow :: Error :: new )
20+ Self :: from_json ( data) ?
1721 } else {
1822 // Load as binary protobuf
19- Self :: decode ( data) . map_err ( anyhow:: Error :: new)
20- }
23+ Self :: decode ( data) ?
24+ } ;
25+ Ok ( report)
2126 }
2227
2328 fn from_json ( bytes : & [ u8 ] ) -> Result < Self , serde_json:: Error > {
@@ -37,6 +42,81 @@ impl Report {
3742 }
3843 }
3944 }
45+
46+ pub fn migrate ( & mut self ) -> Result < ( ) > {
47+ if self . version == 0 {
48+ self . migrate_v0 ( ) ?;
49+ }
50+ if self . version != REPORT_VERSION {
51+ bail ! ( "Unsupported report version: {}" , self . version) ;
52+ }
53+ Ok ( ( ) )
54+ }
55+
56+ fn migrate_v0 ( & mut self ) -> Result < ( ) > {
57+ let Some ( measures) = & mut self . measures else {
58+ bail ! ( "Missing measures in report" ) ;
59+ } ;
60+ for unit in & mut self . units {
61+ let Some ( unit_measures) = & mut unit. measures else {
62+ bail ! ( "Missing measures in report unit" ) ;
63+ } ;
64+ let Some ( metadata) = & mut unit. metadata else {
65+ bail ! ( "Missing metadata in report unit" ) ;
66+ } ;
67+ if metadata. module_name . is_some ( ) || metadata. module_id . is_some ( ) {
68+ metadata. progress_categories = vec ! [ "modules" . to_string( ) ] ;
69+ } else {
70+ metadata. progress_categories = vec ! [ "dol" . to_string( ) ] ;
71+ }
72+ if metadata. complete . unwrap_or ( false ) {
73+ unit_measures. complete_code = unit_measures. total_code ;
74+ unit_measures. complete_data = unit_measures. total_data ;
75+ unit_measures. complete_code_percent = 100.0 ;
76+ unit_measures. complete_data_percent = 100.0 ;
77+ } else {
78+ unit_measures. complete_code = 0 ;
79+ unit_measures. complete_data = 0 ;
80+ unit_measures. complete_code_percent = 0.0 ;
81+ unit_measures. complete_data_percent = 0.0 ;
82+ }
83+ measures. complete_code += unit_measures. complete_code ;
84+ measures. complete_data += unit_measures. complete_data ;
85+ }
86+ measures. calc_matched_percent ( ) ;
87+ self . version = 1 ;
88+ Ok ( ( ) )
89+ }
90+
91+ pub fn calculate_progress_categories ( & mut self ) {
92+ for unit in & self . units {
93+ let Some ( metadata) = unit. metadata . as_ref ( ) else {
94+ continue ;
95+ } ;
96+ let Some ( measures) = unit. measures . as_ref ( ) else {
97+ continue ;
98+ } ;
99+ for category_id in & metadata. progress_categories {
100+ let category = match self . categories . iter_mut ( ) . find ( |c| & c. id == category_id) {
101+ Some ( category) => category,
102+ None => {
103+ self . categories . push ( ReportCategory {
104+ id : category_id. clone ( ) ,
105+ name : String :: new ( ) ,
106+ measures : Some ( Default :: default ( ) ) ,
107+ } ) ;
108+ self . categories . last_mut ( ) . unwrap ( )
109+ }
110+ } ;
111+ * category. measures . get_or_insert_with ( Default :: default) += * measures;
112+ }
113+ }
114+ for category in & mut self . categories {
115+ let measures = category. measures . get_or_insert_with ( Default :: default) ;
116+ measures. calc_fuzzy_match_percent ( ) ;
117+ measures. calc_matched_percent ( ) ;
118+ }
119+ }
40120}
41121
42122impl Measures {
@@ -66,6 +146,16 @@ impl Measures {
66146 } else {
67147 self . matched_functions as f32 / self . total_functions as f32 * 100.0
68148 } ;
149+ self . complete_code_percent = if self . total_code == 0 {
150+ 100.0
151+ } else {
152+ self . complete_code as f32 / self . total_code as f32 * 100.0
153+ } ;
154+ self . complete_data_percent = if self . total_data == 0 {
155+ 100.0
156+ } else {
157+ self . complete_data as f32 / self . total_data as f32 * 100.0
158+ } ;
69159 }
70160}
71161
@@ -75,19 +165,27 @@ impl From<&ReportItem> for ChangeItemInfo {
75165 }
76166}
77167
168+ impl AddAssign for Measures {
169+ fn add_assign ( & mut self , other : Self ) {
170+ self . fuzzy_match_percent += other. fuzzy_match_percent * other. total_code as f32 ;
171+ self . total_code += other. total_code ;
172+ self . matched_code += other. matched_code ;
173+ self . total_data += other. total_data ;
174+ self . matched_data += other. matched_data ;
175+ self . total_functions += other. total_functions ;
176+ self . matched_functions += other. matched_functions ;
177+ self . complete_code += other. complete_code ;
178+ self . complete_data += other. complete_data ;
179+ }
180+ }
181+
78182/// Allows [collect](Iterator::collect) to be used on an iterator of [Measures].
79183impl FromIterator < Measures > for Measures {
80184 fn from_iter < T > ( iter : T ) -> Self
81185 where T : IntoIterator < Item = Measures > {
82186 let mut measures = Measures :: default ( ) ;
83187 for other in iter {
84- measures. fuzzy_match_percent += other. fuzzy_match_percent * other. total_code as f32 ;
85- measures. total_code += other. total_code ;
86- measures. matched_code += other. matched_code ;
87- measures. total_data += other. total_data ;
88- measures. matched_data += other. matched_data ;
89- measures. total_functions += other. total_functions ;
90- measures. matched_functions += other. matched_functions ;
188+ measures += other;
91189 }
92190 measures. calc_fuzzy_match_percent ( ) ;
93191 measures. calc_matched_percent ( ) ;
@@ -125,8 +223,10 @@ impl From<LegacyReport> for Report {
125223 total_functions : value. total_functions ,
126224 matched_functions : value. matched_functions ,
127225 matched_functions_percent : value. matched_functions_percent ,
226+ ..Default :: default ( )
128227 } ) ,
129- units : value. units . into_iter ( ) . map ( ReportUnit :: from) . collect ( ) ,
228+ units : value. units . into_iter ( ) . map ( ReportUnit :: from) . collect :: < Vec < _ > > ( ) ,
229+ ..Default :: default ( )
130230 }
131231 }
132232}
0 commit comments