diff options
author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-07-24 16:20:34 +0200 |
---|---|---|
committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-07-24 16:20:34 +0200 |
commit | a9fddbeebf428eb57c60afab96fbbd38629a636e (patch) | |
tree | 480d9c1ae6f43598bfff7e4a29a378691b0a7508 /crates/yt_dlp/src | |
parent | fix(crates/yt/{commands/playlist,videos/format_video}): Correctly calculate w... (diff) | |
download | yt-a9fddbeebf428eb57c60afab96fbbd38629a636e.zip |
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.
Diffstat (limited to 'crates/yt_dlp/src')
-rw-r--r-- | crates/yt_dlp/src/lib.rs | 44 |
1 files changed, 31 insertions, 13 deletions
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 @@ -50,21 +50,36 @@ 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 "<unknown>", $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::<PyIterator>() { // 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)?; |