From a9fddbeebf428eb57c60afab96fbbd38629a636e Mon Sep 17 00:00:00 2001 From: Benedikt Peetz Date: Thu, 24 Jul 2025 16:20:34 +0200 Subject: fix(treewide): Use `json_try_get!` instead of `json.get(..).map(|| ..)` `json.get` will return `Some(Value::Null)` if the json key exists but has been set to `null`. This is obviously not what we want, and as such we also need to check that the value is not null, before calling map. The `json_try_get!` macro does exactly that. --- crates/yt_dlp/src/lib.rs | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) (limited to 'crates/yt_dlp/src') diff --git a/crates/yt_dlp/src/lib.rs b/crates/yt_dlp/src/lib.rs index dc602db..6be5e87 100644 --- a/crates/yt_dlp/src/lib.rs +++ b/crates/yt_dlp/src/lib.rs @@ -49,22 +49,37 @@ macro_rules! json_get { }}; } +#[macro_export] +macro_rules! json_try_get { + ($value:expr, $name:literal, $into:ident) => {{ + if let Some(val) = $value.get($name) { + if val.is_null() { + None + } else { + Some(json_cast!(@log_key $name, val, $into)) + } + } else { + None + } + }}; +} + #[macro_export] macro_rules! json_cast { ($value:expr, $into:ident) => {{ - json_cast!(@log_key "", $value, $into) + let value_name = stringify!($value); + json_cast!(@log_key value_name, $value, $into) }}; - (@log_key $name:literal, $value:expr, $into:ident) => {{ + (@log_key $name:expr, $value:expr, $into:ident) => {{ match $value.$into() { Some(result) => result, None => panic!( concat!( - "Expected to be able to cast '", - $name, - "' value ({:#?}) ", + "Expected to be able to cast '{}' value (which is '{:?}') ", stringify!($into) ), + $name, $value ), } @@ -130,8 +145,9 @@ impl YoutubeDL { let info_json = self.extract_info(url, true, true)?; // Try to work around yt-dlp type weirdness - let result_string = if let Some(filename) = info_json.get("filename") { - PathBuf::from(json_cast!(filename, as_str)) + let result_string = if let Some(filename) = json_try_get!(info_json, "filename", as_str) + { + PathBuf::from(filename) } else { PathBuf::from(json_get!( json_cast!( @@ -195,9 +211,10 @@ impl YoutubeDL { // already resolved. Do nothing } else if let Ok(generator) = generator.downcast::() { // A python generator object. - let max_backlog = self.options.get("playlistend").map_or(10000, |value| { - usize::try_from(json_cast!(value, as_u64)).expect("Should work") - }); + let max_backlog = json_try_get!(self.options, "playlistend", as_u64) + .map_or(10000, |playlistend| { + usize::try_from(playlistend).expect("Should work") + }); let mut out = vec![]; for output in generator { @@ -211,9 +228,10 @@ impl YoutubeDL { result.set_item(intern!(py, "entries"), out).wrap_exc(py)?; } else { // Probably some sort of paged list (`OnDemand` or otherwise) - let max_backlog = self.options.get("playlistend").map_or(10000, |value| { - usize::try_from(json_cast!(value, as_u64)).expect("Should work") - }); + let max_backlog = json_try_get!(self.options, "playlistend", as_u64) + .map_or(10000, |playlistend| { + usize::try_from(playlistend).expect("Should work") + }); let next = generator.getattr(intern!(py, "getslice")).wrap_exc(py)?; -- cgit 1.4.1