use std::fs::{canonicalize, read_to_string};
use std::path::{Path, PathBuf};
use std::time::Instant;
use colored::*;
use rayon::iter::{IntoParallelRefIterator as _, ParallelIterator as _};
use tracing_subscriber::{
prelude::__tracing_subscriber_SubscriberExt as _, util::SubscriberInitExt, EnvFilter,
};
use liboptic_edid::{error::EdidError, Edid};
static mut PANICKED: u32 = 0_u32;
const PATH: &str = "/home/barrett/Downloads/linuxhw_edid_repo";
const LIST_ERRS: bool = false;
fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt()
.compact()
.with_max_level(tracing::Level::WARN)
.init();
println!("parsing all edids... (this may take a sec)");
let parsed_edids = parse_all();
let passed = format!(
"{}{}",
parsed_edids
.iter()
.flat_map(|pe| &pe.parsed_edid)
.count()
.to_string()
.bright_green(),
" passed".green()
);
let failed = format!(
"{}{}",
parsed_edids
.iter()
.filter(|pe| pe.parsed_edid.is_err())
.count()
.to_string()
.bright_red(),
" failed".red()
);
let panicked = format!(
"{}{}",
unsafe { PANICKED }.to_string().black().on_red(),
" panicked".black().on_red()
);
if LIST_ERRS {
for edid in parsed_edids {
if let Err(e) = edid.parsed_edid {
println!("{} {}\n", "[ERR]".black().on_red(), e.to_string().red());
}
}
}
println!("({passed}/{failed}/{panicked})");
Ok(())
}
fn parse_all() -> Vec<Entry> {
let path = canonicalize(PathBuf::from(PATH)).expect("canonicalize");
println!("checking at path `{}`", path.display());
let timer = Instant::now();
let paths = [path.join("Digital"), path.join("Analog")]
.par_iter()
.flat_map(|p| {
let inner: Vec<_> = jwalk::WalkDir::new(p)
.into_iter()
.flat_map(|entry| {
if let Ok(entry) = entry {
Some(entry.path())
} else {
None
}
})
.map(run) .collect();
inner
})
.collect::<Vec<Option<_>>>()
.into_iter()
.flatten()
.collect::<Vec<_>>();
println!(
"{}\n",
format!(
"Completed in {:.2} seconds.",
Instant::now().duration_since(timer).as_secs_f32()
)
.white()
.on_green()
);
paths
}
struct Entry {
parsed_edid: Result<Edid, EdidError>,
raw_edid: Vec<u8>,
path: PathBuf,
}
fn run<P: AsRef<Path>>(entry_path: P) -> Option<Entry> {
let entry_path = entry_path.as_ref();
if let Some(edid) = edid_by_filename(entry_path) {
return Some(Entry {
parsed_edid: Edid::new(edid.clone()),
raw_edid: edid,
path: entry_path.into(),
});
}
None
}
#[tracing::instrument]
pub(crate) fn edid_by_filename(path: &Path) -> Option<Vec<u8>> {
let path = PathBuf::from(path);
let s = read_to_string(&path).ok()?;
if !s.contains("edid-decode (hex):") {
return None;
}
let v: Vec<&str> = s.split("----------------").collect();
let s = v.first()?.trim();
let s = s.replace("edid-decode (hex):", "");
let s = s.replace([' ', '\n', '\r'], "");
let hr = hex::decode(&s).inspect_err(|e| {
tracing::error!("couldn't turn into hex! (err: {e}) for the following hex:");
eprintln!("{s}")
});
hr.ok()
}