crap4rust/
coverage_index.rs1use std::collections::HashMap;
6
7use crate::model::{CoverageRecord, SourceFunction};
8
9pub struct CoverageIndex {
10 inner: HashMap<(String, usize), CoverageRecord>,
11}
12
13impl CoverageIndex {
14 pub fn from_records(records: Vec<CoverageRecord>) -> Self {
15 let mut inner = HashMap::new();
16 for record in records {
17 let key = (record.path_key.clone(), record.line);
18 inner
19 .entry(key)
20 .and_modify(|existing: &mut CoverageRecord| {
21 existing.covered_regions += record.covered_regions;
22 existing.total_regions += record.total_regions;
23 })
24 .or_insert(record);
25 }
26 Self { inner }
27 }
28
29 pub fn match_function(&self, function: &SourceFunction) -> Option<f64> {
30 match_function_coverage(function, &self.inner).map(|record| record.coverage_ratio())
31 }
32}
33
34pub fn match_function_coverage(
35 function: &SourceFunction,
36 coverage_index: &HashMap<(String, usize), CoverageRecord>,
37) -> Option<CoverageRecord> {
38 let matching: Vec<&CoverageRecord> = coverage_index
39 .iter()
40 .filter(|((path_key, line), _)| {
41 path_key == &function.path_key && *line >= function.line && *line <= function.end_line
42 })
43 .map(|(_, record)| record)
44 .collect();
45
46 if matching.is_empty() {
47 return None;
48 }
49
50 let covered_regions = matching.iter().map(|r| r.covered_regions).sum();
51 let total_regions = matching.iter().map(|r| r.total_regions).sum();
52
53 Some(CoverageRecord {
54 path_key: function.path_key.clone(),
55 line: function.line,
56 covered_regions,
57 total_regions,
58 })
59}