use std::{fmt, str::FromStr}; use crate::project_root; pub struct TestFiles { files: Vec, } impl Default for TestFiles { fn default() -> Self { Self::new() } } impl TestFiles { /// # Panics /// Fails to read file pub fn new() -> Self { let root = project_root(); let files = std::fs::read_to_string(root.join("./tasks/libs.txt")) .unwrap() .lines() .map(|file| TestFile::new(file).unwrap()) .collect::>(); Self { files } } pub fn files(&self) -> &Vec { &self.files } } pub struct TestFile { pub url: String, pub file_name: String, pub source_text: String, } impl TestFile { /// # Errors pub fn new(url: &str) -> Result { let (file_name, source_text) = Self::get_source_text(url)?; Ok(Self { url: url.to_string(), file_name, source_text }) } /// # Errors /// # Panics pub fn get_source_text(lib: &str) -> Result<(String, String), String> { let url = url::Url::from_str(lib).map_err(err_to_string)?; let segments = url.path_segments().ok_or_else(|| "lib url has no segments".to_string())?; let filename = segments.last().ok_or_else(|| "lib url has no segments".to_string())?; let file = project_root().join("target").join(filename); if let Ok(code) = std::fs::read_to_string(&file) { println!("[{filename}] - using [{}]", file.display()); Ok((filename.to_string(), code)) } else { println!("[{filename}] - Downloading [{lib}] to [{}]", file.display()); match ureq::get(lib).call() { Ok(response) => { let mut reader = response.into_reader(); let _drop = std::fs::remove_file(&file); let mut writer = std::fs::File::create(&file).map_err(err_to_string)?; let _drop = std::io::copy(&mut reader, &mut writer); std::fs::read_to_string(&file) .map_err(err_to_string) .map(|code| (filename.to_string(), code)) } Err(e) => Err(format!("{e:?}")), } } } } fn err_to_string(e: E) -> String { format!("{e:?}") }