0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-11 06:37:12 -04:00
deno/cli/tools/coverage/range_tree.rs
Nathan Whitaker ee4c14a550
chore: update to rust 1.85 (#28236)
Updates to use rust 1.85. Doesn't move to the 2024 edition, as that's a
fair bit more involved.

A nice side benefit is that the new rustc version seems to lead to a
slight reduction in binary size (at least on mac):

```
    FILE SIZE   
 -------------- 
  +4.3%  +102Ki    __DATA_CONST,__const
  [NEW] +69.3Ki    __TEXT,__literals
  [NEW] +68.5Ki    Rebase Info
  +5.0% +39.9Ki    __TEXT,__unwind_info
   +57% +8.85Ki    [__TEXT]
  [NEW] +8.59Ki    Lazy Binding Info
  [NEW] +5.16Ki    __TEXT,__stub_helper
  [NEW] +3.58Ki    Export Info
  [NEW] +3.42Ki    __DATA,__la_symbol_ptr
  -0.1%    -726    [12 Others]
 -21.4% -3.10Ki    [__DATA_CONST]
 -95.8% -3.39Ki    __DATA_CONST,__got
 -20.9% -3.43Ki    [__DATA]
  -0.5% -4.52Ki    Code Signature
 -100.0% -11.6Ki    [__LINKEDIT]
  -1.0% -43.5Ki    Symbol Table
  -1.6% -44.0Ki    __TEXT,__gcc_except_tab
  -0.2% -48.1Ki    __TEXT,__const
  -3.3% -78.6Ki    __TEXT,__eh_frame
  -0.7%  -320Ki    __TEXT,__text
  -1.5%  -334Ki    String Table
  -0.5%  -586Ki    TOTAL
```
2025-02-25 08:50:01 -08:00

207 lines
5.7 KiB
Rust

// Copyright 2018-2025 the Deno authors. MIT license.
//
// Forked from https://github.com/demurgos/v8-coverage/tree/d0ca18da8740198681e0bc68971b0a6cdb11db3e/rust
// Copyright 2021 Charles Samborski. All rights reserved. MIT license.
use std::iter::Peekable;
use typed_arena::Arena;
use crate::cdp;
pub struct RangeTreeArena<'a>(Arena<RangeTree<'a>>);
impl<'a> RangeTreeArena<'a> {
#[cfg(test)]
pub fn new() -> Self {
RangeTreeArena(Arena::new())
}
pub fn with_capacity(n: usize) -> Self {
RangeTreeArena(Arena::with_capacity(n))
}
#[allow(clippy::mut_from_ref)]
pub fn alloc(&'a self, value: RangeTree<'a>) -> &'a mut RangeTree<'a> {
self.0.alloc(value)
}
}
#[derive(Eq, PartialEq, Debug)]
pub struct RangeTree<'a> {
pub start: usize,
pub end: usize,
pub delta: i64,
pub children: Vec<&'a mut RangeTree<'a>>,
}
impl RangeTree<'_> {
pub fn new<'a>(
start: usize,
end: usize,
delta: i64,
children: Vec<&'a mut RangeTree<'a>>,
) -> RangeTree<'a> {
RangeTree {
start,
end,
delta,
children,
}
}
pub fn split<'a>(
rta: &'a RangeTreeArena<'a>,
tree: &'a mut RangeTree<'a>,
value: usize,
) -> (&'a mut RangeTree<'a>, &'a mut RangeTree<'a>) {
let mut left_children: Vec<&'a mut RangeTree<'a>> = Vec::new();
let mut right_children: Vec<&'a mut RangeTree<'a>> = Vec::new();
for child in tree.children.iter_mut() {
if child.end <= value {
left_children.push(child);
} else if value <= child.start {
right_children.push(child);
} else {
let (left_child, right_child) = Self::split(rta, child, value);
left_children.push(left_child);
right_children.push(right_child);
}
}
let left = RangeTree::new(tree.start, value, tree.delta, left_children);
let right = RangeTree::new(value, tree.end, tree.delta, right_children);
(rta.alloc(left), rta.alloc(right))
}
pub fn normalize<'a>(tree: &'a mut RangeTree<'a>) -> &'a mut RangeTree<'a> {
tree.children = {
let mut children: Vec<&'a mut RangeTree<'a>> = Vec::new();
let mut chain: Vec<&'a mut RangeTree<'a>> = Vec::new();
for child in tree.children.drain(..) {
let is_chain_end: bool =
match chain.last().map(|tree| (tree.delta, tree.end)) {
Some((delta, chain_end)) => {
(delta, chain_end) != (child.delta, child.start)
}
None => false,
};
if is_chain_end {
let mut chain_iter = chain.drain(..);
let head: &'a mut RangeTree<'a> = chain_iter.next().unwrap();
for tree in chain_iter {
head.end = tree.end;
for sub_child in tree.children.drain(..) {
sub_child.delta += tree.delta - head.delta;
head.children.push(sub_child);
}
}
children.push(RangeTree::normalize(head));
}
chain.push(child)
}
if !chain.is_empty() {
let mut chain_iter = chain.drain(..);
let head: &'a mut RangeTree<'a> = chain_iter.next().unwrap();
for tree in chain_iter {
head.end = tree.end;
for sub_child in tree.children.drain(..) {
sub_child.delta += tree.delta - head.delta;
head.children.push(sub_child);
}
}
children.push(RangeTree::normalize(head));
}
if children.len() == 1
&& children[0].start == tree.start
&& children[0].end == tree.end
{
let normalized = children.remove(0);
normalized.delta += tree.delta;
return normalized;
}
children
};
tree
}
pub fn to_ranges(&self) -> Vec<cdp::CoverageRange> {
let mut ranges: Vec<cdp::CoverageRange> = Vec::new();
let mut stack: Vec<(&RangeTree, i64)> = vec![(self, 0)];
while let Some((cur, parent_count)) = stack.pop() {
let count: i64 = parent_count + cur.delta;
ranges.push(cdp::CoverageRange {
start_char_offset: cur.start,
end_char_offset: cur.end,
count,
});
for child in cur.children.iter().rev() {
stack.push((child, count))
}
}
ranges
}
pub fn from_sorted_ranges<'a>(
rta: &'a RangeTreeArena<'a>,
ranges: &[cdp::CoverageRange],
) -> Option<&'a mut RangeTree<'a>> {
Self::from_sorted_ranges_inner(
rta,
&mut ranges.iter().peekable(),
usize::MAX,
0,
)
}
fn from_sorted_ranges_inner<'a, 'b, 'c: 'b>(
rta: &'a RangeTreeArena<'a>,
ranges: &'b mut Peekable<impl Iterator<Item = &'c cdp::CoverageRange>>,
parent_end: usize,
parent_count: i64,
) -> Option<&'a mut RangeTree<'a>> {
let has_range: bool = match ranges.peek() {
None => false,
Some(range) => range.start_char_offset < parent_end,
};
if !has_range {
return None;
}
let range = ranges.next().unwrap();
let start: usize = range.start_char_offset;
let end: usize = range.end_char_offset;
let count: i64 = range.count;
let delta: i64 = count - parent_count;
let mut children: Vec<&mut RangeTree> = Vec::new();
while let Some(child) =
Self::from_sorted_ranges_inner(rta, ranges, end, count)
{
children.push(child);
}
Some(rta.alloc(RangeTree::new(start, end, delta, children)))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn from_sorted_ranges_empty() {
let rta = RangeTreeArena::new();
let inputs: Vec<cdp::CoverageRange> = vec![cdp::CoverageRange {
start_char_offset: 0,
end_char_offset: 9,
count: 1,
}];
let actual: Option<&mut RangeTree> =
RangeTree::from_sorted_ranges(&rta, &inputs);
let expected: Option<&mut RangeTree> =
Some(rta.alloc(RangeTree::new(0, 9, 1, Vec::new())));
assert_eq!(actual, expected);
}
}