lcov/report/section/
branch.rs1use super::{Merge, MergeError, Record};
7use std::collections::BTreeMap;
8use std::iter;
9
10pub type Branches = BTreeMap<Key, Value>;
12
13#[derive(Debug, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
19pub struct Key {
20 pub line: u32,
22 pub block: u32,
24 pub branch: u32,
26}
27
28#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
34pub struct Value {
35 pub taken: Option<u64>,
37}
38
39impl Merge for Value {
40 fn merge(&mut self, other: Self) -> Result<(), MergeError> {
41 self.merge_lossy(other);
42 Ok(())
43 }
44
45 fn merge_lossy(&mut self, other: Self) {
46 if let Value { taken: Some(taken) } = other {
47 self.taken = Some(self.taken.unwrap_or(0) + taken);
48 }
49 }
50}
51
52pub(crate) fn into_records(branches: Branches) -> Box<dyn Iterator<Item = Record>> {
53 if branches.is_empty() {
54 return Box::new(iter::empty());
55 }
56
57 let found = branches.len() as u32;
58
59 enum Branch {
60 Data((Key, Value)),
61 Found,
62 Hit(u32),
63 }
64 let iter = branches
65 .into_iter()
66 .map(Branch::Data)
67 .chain(iter::once(Branch::Found))
68 .chain(iter::once(Branch::Hit(0)))
69 .scan(0, |hit_count, mut rec| {
70 match rec {
71 Branch::Data((_, ref data)) => {
72 if data.taken.unwrap_or(0) > 0 {
73 *hit_count += 1
74 }
75 }
76 Branch::Found => {}
77 Branch::Hit(ref mut hit) => *hit = *hit_count,
78 }
79 Some(rec)
80 })
81 .map(move |rec| match rec {
82 Branch::Data((key, data)) => Record::BranchData {
83 line: key.line,
84 block: key.block,
85 branch: key.branch,
86 taken: data.taken,
87 },
88 Branch::Found => Record::BranchesFound { found },
89 Branch::Hit(hit) => Record::BranchesHit { hit },
90 });
91
92 Box::new(iter)
93}