rust_code_analysis/
count.rs1extern crate num_format;
2
3use num_format::{Locale, ToFormattedString};
4use std::fmt;
5use std::sync::{Arc, Mutex};
6
7use crate::node::Node;
8use crate::traits::*;
9
10pub fn count<T: ParserTrait>(parser: &T, filters: &[String]) -> (usize, usize) {
13 let filters = parser.get_filters(filters);
14 let node = parser.get_root();
15 let mut cursor = node.object().walk();
16 let mut stack = Vec::new();
17 let mut good = 0;
18 let mut total = 0;
19
20 stack.push(node);
21
22 while let Some(node) = stack.pop() {
23 total += 1;
24 if filters.any(&node) {
25 good += 1;
26 }
27 cursor.reset(node.object());
28 if cursor.goto_first_child() {
29 loop {
30 stack.push(Node::new(cursor.node()));
31 if !cursor.goto_next_sibling() {
32 break;
33 }
34 }
35 }
36 }
37 (good, total)
38}
39
40pub struct CountCfg {
43 pub filters: Vec<String>,
45 pub stats: Arc<Mutex<Count>>,
47}
48
49#[derive(Debug, Default)]
51pub struct Count {
52 pub good: usize,
54 pub total: usize,
56}
57
58impl Callback for Count {
59 type Res = std::io::Result<()>;
60 type Cfg = CountCfg;
61
62 fn call<T: ParserTrait>(cfg: Self::Cfg, parser: &T) -> Self::Res {
63 let (good, total) = count(parser, &cfg.filters);
64 let mut results = cfg.stats.lock().unwrap();
65 results.good += good;
66 results.total += total;
67 Ok(())
68 }
69}
70
71impl fmt::Display for Count {
72 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73 writeln!(
74 f,
75 "Total nodes: {}",
76 self.total.to_formatted_string(&Locale::en)
77 )?;
78 writeln!(
79 f,
80 "Found nodes: {}",
81 self.good.to_formatted_string(&Locale::en)
82 )?;
83 write!(
84 f,
85 "Percentage: {:.2}%",
86 (self.good as f64) / (self.total as f64) * 100.
87 )
88 }
89}