diff --git a/libcasr/src/stacktrace.rs b/libcasr/src/stacktrace.rs index 633d838a..14e3ccdf 100644 --- a/libcasr/src/stacktrace.rs +++ b/libcasr/src/stacktrace.rs @@ -287,35 +287,23 @@ impl Filter for Stacktrace { self.drain(pos + 1..); } - // Find repeating intervals in stacktrace - // We need to create an element that will not be equal to others - let mut intervals = get_interval_repetitions(self); - intervals.sort_by(|x, y| x.0.cmp(&y.0)); - let ilen = intervals.len(); - let mut cur = (0, ilen); - let mut intervals = intervals.into_iter(); - - // Remove repeating intervals and trusted functions from stack trace + // Remove trusted functions from stack trace *self = std::mem::take(self) .into_iter() - .enumerate() - .filter(|(idx, _)| { - if *idx < cur.0 { - true - } else if cur.1 != ilen && *idx < cur.1 + 1 { - false - } else { - if let Some(interval) = intervals.next() { - cur = interval; - } - true - } - }) - .map(|(_, entry)| entry) .filter(|entry| (entry.function.is_empty() || !rfunction.is_match(&entry.function))) .filter(|entry| (entry.module.is_empty() || !rfile.is_match(&entry.module))) .filter(|entry| (entry.debug.file.is_empty() || !rfile.is_match(&entry.debug.file))) .collect(); + // Find repeating intervals in stacktrace + let mut vec = get_interval_repetitions(self); + while vec.iter().any(|el| !el) { + let mut keep = vec.iter(); + *self = std::mem::take(self) + .into_iter() + .filter(|_| *keep.next().unwrap()) + .collect(); + vec = get_interval_repetitions(self); + } } } @@ -327,9 +315,9 @@ impl Filter for Stacktrace { /// /// # Return value /// -/// Resulting vector with repeating intervals: (start index, end index) -/// Start and end indices are included -fn get_interval_repetitions(arr: &[T]) -> Vec<(usize, usize)> { +/// An vector of the same length as `arr`. +/// Vec\[i\] is false, if original element i is a duplicate in some loop. +fn get_interval_repetitions(arr: &[T]) -> Vec { let len = arr.len(); let mut indices = Vec::new(); indices.resize(len, true); @@ -352,22 +340,7 @@ fn get_interval_repetitions(arr: &[T]) -> Vec<(usize, usize)> { (start..len - (len - start) % i - i).for_each(|index| indices[index] = false); } } - let mut intervals = Vec::new(); - let mut start = len; - indices.iter().enumerate().for_each(|(idx, el)| { - if !*el { - if start == len { - start = idx; - } - } else if start != len { - intervals.push((start, idx - 1)); - start = len; - } - }); - if start != len { - intervals.push((start, len - 1)); - } - intervals + indices } #[cfg(test)] @@ -387,25 +360,46 @@ mod tests { .iter() .map(|x| x.chars().collect::>()) .collect::>(); - let answer = get_interval_repetitions(&tests[0]); + + fn convert_answer(indices: &[bool]) -> Vec<(usize, usize)> { + let mut intervals = Vec::new(); + let len = indices.len(); + let mut start = len; + indices.iter().enumerate().for_each(|(idx, el)| { + if !*el { + if start == len { + start = idx; + } + } else if start != len { + intervals.push((start, idx - 1)); + start = len; + } + }); + if start != len { + intervals.push((start, len - 1)); + } + intervals + } + + let answer = convert_answer(&get_interval_repetitions(&tests[0])); assert!(answer.contains(&(0, 0))); - let answer = get_interval_repetitions(&tests[1]); + let answer = convert_answer(&get_interval_repetitions(&tests[1])); assert!(answer.contains(&(0, 3))); - let answer = get_interval_repetitions(&tests[2]); + let answer = convert_answer(&get_interval_repetitions(&tests[2])); assert!(answer.contains(&(0, 4))); - let answer = get_interval_repetitions(&tests[3]); + let answer = convert_answer(&get_interval_repetitions(&tests[3])); assert!(answer.contains(&(0, 5))); assert!(answer.contains(&(11, 11))); assert!(answer.contains(&(13, 18))); - let answer = get_interval_repetitions(&tests[4]); + let answer = convert_answer(&get_interval_repetitions(&tests[4])); assert!(answer.contains(&(2, 7))); assert!(answer.contains(&(9, 9))); - let answer = get_interval_repetitions(&tests[5]); + let answer = convert_answer(&get_interval_repetitions(&tests[5])); assert!(answer.contains(&(0, 9))); } }