1
+ use std:: ops:: AddAssign ;
2
+
1
3
use anyhow:: { bail, Result } ;
2
4
use prost:: Message ;
3
5
use serde_json:: error:: Category ;
@@ -6,18 +8,21 @@ use serde_json::error::Category;
6
8
include ! ( concat!( env!( "OUT_DIR" ) , "/objdiff.report.rs" ) ) ;
7
9
include ! ( concat!( env!( "OUT_DIR" ) , "/objdiff.report.serde.rs" ) ) ;
8
10
11
+ pub const REPORT_VERSION : u32 = 1 ;
12
+
9
13
impl Report {
10
14
pub fn parse ( data : & [ u8 ] ) -> Result < Self > {
11
15
if data. is_empty ( ) {
12
16
bail ! ( std:: io:: Error :: from( std:: io:: ErrorKind :: UnexpectedEof ) ) ;
13
17
}
14
- if data[ 0 ] == b'{' {
18
+ let report = if data[ 0 ] == b'{' {
15
19
// Load as JSON
16
- Self :: from_json ( data) . map_err ( anyhow :: Error :: new )
20
+ Self :: from_json ( data) ?
17
21
} else {
18
22
// Load as binary protobuf
19
- Self :: decode ( data) . map_err ( anyhow:: Error :: new)
20
- }
23
+ Self :: decode ( data) ?
24
+ } ;
25
+ Ok ( report)
21
26
}
22
27
23
28
fn from_json ( bytes : & [ u8 ] ) -> Result < Self , serde_json:: Error > {
@@ -37,6 +42,81 @@ impl Report {
37
42
}
38
43
}
39
44
}
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
+ }
40
120
}
41
121
42
122
impl Measures {
@@ -66,6 +146,16 @@ impl Measures {
66
146
} else {
67
147
self . matched_functions as f32 / self . total_functions as f32 * 100.0
68
148
} ;
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
+ } ;
69
159
}
70
160
}
71
161
@@ -75,19 +165,27 @@ impl From<&ReportItem> for ChangeItemInfo {
75
165
}
76
166
}
77
167
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
+
78
182
/// Allows [collect](Iterator::collect) to be used on an iterator of [Measures].
79
183
impl FromIterator < Measures > for Measures {
80
184
fn from_iter < T > ( iter : T ) -> Self
81
185
where T : IntoIterator < Item = Measures > {
82
186
let mut measures = Measures :: default ( ) ;
83
187
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;
91
189
}
92
190
measures. calc_fuzzy_match_percent ( ) ;
93
191
measures. calc_matched_percent ( ) ;
@@ -125,8 +223,10 @@ impl From<LegacyReport> for Report {
125
223
total_functions : value. total_functions ,
126
224
matched_functions : value. matched_functions ,
127
225
matched_functions_percent : value. matched_functions_percent ,
226
+ ..Default :: default ( )
128
227
} ) ,
129
- units : value. units . into_iter ( ) . map ( ReportUnit :: from) . collect ( ) ,
228
+ units : value. units . into_iter ( ) . map ( ReportUnit :: from) . collect :: < Vec < _ > > ( ) ,
229
+ ..Default :: default ( )
130
230
}
131
231
}
132
232
}
0 commit comments