in src/parser.rs [624:680]
fn parse_jacoco_report_sourcefile<T: BufRead>(
parser: &mut Reader<T>,
buf: &mut Vec<u8>,
) -> Result<JacocoReport, ParserError> {
let mut lines: BTreeMap<u32, u64> = BTreeMap::new();
let mut branches: BTreeMap<u32, Vec<bool>> = BTreeMap::new();
loop {
match parser.read_event_into(buf) {
Ok(Event::Start(ref e)) if e.local_name().into_inner() == b"line" => {
let (mut ci, mut cb, mut mb, mut nr) = (None, None, None, None);
for a in e.attributes() {
let a = a?;
match a.key.into_inner() {
b"ci" => ci = Some(Decoder {}.decode(&a.value)?.parse::<u64>()?),
b"cb" => cb = Some(Decoder {}.decode(&a.value)?.parse::<u64>()?),
b"mb" => mb = Some(Decoder {}.decode(&a.value)?.parse::<u64>()?),
b"nr" => nr = Some(Decoder {}.decode(&a.value)?.parse::<u32>()?),
_ => (),
}
}
fn try_att<T>(opt: Option<T>, name: &str) -> Result<T, ParserError> {
opt.ok_or_else(|| {
ParserError::InvalidRecord(format!("Attribute {} not found", name))
})
}
let ci = try_att(ci, "ci")?;
let cb = try_att(cb, "cb")?;
let mb = try_att(mb, "mb")?;
let nr = try_att(nr, "nr")?;
if mb > 0 || cb > 0 {
// This line is a branch.
let mut v = vec![true; cb as usize];
v.extend(vec![false; mb as usize]);
branches.insert(nr, v);
} else {
// This line is a statement.
// JaCoCo does not feature execution counts, so we set the
// count to 0 or 1.
let hit = u64::from(ci > 0);
lines.insert(nr, hit);
}
}
Ok(Event::End(ref e)) if e.local_name().into_inner() == b"sourcefile" => {
break;
}
Err(e) => return Err(ParserError::Parse(e.to_string())),
_ => {}
}
buf.clear();
}
Ok(JacocoReport { lines, branches })
}