Compare commits

..

No commits in common. "f7b7c1954c011dbdf97430b388aa661ca9e9238f" and "1abdd6f3e2c7ec306adfac4642e2f2a4b30c4acb" have entirely different histories.

13 changed files with 55 additions and 1543 deletions

View file

@ -64,22 +64,15 @@ mod tests {
use crate::{client::response, model::ChannelRss}; use crate::{client::response, model::ChannelRss};
use rstest::rstest; #[test]
fn map_channel_rss() {
#[rstest] let xml_path = Path::new("testfiles/channel_rss/base.xml");
#[case::base("base")]
#[case::no_likes("no_likes")]
#[case::no_channel_id("no_channel_id")]
fn map_channel_rss(#[case] name: &str) {
let filename = format!("testfiles/channel_rss/{}.xml", name);
let xml_path = Path::new(&filename);
let xml_file = File::open(xml_path).unwrap(); let xml_file = File::open(xml_path).unwrap();
let feed: response::ChannelRss = let feed: response::ChannelRss =
quick_xml::de::from_reader(BufReader::new(xml_file)).unwrap(); quick_xml::de::from_reader(BufReader::new(xml_file)).unwrap();
let map_res: ChannelRss = feed.into(); let map_res: ChannelRss = feed.into();
insta::assert_ron_snapshot!(format!("map_channel_rss_{}", name), map_res); insta::assert_ron_snapshot!("map_channel_rss", map_res);
} }
} }

View file

@ -1,8 +1,10 @@
use serde::Deserialize; use serde::Deserialize;
use serde_with::{rust::deserialize_ignore_any, serde_as, DefaultOnError, VecSkipError}; use serde_with::serde_as;
use serde_with::{DefaultOnError, VecSkipError};
use super::url_endpoint::NavigationEndpoint; use super::url_endpoint::NavigationEndpoint;
use super::{Alert, ChannelBadge, ContentsRenderer, ResponseContext, Thumbnails, YouTubeListItem}; use super::{Alert, ChannelBadge, ContentsRenderer, ResponseContext, Thumbnails, YouTubeListItem};
use crate::serializer::ignore_any;
use crate::serializer::{text::Text, MapResult, VecLogError}; use crate::serializer::{text::Text, MapResult, VecLogError};
#[serde_as] #[serde_as]
@ -106,7 +108,7 @@ pub(crate) enum ChannelContent {
}, },
ChannelAboutFullMetadataRenderer(ChannelFullMetadata), ChannelAboutFullMetadataRenderer(ChannelFullMetadata),
#[default] #[default]
#[serde(other, deserialize_with = "deserialize_ignore_any")] #[serde(other, deserialize_with = "ignore_any")]
None, None,
} }
@ -152,7 +154,7 @@ pub(crate) enum CarouselHeaderRendererItem {
#[serde(default)] #[serde(default)]
avatar: Thumbnails, avatar: Thumbnails,
}, },
#[serde(other, deserialize_with = "deserialize_ignore_any")] #[serde(other, deserialize_with = "ignore_any")]
None, None,
} }

View file

