use std::{env::{self}, os::linux::raw, path::Path, str::FromStr}; use std::fs; pub mod headparse; // The HEAder parsing pub mod signal_data; use crate::{headparse::{Header, SignalSpec}, signal_data::SignalData}; /// Use for handling possible formats of the WFDB data #[derive(Debug, Clone, Copy, PartialEq)] enum SignalFormat { Format16 = 16, Format212 = 212, Invalid = -1, Unimpl = 0 } fn main() -> Result<(), String>{ let args: Vec = env::args().collect(); if args.len() <= 1 || args.contains(&"help".to_string()) { help(); return Ok(()); } let filepath = Path::new(&args[1]); if !filepath.is_file() { println!("Path argument provided is not a valid file"); return Ok(()); } if filepath.extension().unwrap() != "hea" { println!("File provided is not a .hea file"); return Ok(()); } // Parse the header information let header: Header; { let hea_file_result = fs::read_to_string(filepath); match hea_file_result { Ok(file_data) => { match headparse::parse_header(file_data.as_str()) { Ok(h) => {header = h} Err(e) => {return Err(e.to_string())} } } Err(e) => {return Err("error: Provided file cannot be opened".to_string())} } } let path_parent: String; { // This is cursed lol match filepath.parent() { Some(p) => { match p.to_str() { Some(str) => { path_parent = str.to_string(); } None => {path_parent = "".to_string()} } } None => {path_parent = "".to_string()} } } let parsed_signal_result = get_all_data(header, path_parent); println!("Hello, world!"); Ok(()) } fn help() { println!("Conversion of WFDB files to a more human readable format. By default to a CSV."); println!("\nUse in the format \"wfdb_corrosion (.hea filename)\"") } fn get_signal_data(spec: &SignalSpec, offset: u64, data_length: usize, raw: &Vec) -> SignalData { todo!() } fn get_all_data(header: Header, header_root: String) -> Result, String> { let signal_counts = header.signals_per_file(); for (fname, sigcount) in signal_counts { let mut full = header_root.to_owned(); // Consider refactoring these to avoid this massive amount of ownership bs full.push('/'); let fname = fname.to_owned(); full.push_str(&fname); let filepath = Path::new(&full); if !filepath.is_file() { return Err("Error: Could not open signal .dat file. Check if the header points to the right .dat file and if files are present".to_string()); } if filepath.extension().unwrap() != "dat" { println!("warn: Header file defines signal files with an extension other than .dat. Check if the header points to the right files, reading will continue but correct data is not guaranteed"); } // Time to actually do the work let signals = header.signals_in_file(fname); let format = file_signal_format_check(signals); if format == SignalFormat::Invalid { return Err("Error: Signals in single file use multiple formats. Is your header file correctly formatted?".to_string()); } if format == SignalFormat::Unimpl { println!("Warn: Signals in single file use an unimplemented format, and will be ignored"); continue; } let raw_bytes = fs::read(filepath).unwrap(); match format { SignalFormat::Format16 => { let mut buffer: u64 = 0; let mut do_append = false; let mut raw_converted: Vec = Vec::with_capacity(raw_bytes.len() / 2); for byte in raw_bytes { if do_append { buffer = (buffer & 0xFF) + (byte as u64) << 8; raw_converted.push(buffer); do_append = false; } else { buffer = byte as u64; do_append = true; } } dbg!(raw_converted); }, _ => { panic!("Somehow reached actual file and format processing with unimplemented format. Please make a bug report") } } } todo!() } fn file_signal_format_check(signals: Vec<&SignalSpec>) -> SignalFormat { let first_sig = signals[0]; let format = first_sig.format; for sig in signals { if sig.format != format { return SignalFormat::Invalid; } } return format; }