1mod pattern;
8mod redactions;
9#[cfg(test)]
10mod test;
11#[cfg(test)]
12mod test_redactions;
13#[cfg(test)]
14mod test_unordered_redactions;
15
16use crate::data::DataInner;
17use crate::Data;
18
19pub use pattern::NormalizeToExpected;
20pub use redactions::RedactedValue;
21pub use redactions::Redactions;
22
23pub trait Filter {
24 fn filter(&self, data: Data) -> Data;
25}
26
27pub struct FilterNewlines;
28impl Filter for FilterNewlines {
29 fn filter(&self, data: Data) -> Data {
30 let source = data.source;
31 let filters = data.filters;
32 let inner = match data.inner {
33 DataInner::Error(err) => DataInner::Error(err),
34 DataInner::Binary(bin) => DataInner::Binary(bin),
35 DataInner::Text(text) => {
36 let lines = normalize_lines(&text);
37 DataInner::Text(lines)
38 }
39 #[cfg(feature = "json")]
40 DataInner::Json(value) => {
41 let mut value = value;
42 normalize_json_string(&mut value, &normalize_lines);
43 DataInner::Json(value)
44 }
45 #[cfg(feature = "json")]
46 DataInner::JsonLines(value) => {
47 let mut value = value;
48 normalize_json_string(&mut value, &normalize_lines);
49 DataInner::JsonLines(value)
50 }
51 #[cfg(feature = "term-svg")]
52 DataInner::TermSvg(text) => {
53 let lines = normalize_lines(&text);
54 DataInner::TermSvg(lines)
55 }
56 };
57 Data {
58 inner,
59 source,
60 filters,
61 }
62 }
63}
64
65pub fn normalize_lines(data: &str) -> String {
67 normalize_lines_chars(data.chars()).collect()
68}
69
70fn normalize_lines_chars(data: impl Iterator<Item = char>) -> impl Iterator<Item = char> {
71 normalize_line_endings::normalized(data)
72}
73
74pub struct FilterPaths;
75impl Filter for FilterPaths {
76 fn filter(&self, data: Data) -> Data {
77 let source = data.source;
78 let filters = data.filters;
79 let inner = match data.inner {
80 DataInner::Error(err) => DataInner::Error(err),
81 DataInner::Binary(bin) => DataInner::Binary(bin),
82 DataInner::Text(text) => {
83 let lines = normalize_paths(&text);
84 DataInner::Text(lines)
85 }
86 #[cfg(feature = "json")]
87 DataInner::Json(value) => {
88 let mut value = value;
89 normalize_json_string(&mut value, &normalize_paths);
90 DataInner::Json(value)
91 }
92 #[cfg(feature = "json")]
93 DataInner::JsonLines(value) => {
94 let mut value = value;
95 normalize_json_string(&mut value, &normalize_paths);
96 DataInner::JsonLines(value)
97 }
98 #[cfg(feature = "term-svg")]
99 DataInner::TermSvg(text) => {
100 let lines = normalize_paths(&text);
101 DataInner::TermSvg(lines)
102 }
103 };
104 Data {
105 inner,
106 source,
107 filters,
108 }
109 }
110}
111
112pub fn normalize_paths(data: &str) -> String {
119 normalize_paths_chars(data.chars()).collect()
120}
121
122fn normalize_paths_chars(data: impl Iterator<Item = char>) -> impl Iterator<Item = char> {
123 data.map(|c| if c == '\\' { '/' } else { c })
124}
125
126struct NormalizeRedactions<'r> {
127 redactions: &'r Redactions,
128}
129impl Filter for NormalizeRedactions<'_> {
130 fn filter(&self, data: Data) -> Data {
131 let source = data.source;
132 let filters = data.filters;
133 let inner = match data.inner {
134 DataInner::Error(err) => DataInner::Error(err),
135 DataInner::Binary(bin) => DataInner::Binary(bin),
136 DataInner::Text(text) => {
137 let lines = self.redactions.redact(&text);
138 DataInner::Text(lines)
139 }
140 #[cfg(feature = "json")]
141 DataInner::Json(value) => {
142 let mut value = value;
143 normalize_json_string(&mut value, &|s| self.redactions.redact(s));
144 DataInner::Json(value)
145 }
146 #[cfg(feature = "json")]
147 DataInner::JsonLines(value) => {
148 let mut value = value;
149 normalize_json_string(&mut value, &|s| self.redactions.redact(s));
150 DataInner::JsonLines(value)
151 }
152 #[cfg(feature = "term-svg")]
153 DataInner::TermSvg(text) => {
154 let lines = self.redactions.redact(&text);
155 DataInner::TermSvg(lines)
156 }
157 };
158 Data {
159 inner,
160 source,
161 filters,
162 }
163 }
164}
165
166#[cfg(feature = "structured-data")]
167fn normalize_json_string(value: &mut serde_json::Value, op: &dyn Fn(&str) -> String) {
168 match value {
169 serde_json::Value::String(str) => {
170 *str = op(str);
171 }
172 serde_json::Value::Array(arr) => {
173 for value in arr.iter_mut() {
174 normalize_json_string(value, op);
175 }
176 }
177 serde_json::Value::Object(obj) => {
178 for (key, mut value) in std::mem::replace(obj, serde_json::Map::new()) {
179 let key = op(&key);
180 normalize_json_string(&mut value, op);
181 obj.insert(key, value);
182 }
183 }
184 _ => {}
185 }
186}