@ -1,8 +1,6 @@
use serde::Deserialize; use serde::Deserialize;
use time::OffsetDateTime; use time::OffsetDateTime;
use crate::util;
use super::Thumbnail; use super::Thumbnail;
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@ -11,7 +9,6 @@ pub(crate) struct ChannelRss {
pub channel_id: String, pub channel_id: String,
#[serde(rename = "$unflatten=title")] #[serde(rename = "$unflatten=title")]
pub title: String, pub title: String,
pub author: Author,
#[serde(rename = "$unflatten=published", with = "time::serde::rfc3339")] #[serde(rename = "$unflatten=published", with = "time::serde::rfc3339")]
pub create_date: OffsetDateTime, pub create_date: OffsetDateTime,
pub entry: Vec<Entry>, pub entry: Vec<Entry>,
@ -21,8 +18,6 @@ pub(crate) struct ChannelRss {
pub(crate) struct Entry { pub(crate) struct Entry {
#[serde(rename = "$unflatten=yt:videoId")] #[serde(rename = "$unflatten=yt:videoId")]
pub video_id: String, pub video_id: String,
#[serde(rename = "$unflatten=yt:channelId")]
pub channel_id: String,
#[serde(rename = "$unflatten=title")] #[serde(rename = "$unflatten=title")]
pub title: String, pub title: String,
#[serde(rename = "$unflatten=published", with = "time::serde::rfc3339")] #[serde(rename = "$unflatten=published", with = "time::serde::rfc3339")]
@ -61,42 +56,10 @@ pub(crate) struct Statistics {
pub views: u64, pub views: u64,
} }
#[derive(Debug, Deserialize)]
pub(crate) struct Author {
pub uri: String,
}
impl From<ChannelRss> for crate::model::ChannelRss { impl From<ChannelRss> for crate::model::ChannelRss {
fn from(feed: ChannelRss) -> Self { fn from(feed: ChannelRss) -> Self {
let id = if feed.channel_id.is_empty() {
feed.entry
.iter()
.find_map(|entry| {
if !entry.channel_id.is_empty() {
Some(entry.channel_id.to_owned())
} else {
None
}
})
.or_else(|| {
feed.author
.uri
.strip_prefix("https://www.youtube.com/channel/")
.and_then(|id| {
if util::CHANNEL_ID_REGEX.is_match(id).unwrap_or_default() {
Some(id.to_owned())
} else {
None
}
})
})
.unwrap_or_default()
} else {
feed.channel_id
};
Self { Self {
id, id: feed.channel_id,
name: feed.title, name: feed.title,
videos: feed videos: feed
.entry .entry

View file

@ -1,5 +1,5 @@
use serde::Deserialize; use serde::Deserialize;
use serde_with::{rust::deserialize_ignore_any, serde_as, DefaultOnError, VecSkipError}; use serde_with::{serde_as, DefaultOnError, VecSkipError};
use crate::{ use crate::{
model::{ model::{
@ -8,6 +8,7 @@ use crate::{
}, },
param::Language, param::Language,
serializer::{ serializer::{
ignore_any,
text::{Text, TextComponents}, text::{Text, TextComponents},
MapResult, VecLogError, MapResult, VecLogError,
}, },
@ -30,7 +31,7 @@ pub(crate) enum ItemSection {
#[serde_as(as = "VecLogError<_>")] #[serde_as(as = "VecLogError<_>")]
contents: MapResult<Vec<MusicResponseItem>>, contents: MapResult<Vec<MusicResponseItem>>,
}, },
#[serde(other, deserialize_with = "deserialize_ignore_any")] #[serde(other, deserialize_with = "ignore_any")]
None, None,
} }
@ -200,7 +201,7 @@ pub(crate) struct PlaylistPanelRenderer {
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub(crate) enum PlaylistPanelVideo { pub(crate) enum PlaylistPanelVideo {
PlaylistPanelVideoRenderer(QueueMusicItem), PlaylistPanelVideoRenderer(QueueMusicItem),
#[serde(other, deserialize_with = "deserialize_ignore_any")] #[serde(other, deserialize_with = "ignore_any")]
None, None,
} }

View file

@ -1,7 +1,7 @@
use serde::Deserialize; use serde::Deserialize;
use serde_with::{rust::deserialize_ignore_any, serde_as, VecSkipError}; use serde_with::{serde_as, VecSkipError};
use crate::serializer::text::Text; use crate::serializer::{ignore_any, text::Text};
use super::{music_item::MusicShelf, ContentsRenderer, SectionList, Tab}; use super::{music_item::MusicShelf, ContentsRenderer, SectionList, Tab};
@ -28,7 +28,7 @@ pub(crate) enum ItemSection {
#[serde_as(as = "VecSkipError<_>")] #[serde_as(as = "VecSkipError<_>")]
contents: Vec<ShowingResultsFor>, contents: Vec<ShowingResultsFor>,
}, },
#[serde(other, deserialize_with = "deserialize_ignore_any")] #[serde(other, deserialize_with = "ignore_any")]
None, None,
} }

View file

@ -1,10 +1,8 @@
use serde::Deserialize; use serde::Deserialize;
use serde_with::{ use serde_with::{json::JsonString, serde_as, DefaultOnError, VecSkipError};
json::JsonString, rust::deserialize_ignore_any, serde_as, DefaultOnError, VecSkipError,
};
use crate::serializer::text::{Text, TextComponent}; use crate::serializer::text::{Text, TextComponent};
use crate::serializer::{MapResult, VecLogError}; use crate::serializer::{ignore_any, MapResult, VecLogError};
use crate::util::MappingError; use crate::util::MappingError;
use super::{ use super::{
@ -158,7 +156,7 @@ pub(crate) enum PlaylistItem {
continuation_endpoint: ContinuationEndpoint, continuation_endpoint: ContinuationEndpoint,
}, },
/// No video list item (e.g. ad) or unimplemented item /// No video list item (e.g. ad) or unimplemented item
#[serde(other, deserialize_with = "deserialize_ignore_any")] #[serde(other, deserialize_with = "ignore_any")]
None, None,
} }

View file

@ -1,10 +1,12 @@
#![allow(clippy::enum_variant_names)] #![allow(clippy::enum_variant_names)]
use serde::Deserialize; use serde::Deserialize;
use serde_with::{rust::deserialize_ignore_any, serde_as, DefaultOnError, VecSkipError}; use serde_with::serde_as;
use serde_with::{DefaultOnError, VecSkipError};
use crate::serializer::text::TextComponent; use crate::serializer::text::TextComponent;
use crate::serializer::{ use crate::serializer::{
ignore_any,
text::{AccessibilityText, AttributedText, Text, TextComponents}, text::{AccessibilityText, AttributedText, Text, TextComponents},
MapResult, VecLogError, MapResult, VecLogError,
}; };
@ -100,7 +102,7 @@ pub(crate) enum VideoResultsItem {
/// 1. sectionIdentifier: "comments-entry-point", contains number of comments /// 1. sectionIdentifier: "comments-entry-point", contains number of comments
/// 2. sectionIdentifier: "comment-item-section", contains continuation token /// 2. sectionIdentifier: "comment-item-section", contains continuation token
ItemSectionRenderer(#[serde_as(deserialize_as = "DefaultOnError")] ItemSection), ItemSectionRenderer(#[serde_as(deserialize_as = "DefaultOnError")] ItemSection),
#[serde(other, deserialize_with = "deserialize_ignore_any")] #[serde(other, deserialize_with = "ignore_any")]
None, None,
} }
@ -333,7 +335,7 @@ pub(crate) enum EngagementPanelRenderer {
/// (Description already included in `VideoSecondaryInfoRenderer`) /// (Description already included in `VideoSecondaryInfoRenderer`)
/// - `engagement-panel-searchable-transcript` /// - `engagement-panel-searchable-transcript`
/// (basically video subtitles in a different format) /// (basically video subtitles in a different format)
#[serde(other, deserialize_with = "deserialize_ignore_any")] #[serde(other, deserialize_with = "ignore_any")]
None, None,
} }

View file

@ -1,9 +1,7 @@
use fancy_regex::Regex; use fancy_regex::Regex;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use serde::Deserialize; use serde::Deserialize;
use serde_with::{ use serde_with::{json::JsonString, serde_as, DefaultOnError, VecSkipError};
json::JsonString, rust::deserialize_ignore_any, serde_as, DefaultOnError, VecSkipError,
};
use time::{Duration, OffsetDateTime}; use time::{Duration, OffsetDateTime};
use super::{ChannelBadge, ContinuationEndpoint, Thumbnails}; use super::{ChannelBadge, ContinuationEndpoint, Thumbnails};
@ -11,6 +9,7 @@ use crate::{
model::{Channel, ChannelId, ChannelItem, ChannelTag, PlaylistItem, VideoItem, YouTubeItem}, model::{Channel, ChannelId, ChannelItem, ChannelTag, PlaylistItem, VideoItem, YouTubeItem},
param::Language, param::Language,
serializer::{ serializer::{
ignore_any,
text::{AccessibilityText, Text, TextComponent}, text::{AccessibilityText, Text, TextComponent},
MapResult, VecLogError, MapResult, VecLogError,
}, },
@ -70,7 +69,7 @@ pub(crate) enum YouTubeListItem {
/// Unimplemented: /// Unimplemented:
/// - compactPlaylistRenderer (recommended playlists) /// - compactPlaylistRenderer (recommended playlists)
/// - compactRadioRenderer (recommended mix) /// - compactRadioRenderer (recommended mix)
#[serde(other, deserialize_with = "deserialize_ignore_any")] #[serde(other, deserialize_with = "ignore_any")]
None, None,
} }

View file

@ -1,221 +0,0 @@
---
source: src/client/channel_rss.rs
expression: map_res
---
ChannelRss(
id: "UCdfxp4cUWsWryZOy-o427dw",
name: "Nestlé",
videos: [
ChannelRssVideo(
id: "Kti0T9JF0go",
title: "KitKat V PTC York Production | Nestlé B-Roll",
description: "Footage from the production for the test launch of KitKat V in 2021 at Nestlés Confectionery Product Technology Center in York. \n\nYou can download this B-roll stock footage from our corporate website here: http://www.nestle.com/media/videos\n\nFor regular Nestlé updates, follow:\nhttps://www.facebook.com/Nestle \nhttps://www.instagram.com/Nestle \nhttps://www.twitter.com/Nestle",
thumbnail: Thumbnail(
url: "https://i4.ytimg.com/vi/Kti0T9JF0go/hqdefault.jpg",
width: 480,
height: 360,
),
publish_date: "2022-08-29T08:00:11Z",
update_date: "2022-08-29T08:18:04Z",
view_count: 422,
like_count: 0,
),
ChannelRssVideo(
id: "0L2TOCyvCH8",
title: "KitKat V Hamburg Production | Nestlé B-Roll",
description: "Footage from the production line of KitKat V at Nestlés factory in Hamburg, Germany.\n\nYou can download this B-roll stock footage from our corporate website here: http://www.nestle.com/media/videos\n\nFor regular Nestlé updates, follow:\nhttps://www.facebook.com/Nestle \nhttps://www.instagram.com/Nestle \nhttps://www.twitter.com/Nestle",
thumbnail: Thumbnail(
url: "https://i1.ytimg.com/vi/0L2TOCyvCH8/hqdefault.jpg",
width: 480,
height: 360,
),
publish_date: "2022-08-29T08:00:01Z",
update_date: "2022-08-29T08:18:08Z",
view_count: 500,
like_count: 0,
),
ChannelRssVideo(
id: "PIXvtaQmnjA",
title: "R+D Accelerator | Nestlé Innovates",
description: "Our R&D Accelerator brings together Nestlé scientists, students and start-ups to advance science and technology by accelerating the development of innovative products and systems.\u{a0}\u{200b}Got an idea to submit? Go ahead! https://rdaccelerator.nestle.com/\n\n#Nestlé Innovates #shorts",
thumbnail: Thumbnail(
url: "https://i1.ytimg.com/vi/PIXvtaQmnjA/hqdefault.jpg",
width: 480,
height: 360,
),
publish_date: "2022-08-25T15:38:47Z",
update_date: "2022-08-26T14:44:53Z",
view_count: 103,
like_count: 0,
),
ChannelRssVideo(
id: "OAq0FBdxuuI",
title: "R+D Accelerator | Nestlé Innovates",
description: "Do you have an innovation you could unlock with Nestlé partnership? Our R&D Accelerator harnesses the expertise of Nestlés global R&D network in food and nutrition as well as leading academic institutions and a wide range of innovation partners, suppliers and start-ups. Find out how to advance your idea with science and technology here: https://rdaccelerator.nestle.com/\n\n#NestleInnovates #shorts",
thumbnail: Thumbnail(
url: "https://i4.ytimg.com/vi/OAq0FBdxuuI/hqdefault.jpg",
width: 480,
height: 360,
),
publish_date: "2022-08-25T15:37:43Z",
update_date: "2022-08-26T14:08:38Z",
view_count: 70,
like_count: 0,
),
ChannelRssVideo(
id: "rh2ryMOIQ8k",
title: "R+D Accelerator | Nestlé Innovates",
description: "Calling all food and nutrition entrepreneurs! Got an idea adn looking for the science, technology and experts to put it into action? Check out our R&D Accelerator that brings all those together in the pursuit of developing innovative products and systems: https://rdaccelerator.nestle.com/\n\n#NestleInnovates #shorts",
thumbnail: Thumbnail(
url: "https://i3.ytimg.com/vi/rh2ryMOIQ8k/hqdefault.jpg",
width: 480,
height: 360,
),
publish_date: "2022-08-25T15:36:04Z",
update_date: "2022-08-26T08:24:59Z",
view_count: 85,
like_count: 0,
),
ChannelRssVideo(
id: "Q0xHfgCmb0g",
title: "R+D Accelerator | Nestlé Innovates",
description: "Our R&D Accelerator brings together Nestlé scientists, students and start-ups to advance science and technology by accelerating the development of innovative products and systems.\u{a0}\u{200b}Got an idea to submit? Go ahead! https://rdaccelerator.nestle.com/\n\n#NestleInnovates #shorts",
thumbnail: Thumbnail(
url: "https://i2.ytimg.com/vi/Q0xHfgCmb0g/hqdefault.jpg",
width: 480,
height: 360,
),
publish_date: "2022-08-25T15:34:38Z",
update_date: "2022-09-07T19:15:24Z",
view_count: 77,
like_count: 0,
),
ChannelRssVideo(
id: "jD_EcIB4kq4",
title: "Brain Health | Nestlé Innovates",
description: "Aging is a complex journey. Getting the most out of your health shouldnt have to be. Thats why our teams have dug into the data to support with living the fullest life in our later years. Check it out: https://nes.tl/HealthScience\n\n#NestleInnovates #shorts",
thumbnail: Thumbnail(
url: "https://i3.ytimg.com/vi/jD_EcIB4kq4/hqdefault.jpg",
width: 480,
height: 360,
),
publish_date: "2022-08-25T15:27:15Z",
update_date: "2022-08-26T08:38:04Z",
view_count: 39,
like_count: 0,
),
ChannelRssVideo(
id: "KNSHhxGGAik",
title: "Gut Microbiome | Nestlé Innovates",
description: "In-depth research has given us an understanding of the gut microbiome. Now check out the health solutions weve worked on as a result: https://nes.tl/HealthScience\n\n#NestleInnovates #shorts",
thumbnail: Thumbnail(
url: "https://i4.ytimg.com/vi/KNSHhxGGAik/hqdefault.jpg",
width: 480,
height: 360,
),
publish_date: "2022-08-25T15:26:13Z",
update_date: "2022-08-26T08:29:53Z",
view_count: 78,
like_count: 0,
),
ChannelRssVideo(
id: "bPtEA9yjHVU",
title: "Cellular Decline | Nestlé Innovates",
description: "Age-associated cellular decline can reduce a person\'s energy level, muscle function, immune response, and overall health. Our research and development teams believe health science can help address this. Discover the results their work has yielded: https://nes.tl/HealthScience\n\n#NestleInnovates #shorts",
thumbnail: Thumbnail(
url: "https://i3.ytimg.com/vi/bPtEA9yjHVU/hqdefault.jpg",
width: 480,
height: 360,
),
publish_date: "2022-08-25T15:24:26Z",
update_date: "2022-08-26T08:23:43Z",
view_count: 61,
like_count: 0,
),
ChannelRssVideo(
id: "T0ugeidZ44k",
title: "Nescafé Gold Roastery Collection | Nestlé Innovates",
description: "Our Nescafé Gold Blend Roastery Collection is carefully crafted for a great taste thanks to our teams\' experimenting with roasting levels and times. With a range of flavors and intensities to choose from, theres something for everyone. Find your fave: https://nes.tl/NescafeGoldCollection \n\n#NestleInnovates #Shorts",
thumbnail: Thumbnail(
url: "https://i1.ytimg.com/vi/T0ugeidZ44k/hqdefault.jpg",
width: 480,
height: 360,
),
publish_date: "2022-08-25T15:21:43Z",
update_date: "2022-08-26T08:35:57Z",
view_count: 61,
like_count: 0,
),
ChannelRssVideo(
id: "DhMa-669pKU",
title: "Garden Gourmet Vuna | Nestlé Innovates",
description: "Cracking open a jar of Vuna you don\'t believe you\'re eating anything other than tuna. This is thanks to our creative R&D colleagues. Check out this groundbreaking creation made from only six ingredients: https://nes.tl/VUNA-Story \n\n#NestleInnovates #Shorts",
thumbnail: Thumbnail(
url: "https://i1.ytimg.com/vi/DhMa-669pKU/hqdefault.jpg",
width: 480,
height: 360,
),
publish_date: "2022-08-25T15:15:24Z",
update_date: "2022-08-26T06:51:51Z",
view_count: 281,
like_count: 0,
),
ChannelRssVideo(
id: "IVHIRHyEha0",
title: "Wunda | Nestlé Innovates",
description: "A milk-alternative powered by pea-protein and carbon neutral from creation sounds to good to be true? Not so. Check out the innovation that brought Wunda to life: https://nes.tl/WundaStory \n\n#NestleInnovates #Shorts",
thumbnail: Thumbnail(
url: "https://i2.ytimg.com/vi/IVHIRHyEha0/hqdefault.jpg",
width: 480,
height: 360,
),
publish_date: "2022-08-25T15:14:29Z",
update_date: "2022-08-26T06:49:23Z",
view_count: 63,
like_count: 0,
),
ChannelRssVideo(
id: "EKsM6WrGR7k",
title: "Plant-based Milo | Nestlé Innovates",
description: "Our Milo teams wanted to ensure that everyone has the chance to enjoy their iconic chocolate-malt flavor and crunch. That\'s why they\'ve created nutritious, plant-based options. Learn more here: https://nes.tl/MiloPlantBased \n\n#NestleInnovates #Shorts",
thumbnail: Thumbnail(
url: "https://i2.ytimg.com/vi/EKsM6WrGR7k/hqdefault.jpg",
width: 480,
height: 360,
),
publish_date: "2022-08-25T15:13:14Z",
update_date: "2022-08-26T06:59:11Z",
view_count: 93,
like_count: 0,
),
ChannelRssVideo(
id: "VhpNpEC5RNs",
title: "Smarties Paper Packaging | Nestlé Innovates",
description: "Have you heard about the first global confectionery brand to use recyclable paper packaging? Hint: they\'re pretty smart. Get the detes here: https://nes.tl/SmartiesPaperStory\n\n#NestleInnovates #shorts",
thumbnail: Thumbnail(
url: "https://i3.ytimg.com/vi/VhpNpEC5RNs/hqdefault.jpg",
width: 480,
height: 360,
),
publish_date: "2022-08-25T15:11:48Z",
update_date: "2022-08-26T08:54:09Z",
view_count: 145,
like_count: 0,
),
ChannelRssVideo(
id: "Z1lTKnUzSDk",
title: "Nescafé Gold Iced Latte | Nestlé Innovates",
description: "Our coffee teams developed Nescafe Gold Iced Lattes a range for those who want to enjoy refreshing coffee shop style drinks at home. See how we\'re meeting all tastes and preferences through innovation: https://nes.tl/DailyGrinds \n\n#NestleInnovates #shorts",
thumbnail: Thumbnail(
url: "https://i3.ytimg.com/vi/Z1lTKnUzSDk/hqdefault.jpg",
width: 480,
height: 360,
),
publish_date: "2022-08-25T15:10:23Z",
update_date: "2022-08-26T06:54:55Z",
view_count: 119,
like_count: 0,
),
],
create_date: "2009-10-07T14:00:36Z",
)

View file

@ -10,6 +10,8 @@ pub use vec_log_err::VecLogError;
use std::fmt::Debug; use std::fmt::Debug;
use serde::{de::IgnoredAny, Deserializer};
/// This represents a result from a deserializing/mapping operation. /// This represents a result from a deserializing/mapping operation.
/// It holds the desired content (`c`) and a list of warning messages, /// It holds the desired content (`c`) and a list of warning messages,
/// if there occurred minor error during the deserializing or mapping /// if there occurred minor error during the deserializing or mapping
@ -41,10 +43,33 @@ where
} }
} }
/// Deserialization method that consumes anything and returns an empty value.
/// Intended to be used for a wildcard enum option.
///
/// Example:
/// ```rs
/// #[derive(Deserialize)]
/// enum Fruit {
/// Apple {
/// red: bool,
/// },
/// Banana {
/// yellow: bool,
/// },
/// #[serde(other, deserialize_with = "deserialize_blackhole")]
/// None,
/// }
/// ```
pub fn ignore_any<'de, D>(deserializer: D) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_ignored_any(IgnoredAny).and(Ok(()))
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use serde::Deserialize; use serde::Deserialize;
use serde_with::rust::deserialize_ignore_any;
use super::*; use super::*;
@ -56,7 +81,7 @@ mod tests {
Banana { Banana {
yellow: bool, yellow: bool,
}, },
#[serde(other, deserialize_with = "deserialize_ignore_any")] #[serde(other, deserialize_with = "ignore_any")]
None, None,
} }

File diff suppressed because it is too large Load diff