1use serde_derive::{
2 Deserialize,
3 Serialize,
4};
5
6pub const COV_IDENTIFIER: &str = "COV=";
7#[derive(Clone, Default, Serialize, Debug, Deserialize)]
8pub struct CoverageTrace(pub Vec<u8>);
9
10impl From<Vec<u8>> for CoverageTrace {
11 fn from(vec: Vec<u8>) -> Self {
12 CoverageTrace(vec)
13 }
14}
15
16impl AsRef<[u8]> for CoverageTrace {
17 fn as_ref(&self) -> &[u8] {
18 self.0.as_slice()
19 }
20}
21
22impl CoverageTrace {
23 pub fn as_string(&self) -> String {
24 String::from_utf8_lossy(&self.0).to_string()
25 }
26
27 pub fn parse_coverage(&self) -> Vec<u64> {
28 let coverage_str = self.as_string();
29 let mut parsed = Vec::new();
30
31 for part in coverage_str.split_whitespace() {
32 if let Some(cov) = part.strip_prefix(COV_IDENTIFIER) {
33 if let Ok(value) = cov.parse::<u64>() {
34 parsed.push(value);
35 }
36 }
37 }
38 parsed
39 }
40
41 pub fn remove_cov_from_trace(&self) -> String {
42 self.as_string()
43 .split_whitespace()
44 .filter(|&s| !s.starts_with(COV_IDENTIFIER))
45 .collect::<Vec<&str>>()
46 .join(" ")
47 }
48}
49#[cfg(test)]
50mod tests {
51 use super::*;
52
53 #[test]
54 fn test_parse_coverage_empty() {
55 let trace = CoverageTrace(vec![]);
56 assert_eq!(trace.parse_coverage(), Vec::<u64>::new());
57 }
58
59 #[test]
60 fn test_parse_coverage_with_valid_data() {
61 let data = "COV=10 COV=20 other_data COV=30".as_bytes().to_vec();
62 let trace = CoverageTrace(data);
63 assert_eq!(trace.parse_coverage(), vec![10, 20, 30]);
64 }
65
66 #[test]
67 fn test_parse_coverage_with_invalid_data() {
68 let data = "COV=10 COV=invalid COV=30".as_bytes().to_vec();
69 let trace = CoverageTrace(data);
70 assert_eq!(trace.parse_coverage(), vec![10, 30]);
71 }
72
73 #[test]
74 fn test_new_line() {
75 let data = "COV=10\nCOV=invalid\nCOV=30".as_bytes().to_vec();
76 let trace = CoverageTrace(data);
77 assert_eq!(trace.parse_coverage(), vec![10, 30]);
78 }
79
80 #[test]
81 fn test_remove_cov_from_trace() {
82 let data = "COV=10 other_data COV=20 more_data".as_bytes().to_vec();
83 let trace = CoverageTrace(data);
84 let cleaned = trace.remove_cov_from_trace();
85 assert_eq!(cleaned, "other_data more_data");
86 }
87
88 #[test]
89 fn test_yet_another_invalid() {
90 let data = "COV=10 other_data COV=20rzerze more_data"
91 .as_bytes()
92 .to_vec();
93 let trace = CoverageTrace(data);
94 let cleaned = trace.remove_cov_from_trace();
95 assert_eq!(cleaned, "other_data more_data");
96 }
97}