cargo_difftests/
analysis_data.rs

1/*
2 *        Copyright (c) 2023-2024 Dinu Blanovschi
3 *
4 *    Licensed under the Apache License, Version 2.0 (the "License");
5 *    you may not use this file except in compliance with the License.
6 *    You may obtain a copy of the License at
7 *
8 *        https://www.apache.org/licenses/LICENSE-2.0
9 *
10 *    Unless required by applicable law or agreed to in writing, software
11 *    distributed under the License is distributed on an "AS IS" BASIS,
12 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 *    See the License for the specific language governing permissions and
14 *    limitations under the License.
15 */
16
17//! Profiling data, deserialized from `llvm-cov export` JSON.
18
19use std::collections::HashMap;
20use std::path::PathBuf;
21
22#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
23pub struct CoverageData {
24    pub data: Vec<CoverageMapping>,
25    #[serde(rename = "type")]
26    pub kind: String,
27    pub version: String,
28}
29
30#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
31pub struct CoverageMapping {
32    pub functions: Vec<CoverageFunction>,
33    pub files: Vec<CoverageFile>,
34    pub totals: BinarySummary,
35}
36
37#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
38pub struct CoverageFile {
39    pub filename: PathBuf,
40    pub branches: Vec<CoverageBranch>,
41    pub segments: Vec<CoverageFileSegment>,
42    pub expansions: Vec<Expansion>,
43    pub summary: FileSummary,
44}
45
46#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, Copy)]
47#[serde(transparent)]
48pub struct CoverageBranchSerDe([usize; 9]);
49
50#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, Copy)]
51#[serde(from = "CoverageBranchSerDe", into = "CoverageBranchSerDe")]
52pub struct CoverageBranch {
53    pub l1: usize,
54    pub l2: usize,
55    pub c1: usize,
56    pub c2: usize,
57
58    pub execution_count: usize,
59    pub false_execution_count: usize,
60    pub file_id: usize,
61    pub expanded_file_id: usize,
62    pub region_kind: usize,
63}
64
65impl From<CoverageBranchSerDe> for CoverageBranch {
66    fn from(
67        CoverageBranchSerDe(
68            [l1, l2, c1, c2, execution_count, false_execution_count, file_id, expanded_file_id, region_kind],
69        ): CoverageBranchSerDe,
70    ) -> Self {
71        Self {
72            l1,
73            l2,
74            c1,
75            c2,
76            execution_count,
77            false_execution_count,
78            file_id,
79            expanded_file_id,
80            region_kind,
81        }
82    }
83}
84
85impl From<CoverageBranch> for CoverageBranchSerDe {
86    fn from(
87        CoverageBranch {
88            l1,
89            l2,
90            c1,
91            c2,
92            execution_count,
93            false_execution_count,
94            file_id,
95            expanded_file_id,
96            region_kind,
97        }: CoverageBranch,
98    ) -> Self {
99        Self(
100            [l1, l2, c1, c2, execution_count, false_execution_count, file_id, expanded_file_id, region_kind],
101        )
102    }
103}
104
105#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, Copy)]
106struct CoverageFileSegmentSerDe(usize, usize, usize, bool, bool, bool);
107
108#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, Copy)]
109#[serde(from = "CoverageFileSegmentSerDe", into = "CoverageFileSegmentSerDe")]
110pub struct CoverageFileSegment {
111    pub line: usize,
112    pub col: usize,
113    pub count: usize,
114    pub has_count: bool,
115    pub is_region_entry: bool,
116    pub is_gap_region: bool,
117}
118
119impl From<CoverageFileSegmentSerDe> for CoverageFileSegment {
120    fn from(
121        CoverageFileSegmentSerDe(line, col, count, has_count, is_region_entry, is_gap_region): CoverageFileSegmentSerDe,
122    ) -> Self {
123        Self {
124            line,
125            col,
126            count,
127            has_count,
128            is_region_entry,
129            is_gap_region,
130        }
131    }
132}
133
134impl From<CoverageFileSegment> for CoverageFileSegmentSerDe {
135    fn from(
136        CoverageFileSegment {
137            line,
138            col,
139            count,
140            has_count,
141            is_region_entry,
142            is_gap_region,
143        }: CoverageFileSegment,
144    ) -> Self {
145        Self(line, col, count, has_count, is_region_entry, is_gap_region)
146    }
147}
148
149#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
150pub struct Expansion {
151    pub branches: Vec<CoverageBranch>,
152    pub filenames: Vec<PathBuf>,
153    pub source_region: Region,
154    pub target_regions: Vec<Region>,
155}
156
157#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
158#[serde(transparent)]
159pub struct TargetRegion {
160    pub region: HashMap<String, serde_json::Value>,
161}
162
163#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, Copy)]
164pub struct FileSummary {
165    pub lines: GenericSummary,
166    pub functions: GenericSummary,
167    pub instantiations: GenericSummary,
168    pub regions: RegionsSummary,
169    pub branches: BranchesSummary,
170}
171
172#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, Copy)]
173pub struct BranchesSummary {
174    #[serde(flatten)]
175    pub generic: GenericSummary,
176    pub notcovered: usize,
177}
178
179#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, Copy)]
180pub struct RegionsSummary {
181    #[serde(flatten)]
182    pub generic: GenericSummary,
183    pub notcovered: usize,
184}
185
186#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, Copy)]
187pub struct GenericSummary {
188    pub count: usize,
189    pub covered: usize,
190    pub percent: f64,
191}
192
193#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
194pub struct CoverageFunction {
195    pub branches: Vec<CoverageBranch>,
196    pub filenames: Vec<PathBuf>,
197    #[serde(deserialize_with = "deserialize_function_name")]
198    pub name: String,
199    pub count: usize,
200    pub regions: Vec<Region>,
201}
202
203#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, Copy)]
204#[serde(transparent)]
205struct CoverageFunctionRegionSerDe([usize; 8]);
206
207#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, Copy)]
208#[serde(from = "CoverageFunctionRegionSerDe", into = "CoverageFunctionRegionSerDe")]
209pub struct Region {
210    pub l1: usize,
211    pub c1: usize,
212    pub l2: usize,
213    pub c2: usize,
214
215    pub execution_count: usize,
216    pub file_id: usize,
217    pub expanded_file_id: usize,
218    pub region_kind: usize,
219}
220
221impl From<CoverageFunctionRegionSerDe> for Region {
222    fn from(
223        CoverageFunctionRegionSerDe(
224            [l1, c1, l2, c2, execution_count, file_id, expanded_file_id, region_kind],
225        ): CoverageFunctionRegionSerDe,
226    ) -> Self {
227        Self {
228            l1,
229            c1,
230            l2,
231            c2,
232            execution_count,
233            file_id,
234            expanded_file_id,
235            region_kind,
236        }
237    }
238}
239
240impl From<Region> for CoverageFunctionRegionSerDe {
241    fn from(
242        Region {
243            l1,
244            c1,
245            l2,
246            c2,
247            execution_count,
248            file_id,
249            expanded_file_id,
250            region_kind,
251        }: Region,
252    ) -> Self {
253        Self(
254            [l1, c1, l2, c2, execution_count, file_id, expanded_file_id, region_kind],
255        )
256    }
257}
258
259fn deserialize_function_name<'de, D>(deserializer: D) -> Result<String, D::Error>
260where
261    D: serde::Deserializer<'de>,
262{
263    let s = <String as serde::Deserialize>::deserialize(deserializer)?;
264    Ok(rustc_demangle::demangle(&s).to_string())
265}
266
267#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, Copy)]
268pub struct BinarySummary {
269    pub lines: GenericSummary,
270    pub functions: GenericSummary,
271    pub instantiations: GenericSummary,
272    pub regions: RegionsSummary,
273    pub branches: BranchesSummary,
274}