use nom::IResult;
use rustc_hash::FxHashMap;
use std::convert::TryFrom;
use std::path::PathBuf;
use crate::instrumentation_profile::types::MCDCParams;
pub mod coverage_mapping;
pub mod reporting;
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct CoverageMappingInfo {
pub cov_map: FxHashMap<u64, Vec<PathBuf>>,
pub cov_fun: Vec<FunctionRecordV3>,
pub prof_counts: Option<Vec<u64>>,
pub prof_data: Option<Vec<ProfileData>>,
}
impl CoverageMappingInfo {
pub fn get_files_from_id(&self, id: u64) -> Vec<PathBuf> {
let mut paths = vec![];
if let Some(v) = self.cov_map.get(&id) {
let mut last_absolute = None;
for path in v.iter() {
if path.is_absolute() {
if last_absolute.is_none() {
last_absolute = Some(path.clone());
}
paths.push(path.clone());
} else {
let base = last_absolute.clone().unwrap_or_default();
paths.push(base.join(path))
}
}
}
paths
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct ProfileData {
pub name_md5: u64,
pub structural_hash: u64,
pub counters_len: u32,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub enum ExprKind {
Subtract,
Add,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub enum RegionKind {
Code = 0,
Expansion = 1,
Skipped = 2,
Gap = 3,
Branch = 4,
MCDCDecision = 5,
MCDCBranch = 6,
}
impl TryFrom<u64> for RegionKind {
type Error = u64;
fn try_from(v: u64) -> Result<Self, Self::Error> {
match v {
0 => Ok(RegionKind::Code),
1 => Ok(RegionKind::Expansion),
2 => Ok(RegionKind::Skipped),
3 => Ok(RegionKind::Gap),
4 => Ok(RegionKind::Branch),
5 => Ok(RegionKind::MCDCDecision),
6 => Ok(RegionKind::MCDCBranch),
e => Err(e),
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum CounterType {
Zero,
ProfileInstrumentation,
Expression(ExprKind),
}
impl Default for CounterType {
fn default() -> Self {
Self::Zero
}
}
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct Counter {
pub kind: CounterType,
pub id: u64,
}
impl Counter {
pub fn instrumentation(id: u64) -> Self {
Self {
kind: CounterType::ProfileInstrumentation,
id,
}
}
pub fn is_expression(&self) -> bool {
matches!(self.kind, CounterType::Expression(_))
}
pub fn is_instrumentation(&self) -> bool {
self.kind == CounterType::ProfileInstrumentation
}
pub fn is_zero(&self) -> bool {
self.kind == CounterType::Zero
}
pub fn get_expr_kind(&self) -> ExprKind {
match self.kind {
CounterType::Expression(e) => e,
_ => panic!("Counter is not an expression"),
}
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct Expression {
pub kind: ExprKind,
pub lhs: Counter,
pub rhs: Counter,
}
impl Default for Expression {
fn default() -> Self {
Expression::new(Counter::default(), Counter::default())
}
}
impl Expression {
pub fn new(lhs: Counter, rhs: Counter) -> Self {
Self {
kind: ExprKind::Subtract,
lhs,
rhs,
}
}
pub fn set_kind(&mut self, kind: ExprKind) {
self.kind = kind;
}
}
impl Counter {
const ENCODING_TAG_MASK: u64 = 3;
const ENCODING_TAG_AND_EXP_REGION_BITS: u64 = 3;
const ENCODING_EXPANSION_REGION_BIT: u64 = 4;
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CounterMappingRegion {
pub kind: RegionKind,
pub count: Counter,
pub false_count: Counter,
pub file_id: usize,
pub expanded_file_id: usize,
pub loc: SourceLocation,
pub mcdc_params: Option<MCDCParams>,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SourceLocation {
pub line_start: usize,
pub column_start: usize,
pub line_end: usize,
pub column_end: usize,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct CoverageSegment {
pub line: usize,
pub col: usize,
pub count: usize,
pub has_count: bool,
pub is_region_entry: usize,
pub is_gap_region: usize,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct FunctionRecordHeader {
pub name_hash: u64,
pub data_len: u32,
pub fn_hash: u64,
pub filenames_ref: u64,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct FunctionRecordV3 {
pub header: FunctionRecordHeader,
pub regions: Vec<CounterMappingRegion>,
pub expressions: Vec<Expression>,
}
pub struct CoverageMappingRecord {
pub fn_name: String,
pub fn_hash: u64,
pub file_names: Vec<String>,
pub expressions: Vec<Expression>,
pub mapping_regions: Vec<CounterMappingRegion>,
}
pub struct CountedRegion {
pub execution_count: usize,
pub false_execution_count: usize,
pub folded: bool,
pub region: CounterMappingRegion,
}
pub struct FunctionCoverageRecord {
pub name: String,
pub filenames: Vec<String>,
pub counted_regions: Vec<CountedRegion>,
pub counted_branch_regions: Vec<CountedRegion>,
pub execution_count: usize,
}