diff --git a/src/downloader.rs b/src/downloader.rs index e9f1cfd..69dc52b 100644 --- a/src/downloader.rs +++ b/src/downloader.rs @@ -10,6 +10,8 @@ use indicatif::{ProgressBar, ProgressState, ProgressStyle}; use reqwest::{self, Client}; use std::cmp; +use crate::get_mut_ref; + pub enum DualWriter { File(File), Buffer(Vec), @@ -38,14 +40,14 @@ impl DualWriter { let mut buf = String::new(); // Well this is safe since I consume the file anyways - let ptr = &file as *const File as *mut File; - let file = unsafe { &mut *ptr }; + let file = unsafe { get_mut_ref(&file) }; file.read_to_string(&mut buf) .or(Err("Failed to read file".to_owned()))?; buf } }) } + pub fn new(file_name: Option<&str>) -> Result { Ok(if let Some(file_name) = file_name { Self::File(File::create(&file_name)?) @@ -59,7 +61,7 @@ pub async fn download_with_progress( link: &str, file_name: Option<&str>, ) -> Result { - let mut dw = DualWriter::new(file_name).or(Err("Failed to create file".to_owned()))?; + let mut dual_writer = DualWriter::new(file_name).or(Err("Failed to create file".to_owned()))?; let client = Client::builder() .gzip(true) @@ -71,14 +73,14 @@ pub async fn download_with_progress( .send() .await .or(Err("Failed to connect server".to_owned()))?; - let content_length = if let Some(s) = resp.content_length() { - s + let content_length = if let Some(got_content_length) = resp.content_length() { + got_content_length } else { panic!("Could not retrive content length from server. {:?}", &resp); }; - let pb = ProgressBar::new(content_length); - pb.set_style(ProgressStyle::with_template("{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})").unwrap() + let progress_bar = ProgressBar::new(content_length); + progress_bar.set_style(ProgressStyle::with_template("{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})").unwrap() .with_key("eta", |state: &ProgressState, w: &mut dyn fmt::Write| write!(w, "{:.1}s", state.eta().as_secs_f64()).unwrap()) .progress_chars("#>-")); @@ -88,11 +90,12 @@ pub async fn download_with_progress( while let Some(item) = stream.next().await { let bytes = item.unwrap(); downloaded = cmp::min(downloaded + (bytes.len() as u64), content_length); - dw.write(bytes) + dual_writer + .write(bytes) .or(Err("Failed to write to file".to_owned()))?; - pb.set_position(downloaded); + progress_bar.set_position(downloaded); } - Ok(dw) + Ok(dual_writer) } diff --git a/src/lib.rs b/src/lib.rs index 6cf0b33..3e0ea2d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,3 +63,13 @@ impl<'a> Readline<'a> { buffer } } + +/** + * I know that this isn't considered true rusty code, but the places it's used in is + * safe. For this I'll leave the funciton as unsafe, so to better see it's uses. + * This solution makes the uses BLAZINGLY FAST which moreover is the most rusty you can get. + */ +pub unsafe fn get_mut_ref(reference: &T) -> &mut T { + let ptr = reference as *const T as *mut T; + &mut *ptr +} diff --git a/src/main.rs b/src/main.rs index 975f76f..090cbfb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ use std::process::Command; use std::rc::Rc; use colored::Colorize; -use iptvnator::{download_with_progress, setup, M3u8, Parser, Readline}; +use iptvnator::{download_with_progress, get_mut_ref, setup, M3u8, Parser, Readline}; #[tokio::main] async fn main() { @@ -52,7 +52,7 @@ async fn main() { } search_result = Some(Rc::new(parser.find(search))); - if search_result.as_ref().unwrap().len() == 0 { + if search_result.as_ref().unwrap().is_empty() { println!("Nothing found"); continue; } @@ -95,8 +95,8 @@ async fn main() { // Downloadmode "d" => { let to_download = - ask_which_to_download(&mut readline, search_result.as_ref().unwrap().clone()); - download_m3u8(to_download).await; + ask_which_to_download(&mut readline, &search_result.as_ref().unwrap()); + download_m3u8(&to_download).await; } _ => {} } @@ -104,8 +104,8 @@ async fn main() { let choosen = user_wish.parse::(); match choosen { Ok(k) => { - let search_result = search_result.as_ref().unwrap().clone(); - stream(&(search_result[k - 1]), mpv_fs); + let search_result = search_result.as_ref().unwrap(); + stream(search_result[k - 1], mpv_fs); parser.save_watched(); } Err(e) => println!("Have to be a valid number! {:?}", e), @@ -115,7 +115,7 @@ async fn main() { fn ask_which_to_download<'a>( readline: &mut Readline, - search_result: Rc>, + search_result: &Rc>, ) -> Rc> { let selections = loop { // Ask for userinput @@ -155,17 +155,7 @@ fn ask_which_to_download<'a>( ) } -/* - * I know that this is also frowned upon, but it is perfectly safe right here, - * even though the borrowchecker complains - */ -async fn refresh(parser: &Parser) { - let ptr = parser as *const Parser as *mut Parser; - let p = unsafe { &mut *ptr }; - p.forcefully_update().await; -} - -async fn download_m3u8(files_to_download: Rc>) { +async fn download_m3u8(files_to_download: &Vec<&M3u8>) { for m3u8 in files_to_download.iter() { let file_ending_place = m3u8.link.rfind(".").unwrap(); let potential_file_ending = &m3u8.link[file_ending_place..]; @@ -183,14 +173,13 @@ async fn download_m3u8(files_to_download: Rc>) { } /** - * This function uses unsafe code to change an atribute, and while I know that this is not - * how youre supposed to do things, it's perfectly safe in this context and also the most efficient way. + * I know that this is not how youre supposed to do things, but it's perfectly safe + * in this context and also the most efficient way. * With other words, it's BLAZINGLY FAST */ fn stream(m3u8item: &M3u8, launch_in_fullscreen: bool) { - let ptr = m3u8item as *const M3u8 as *mut M3u8; - let mut item = unsafe { &mut *ptr }; - item.watched = true; + let mut m3u8item = unsafe { get_mut_ref(m3u8item) }; + m3u8item.watched = true; let mut args: Vec<&str> = vec![&m3u8item.link]; if launch_in_fullscreen { args.push("--fs"); @@ -201,3 +190,11 @@ fn stream(m3u8item: &M3u8, launch_in_fullscreen: bool) { .output() .expect("Could not listen for output"); } + +/* + * I know that this is also frowned upon, but it is perfectly safe right here, + * even though the borrowchecker complains + */ +async fn refresh(parser: &Parser) { + unsafe { get_mut_ref(parser) }.forcefully_update().await; +}