1pub mod callstack;
2pub mod frame;
3use crate::quote::MatchQuote;
4use anyhow::Result;
5use callstack::CallStack;
6use std::fmt;
7use std::fs::File;
8use std::io::Read;
9use std::iter::Iterator;
10pub struct CallStacks {
11 pub data: Vec<CallStack>,
12}
13
14impl std::fmt::Display for CallStacks {
15 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16 for k in &self.data {
17 write!(f, "{}", &k)?;
18 }
19 writeln!(f)
20 }
21}
22impl Default for CallStacks {
23 fn default() -> Self {
24 Self::new()
25 }
26}
27
28impl IntoIterator for CallStacks{
29 type Item = CallStack;
30 type IntoIter = <Vec<CallStack> as IntoIterator>::IntoIter;
31 fn into_iter(self) -> Self::IntoIter {
32 self.data.into_iter()
33 }
34}
35impl CallStacks {
36 pub fn iter(&self) -> std::slice::Iter<'_, CallStack> {
37 self.data.iter()
38 }
39 pub fn from_file(
40 s: &str,
41 starts: &[&dyn MatchQuote],
42 ends: &[&dyn MatchQuote],
43 ) -> Result<Self> {
44 let mut file = File::open(s)?;
45 let mut content = String::new();
46 let size = file.read_to_string(&mut content)?;
47 if size == 0 {
48 return Ok(CallStacks::default());
49 }
50
51 Ok(Self::from_string(&content, starts, ends))
52 }
53 pub fn new() -> Self {
54 CallStacks { data: vec![] }
55 }
56
57 pub fn push(&mut self, cs: CallStack) {
58 self.data.push(cs);
59 }
60 pub fn from_string(s: &str, starts: &[&dyn MatchQuote], ends: &[&dyn MatchQuote]) -> Self {
61 let mut css = CallStacks::new();
62 let mut cs = Some(CallStack::new()); let mut in_frames = false;
64 for line in s.lines() {
65 if starts.iter().any(|s| s.match_quote(line)) && !in_frames {
66 in_frames = true;
68 cs = Some(CallStack::new());
69
70 continue;
71 }
72 if ends.iter().any(|s| s.match_quote(line)) && in_frames {
73 css.push(cs.take().unwrap());
75 in_frames = false;
76 continue;
77 }
78
79 if !line.trim().is_empty() && in_frames {
80 cs.as_mut().unwrap().append(line.trim().to_string());
81 }
82 }
83 css
84 }
85 pub fn len(&self) -> usize {
86 self.data.len()
87 }
88 pub fn is_empty(&self) -> bool {
89 self.data.is_empty()
90 }
91 pub fn has(&self, cs: &CallStack) -> bool {
92 self.data.iter().any(|e| e == cs)
93 }
94}
95
96#[cfg(test)]
97mod test;