#[derive(PartialOrd, PartialEq, Copy, Clone)]
enum Normalization {
Basic,
}
use self::Normalization::*;
pub struct Variations {
variations: Vec<String>,
}
impl Variations {
pub fn preferred(&self) -> &str {
self.variations.last().unwrap()
}
pub fn any<F: FnMut(&str) -> bool>(&self, mut f: F) -> bool {
self.variations.iter().any(|stderr| f(stderr))
}
}
pub fn diagnostics(output: &[u8]) -> Variations {
let from_bytes = String::from_utf8_lossy(output)
.to_string()
.replace("\r\n", "\n");
let variations = [Basic].iter().map(|_| process(&from_bytes)).collect();
Variations { variations }
}
fn process(original: &str) -> String {
let mut normalized = String::new();
for line in original.lines() {
if let Some(line) = filter_map(line) {
normalized += &line;
if !normalized.ends_with("\n\n") {
normalized.push('\n');
}
}
}
trim(normalized)
}
fn filter_map(line: &str) -> Option<String> {
lazy_static::lazy_static! {
static ref CUT_OUT: Vec<&'static str> = vec![
"error: aborting due to",
"For more information about this error, try `rustc --explain",
"For more information about an error, try `rustc --explain",
"Some errors have detailed explanations:",
];
};
if CUT_OUT.iter().any(|prefix| line.trim().starts_with(prefix)) {
None
} else {
Some(line.to_owned())
}
}
pub fn trim<S: AsRef<[u8]>>(output: S) -> String {
let bytes = output.as_ref();
let mut normalized = String::from_utf8_lossy(bytes).to_string();
let len = normalized.trim_end().len();
normalized.truncate(len);
if !normalized.is_empty() {
normalized.push('\n');
}
normalized
}