diff options
author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-07-15 06:53:07 +0200 |
---|---|---|
committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-07-15 06:53:07 +0200 |
commit | 3c11d068e438da22375a9d0af9abb81c738ebcbb (patch) | |
tree | fbcf0814dac311fbd6c33f23315d57b7546e5737 | |
parent | refactor(crates/yt): Use the new storage layer (diff) | |
download | yt-3c11d068e438da22375a9d0af9abb81c738ebcbb.zip |
refactor(crates/yt/download/progress_hook): Use `json_{get,cast}` and owu-colors
-rw-r--r-- | crates/yt/src/download/progress_hook.rs | 141 |
1 files changed, 49 insertions, 92 deletions
diff --git a/crates/yt/src/download/progress_hook.rs b/crates/yt/src/download/progress_hook.rs index 99d1a74..e5605fd 100644 --- a/crates/yt/src/download/progress_hook.rs +++ b/crates/yt/src/download/progress_hook.rs @@ -23,6 +23,29 @@ use crate::{ shared::bytes::Bytes, }; +macro_rules! json_get_default { + ($value:expr, $name:literal, $convert:ident, $default:expr) => { + $value.get($name).map_or($default, |v| { + if v == &serde_json::Value::Null { + $default + } else { + json_cast!(@log_key $name, v, $convert) + } + }) + }; +} + +fn format_bytes(bytes: u64) -> String { + let bytes = Bytes::new(bytes); + bytes.to_string() +} + +fn format_speed(speed: f64) -> String { + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + let bytes = Bytes::new(speed.floor() as u64); + format!("{bytes}/s") +} + /// # Panics /// If expectations fail. #[allow(clippy::needless_pass_by_value)] @@ -35,110 +58,44 @@ pub(crate) fn progress_hook( return Ok(()); } - macro_rules! get { - (@interrogate $item:ident, $type_fun:ident, $get_fun:ident, $name:expr) => {{ - let a = $item.get($name).expect(concat!( - "The field '", - stringify!($name), - "' should exist." - )); - - if a.$type_fun() { - a.$get_fun().expect( - "The should have been checked in the if guard, so unpacking here is fine", - ) - } else { - panic!( - "Value {} => \n{}\n is not of type: {}", - $name, - a, - stringify!($type_fun) - ); - } - }}; - - ($type_fun:ident, $get_fun:ident, $name1:expr, $name2:expr) => {{ - let a = get! {@interrogate input, is_object, as_object, $name1}; - let b = get! {@interrogate a, $type_fun, $get_fun, $name2}; - b - }}; - - ($type_fun:ident, $get_fun:ident, $name:expr) => {{ - get! {@interrogate input, $type_fun, $get_fun, $name} - }}; - } - - macro_rules! default_get { - (@interrogate $item:ident, $default:expr, $get_fun:ident, $name:expr) => {{ - let a = if let Some(field) = $item.get($name) { - field.$get_fun().unwrap_or($default) - } else { - $default - }; - a - }}; - - ($get_fun:ident, $default:expr, $name1:expr, $name2:expr) => {{ - let a = get! {@interrogate input, is_object, as_object, $name1}; - let b = default_get! {@interrogate a, $default, $get_fun, $name2}; - b - }}; - - ($get_fun:ident, $default:expr, $name:expr) => {{ - default_get! {@interrogate input, $default, $get_fun, $name} - }}; - } - - macro_rules! c { - ($color:expr, $format:expr) => { - format!("\x1b[{}m{}\x1b[0m", $color, $format) - }; - } - - #[allow(clippy::items_after_statements)] - fn format_bytes(bytes: u64) -> String { - let bytes = Bytes::new(bytes); - bytes.to_string() - } - - #[allow(clippy::items_after_statements)] - fn format_speed(speed: f64) -> String { - #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - let bytes = Bytes::new(speed.floor() as u64); - format!("{bytes}/s") - } + let info_dict = json_get!(input, "info_dict", as_object); let get_title = || -> String { - match get! {is_string, as_str, "info_dict", "ext"} { + match json_get!(info_dict, "ext", as_str) { "vtt" => { format!( "Subtitles ({})", - default_get! {as_str, "<No Subtitle Language>", "info_dict", "name"} + json_get_default!(info_dict, "name", as_str, "<No Subtitle Language>") ) } "webm" | "mp4" | "mp3" | "m4a" => { - default_get! { as_str, "<No title>", "info_dict", "title"}.to_owned() + json_get_default!(info_dict, "title", as_str, "<No title>").to_owned() } other => panic!("The extension '{other}' is not yet implemented"), } }; - match get! {is_string, as_str, "status"} { + match json_get!(input, "status", as_str) { "downloading" => { - let elapsed = default_get! {as_f64, 0.0f64, "elapsed"}; - let eta = default_get! {as_f64, 0.0, "eta"}; - let speed = default_get! {as_f64, 0.0, "speed"}; + let elapsed = json_get_default!(input, "elapsed", as_f64, 0.0); + let eta = json_get_default!(input, "eta", as_f64, 0.0); + let speed = json_get_default!(input, "speed", as_f64, 0.0); - let downloaded_bytes = get! {is_u64, as_u64, "downloaded_bytes"}; + let downloaded_bytes = json_get!(input, "downloaded_bytes", as_u64); let (total_bytes, bytes_is_estimate): (u64, &'static str) = { - let total_bytes = default_get!(as_u64, 0, "total_bytes"); + let total_bytes = json_get_default!(input, "total_bytes", as_u64, 0); + if total_bytes == 0 { - let maybe_estimate = default_get!(as_u64, 0, "total_bytes_estimate"); + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + let maybe_estimate = + json_get_default!(input, "total_bytes_estimate", as_f64, 0.0) as u64; #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] if maybe_estimate == 0 { - // The download speed should be in bytes per second and the eta in seconds. - // Thus multiplying them gets us the raw bytes (which were estimated by `yt_dlp`, from their `info.json`) + // The download speed should be in bytes + // per second and the eta in seconds. + // Thus multiplying them gets us the raw bytes + // (which were estimated by `yt_dlp`, from their `info.json`) let bytes_still_needed = (speed * eta).ceil() as u64; (downloaded_bytes + bytes_still_needed, "~") @@ -170,14 +127,14 @@ pub(crate) fn progress_hook( eprint!( "{} [{}/{} at {}] -> [{} of {}{} {}] ", - c!("34;1", get_title()), - c!("33;1", MaybeDuration::from_secs_f64(elapsed)), - c!("33;1", MaybeDuration::from_secs_f64(eta)), - c!("32;1", format_speed(speed)), - c!("31;1", format_bytes(downloaded_bytes)), - c!("31;1", bytes_is_estimate), - c!("31;1", format_bytes(total_bytes)), - c!("36;1", format!("{:.02}%", percent)) + get_title().bold().blue(), + MaybeDuration::from_secs_f64(elapsed).bold().yellow(), + MaybeDuration::from_secs_f64(eta).bold().yellow(), + format_speed(speed).bold().green(), + format_bytes(downloaded_bytes).bold().red(), + bytes_is_estimate.bold().red(), + format_bytes(total_bytes).bold().red(), + format!("{percent:.02}%").bold().cyan(), ); stderr().flush()?; } |