- Commit
- b68e180a1f3e8c9ff6e012df1b4498b6b3de24f1
- Parent
- ccdb0dcabc52c30aeffde118f2a72e90c377e201
- Author
- Pablo <pablo-escobar@riseup.net>
- Date
Renamed the Picture type to GalleryEntry
Also renamed the corresponding module
Yet another static page generator for photo galleries
Renamed the Picture type to GalleryEntry
Also renamed the corresponding module
3 files changed, 421 insertions, 421 deletions
Status | File Name | N° Changes | Insertions | Deletions |
Added | src/gallery_entry.rs | 413 | 413 | 0 |
Modified | src/main.rs | 16 | 8 | 8 |
Deleted | src/picture.rs | 413 | 0 | 413 |
diff --git a/src/gallery_entry.rs b/src/gallery_entry.rs @@ -0,0 +1,413 @@ +use serde::{ + de::{Deserializer, Error, Unexpected}, + Deserialize, +}; +use std::{fmt::{self, Display}, path::PathBuf}; + +const LICENSES: &[&str] = &[ + "PD", + "CC0", + "CC-BY-1", + "CC-BY-2", + "CC-BY-3", + "CC-BY-4", + "CC-BY-SA-1", + "CC-BY-SA-2", + "CC-BY-SA-3", + "CC-BY-SA-4", + "CC-BY-NC-1", + "CC-BY-NC-2", + "CC-BY-NC-3", + "CC-BY-NC-4", + "CC-BY-NC-SA-1", + "CC-BY-NC-SA-2", + "CC-BY-NC-SA-3", + "CC-BY-NC-SA-4", + "CC-BY-ND-1", + "CC-BY-ND-2", + "CC-BY-ND-3", + "CC-BY-ND-4", + "CC-BY-NC-ND-1", + "CC-BY-NC-ND-2", + "CC-BY-NC-ND-3", + "CC-BY-NC-ND-4", +]; + +/// Info on a individual entry on the gallery +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct GalleryEntry { + pub path: PathBuf, + pub file_name: String, + pub alt: String, + pub caption: Option<String>, + pub license: Option<LicenseType>, + pub author: String, + pub author_url: Option<String>, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct LicenseType(CreativeCommons); + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum CreativeCommons { + /// Creative Commons (without attribution) + Cc0, + /// Creative Commons Attributions (derivatives allowed) + CcBy { + version: CreativeCommonsVersion, + non_commercial: bool, + share_alike: bool, + }, + // The ND (non-derivatives) option excludes the SA (share alike) option + /// Creative Commons Attributions Non-Derivatives + CcByNd { + version: CreativeCommonsVersion, + non_commercial: bool, + }, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum CreativeCommonsVersion { + One, + Two, + Three, + Four, +} + +impl LicenseType { + pub const fn url(&self) -> &'static str { + match self.0 { + // CC0 + CreativeCommons::Cc0 => { + "https://creativecommons.org/publicdomain/zero/1.0/" + }, + // CC-BY-1 + CreativeCommons::CcBy { + version: CreativeCommonsVersion::One, + non_commercial: false, + share_alike: false, + } => "http://creativecommons.org/licenses/by/1.0/", + // CC-BY-2 + CreativeCommons::CcBy { + version: CreativeCommonsVersion::Two, + non_commercial: false, + share_alike: false, + } => "http://creativecommons.org/licenses/by/2.0/", + // CC-BY-3 + CreativeCommons::CcBy { + version: CreativeCommonsVersion::Three, + non_commercial: false, + share_alike: false, + } => "http://creativecommons.org/licenses/by/3.0/", + // CC-BY-4 + CreativeCommons::CcBy { + version: CreativeCommonsVersion::Four, + non_commercial: false, + share_alike: false, + } => "http://creativecommons.org/licenses/by/4.0/", + // CC-BY-SA-1 + CreativeCommons::CcBy { + version: CreativeCommonsVersion::One, + non_commercial: false, + share_alike: true, + } => "http://creativecommons.org/licenses/by-sa/1.0/", + // CC-BY-SA-2 + CreativeCommons::CcBy { + version: CreativeCommonsVersion::Two, + non_commercial: false, + share_alike: true, + } => "http://creativecommons.org/licenses/by-sa/2.0/", + // CC-BY-SA-3 + CreativeCommons::CcBy { + version: CreativeCommonsVersion::Three, + non_commercial: false, + share_alike: true, + } => "http://creativecommons.org/licenses/by-sa/3.0/", + // CC-BY-SA-4 + CreativeCommons::CcBy { + version: CreativeCommonsVersion::Four, + non_commercial: false, + share_alike: true, + } => "http://creativecommons.org/licenses/by-sa/4.0/", + // CC-BY-NC-1 + CreativeCommons::CcBy { + version: CreativeCommonsVersion::One, + non_commercial: true, + share_alike: false, + } => "http://creativecommons.org/licenses/by-nc/1.0/", + // CC-BY-NC-2 + CreativeCommons::CcBy { + version: CreativeCommonsVersion::Two, + non_commercial: true, + share_alike: false, + } => "http://creativecommons.org/licenses/by-nc/2.0/", + // CC-BY-NC-3 + CreativeCommons::CcBy { + version: CreativeCommonsVersion::Three, + non_commercial: true, + share_alike: false, + } => "http://creativecommons.org/licenses/by-nc/3.0/", + // CC-BY-NC-4 + CreativeCommons::CcBy { + version: CreativeCommonsVersion::Four, + non_commercial: true, + share_alike: false, + } => "http://creativecommons.org/licenses/by-nc/4.0/", + // CC-BY-NC-SA-1 + CreativeCommons::CcBy { + version: CreativeCommonsVersion::One, + non_commercial: true, + share_alike: true, + } => "http://creativecommons.org/licenses/by-nc-sa/1.0/", + // CC-BY-NC-SA-2 + CreativeCommons::CcBy { + version: CreativeCommonsVersion::Two, + non_commercial: true, + share_alike: true, + } => "http://creativecommons.org/licenses/by-nc-sa/2.0/", + // CC-BY-NC-SA-3 + CreativeCommons::CcBy { + version: CreativeCommonsVersion::Three, + non_commercial: true, + share_alike: true, + } => "http://creativecommons.org/licenses/by-nc-sa/3.0/", + // CC-BY-NC-SA-4 + CreativeCommons::CcBy { + version: CreativeCommonsVersion::Four, + non_commercial: true, + share_alike: true, + } => "http://creativecommons.org/licenses/by-nc-sa/4.0/", + // CC-BY-ND-1 + CreativeCommons::CcByNd { + version: CreativeCommonsVersion::One, + non_commercial: false, + } => "http://creativecommons.org/licenses/by-nd/1.0/", + // CC-BY-ND-2 + CreativeCommons::CcByNd { + version: CreativeCommonsVersion::Two, + non_commercial: false, + } => "http://creativecommons.org/licenses/by-nd/2.0/", + // CC-BY-ND-3 + CreativeCommons::CcByNd { + version: CreativeCommonsVersion::Three, + non_commercial: false, + } => "http://creativecommons.org/licenses/by-nd/3.0/", + // CC-BY-ND-4 + CreativeCommons::CcByNd { + version: CreativeCommonsVersion::Four, + non_commercial: false, + } => "http://creativecommons.org/licenses/by-nd/4.0/", + // CC-BY-NC-ND-1 + CreativeCommons::CcByNd { + version: CreativeCommonsVersion::One, + non_commercial: true, + } => "http://creativecommons.org/licenses/by-nc-nd/1.0/", + // CC-BY-NC-ND-2 + CreativeCommons::CcByNd { + version: CreativeCommonsVersion::Two, + non_commercial: true, + } => "http://creativecommons.org/licenses/by-nc-nd/2.0/", + // CC-BY-NC-ND-3 + CreativeCommons::CcByNd { + version: CreativeCommonsVersion::Three, + non_commercial: true, + } => "http://creativecommons.org/licenses/by-nc-nd/3.0/", + // CC-BY-NC-ND-4 + CreativeCommons::CcByNd { + version: CreativeCommonsVersion::Four, + non_commercial: true, + } => "http://creativecommons.org/licenses/by-nc-nd/4.0/", + } + } + + pub fn parse(s: &str) -> Result<Option<Self>, ()> { + if !LICENSES.contains(&s) { + return Err(()); + } + + if s == "PD" { + return Ok(None); + } else if s == "CC0" { + return Ok(Some(Self(CreativeCommons::Cc0))); + } + + assert!(s.len() >= 3, + "if s is in LICENSES it should contain at least 3 chars"); + + let version = match &s[s.len() - 1..] { + "1" => CreativeCommonsVersion::One, + "2" => CreativeCommonsVersion::Two, + "3" => CreativeCommonsVersion::Three, + "4" => CreativeCommonsVersion::Four, + _ => { + unreachable!("if s is in LICENSES we should be able to parse the license version") + }, + }; + + match &s[..s.len() - 1] { + "CC-BY-" => { + Ok( + Some( + Self( + CreativeCommons::CcBy { + version, + non_commercial: false, + share_alike: false, + } + ) + ) + ) + }, + "CC-BY-NC-" => { + Ok( + Some( + Self( + CreativeCommons::CcBy { + version, + non_commercial: true, + share_alike: false, + } + ) + ) + ) + }, + "CC-BY-SA-" => { + Ok( + Some( + Self( + CreativeCommons::CcBy { + version, + non_commercial: false, + share_alike: true, + } + ) + ) + ) + }, + "CC-BY-NC-SA-" => { + Ok( + Some( + Self( + CreativeCommons::CcBy { + version, + non_commercial: true, + share_alike: true, + } + ) + ) + ) + }, + "CC-BY-ND-" => { + Ok( + Some( + Self( + CreativeCommons::CcByNd { + version, + non_commercial: false, + } + ) + ) + ) + }, + "CC-BY-NC-ND-" => { + Ok( + Some( + Self( + CreativeCommons::CcByNd { + version, + non_commercial: true, + } + ) + ) + ) + }, + _ => { + unreachable!("if s is in LICENSES we should be able to parse the license-type") + }, + } + } +} + +impl<'de> Deserialize<'de> for GalleryEntry { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + #[derive(Deserialize)] + struct Info { + path: String, + alt: String, + caption: Option<String>, + license: String, + author: String, + #[serde(alias = "author-url")] + author_url: Option<String>, + } + + let Info { + path: path_str, + alt, + caption, + license, + author, + author_url, + } = Info::deserialize(deserializer)?; + + let license = LicenseType::parse(&license) + .map_err(|_| D::Error::unknown_variant(&license, LICENSES))?; + let path = PathBuf::from(&path_str); + + if let Some(file_name) = path.file_name().and_then(|s| s.to_str()) { + Ok(Self { + path: path.clone(), + alt: alt.trim().to_string(), + file_name: String::from(file_name), + caption, + author: author.trim().to_string(), + author_url: author_url.map(|s| s.trim().to_string()), + license, + }) + } else { + Err(D::Error::invalid_value( + Unexpected::Str(&path_str), + &"valid file path (couldn't extract file name)", + )) + } + } +} + +impl Display for LicenseType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + match self.0 { + CreativeCommons::Cc0 => write!(f, "CC0"), + CreativeCommons::CcBy { version, non_commercial, share_alike } => { + write!(f, "CC-BY")?; + if non_commercial { + write!(f, "-NC")?; + } + if share_alike { + write!(f, "-SA")?; + } + write!(f, " {version}") + }, + CreativeCommons::CcByNd { version, non_commercial } => { + write!(f, "CC-BY")?; + if non_commercial { + write!(f, "-NC")?; + } + write!(f, "-ND {version}") + } + } + } +} + +impl Display for CreativeCommonsVersion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + match self { + CreativeCommonsVersion::One => write!(f, "1.0"), + CreativeCommonsVersion::Two => write!(f, "2.0"), + CreativeCommonsVersion::Three => write!(f, "3.0"), + CreativeCommonsVersion::Four => write!(f, "4.0"), + } + } +}
diff --git a/src/main.rs b/src/main.rs @@ -10,10 +10,10 @@ use std::{ process::ExitCode, sync::mpsc, }; -use picture::Picture; +use gallery_entry::GalleryEntry; use threadpool::ThreadPool; -mod picture; +mod gallery_entry; /// A wrapper for HTML-escaped strings pub struct Escaped<'a>(pub &'a str); @@ -151,7 +151,7 @@ fn main() -> ExitCode { }; let f = File::open(config); - match f.map(serde_yaml::from_reader::<_, Vec<Picture>>) { + match f.map(serde_yaml::from_reader::<_, Vec<GalleryEntry>>) { // Error opening the config file Err(err) => { errorln!("Couldn't open {config:?}: {err}", @@ -171,7 +171,7 @@ fn main() -> ExitCode { } /// Coordinates the rendering of all the pages and file conversions -fn render_gallery(pics: Vec<Picture>) -> ExitCode { +fn render_gallery(pics: Vec<GalleryEntry>) -> ExitCode { log!("Copying image files to the target directory..."); for pic in &pics { @@ -244,7 +244,7 @@ fn render_gallery(pics: Vec<Picture>) -> ExitCode { ExitCode::SUCCESS } -fn render_index(pics: &Vec<Picture>) -> io::Result<()> { +fn render_index(pics: &Vec<GalleryEntry>) -> io::Result<()> { let mut path = PathBuf::from(TARGET_PATH); path.push("index.html"); @@ -257,7 +257,7 @@ fn render_index(pics: &Vec<Picture>) -> io::Result<()> { writeln!(f, "<title>{PAGE_TITLE}</title>")?; write_head(&mut f)?; - for pic in pics.into_iter().take(10) { + for pic in pics.iter().take(10) { // TODO: Preload mp4 thumbnails for GIF files writeln!( f, @@ -304,7 +304,7 @@ fn render_index(pics: &Vec<Picture>) -> io::Result<()> { writeln!(f, "</html>") } -fn render_pic_page(pic: &Picture) -> io::Result<()> { +fn render_pic_page(pic: &GalleryEntry) -> io::Result<()> { let mut path = PathBuf::from(TARGET_PATH); path.push(PAGES_PATH); path.push(pic.file_name.clone() + ".html"); @@ -448,7 +448,7 @@ fn write_license(f: &mut File) -> io::Result<()> { /// Returns `true` if rendering succeded (or was skipped) and `false` /// otherwise. All warinings and error messages should be logged in here. // TODO: Render GIF files as mp4 instead -fn render_thumbnail(pic: Picture) -> bool { +fn render_thumbnail(pic: GalleryEntry) -> bool { let mut thumb_path = PathBuf::from(TARGET_PATH); thumb_path.push(THUMBS_PATH); thumb_path.push(pic.file_name.clone() + ".webp");
diff --git a/src/picture.rs b/src/picture.rs @@ -1,413 +0,0 @@ -use serde::{ - de::{Deserializer, Error, Unexpected}, - Deserialize, -}; -use std::{fmt::{self, Display}, path::PathBuf}; - -const LICENSES: &'static [&'static str] = &[ - "PD", - "CC0", - "CC-BY-1", - "CC-BY-2", - "CC-BY-3", - "CC-BY-4", - "CC-BY-SA-1", - "CC-BY-SA-2", - "CC-BY-SA-3", - "CC-BY-SA-4", - "CC-BY-NC-1", - "CC-BY-NC-2", - "CC-BY-NC-3", - "CC-BY-NC-4", - "CC-BY-NC-SA-1", - "CC-BY-NC-SA-2", - "CC-BY-NC-SA-3", - "CC-BY-NC-SA-4", - "CC-BY-ND-1", - "CC-BY-ND-2", - "CC-BY-ND-3", - "CC-BY-ND-4", - "CC-BY-NC-ND-1", - "CC-BY-NC-ND-2", - "CC-BY-NC-ND-3", - "CC-BY-NC-ND-4", -]; - -/// Info on a individual entry on the gallery -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Picture { - pub path: PathBuf, - pub file_name: String, - pub alt: String, - pub caption: Option<String>, - pub license: Option<LicenseType>, - pub author: String, - pub author_url: Option<String>, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct LicenseType(CreativeCommons); - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum CreativeCommons { - /// Creative Commons (without attribution) - Cc0, - /// Creative Commons Attributions (derivatives allowed) - CcBy { - version: CreativeCommonsVersion, - non_commercial: bool, - share_alike: bool, - }, - // The ND (non-derivatives) option excludes the SA (share alike) option - /// Creative Commons Attributions Non-Derivatives - CcByNd { - version: CreativeCommonsVersion, - non_commercial: bool, - }, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum CreativeCommonsVersion { - One, - Two, - Three, - Four, -} - -impl LicenseType { - pub const fn url(&self) -> &'static str { - match self.0 { - // CC0 - CreativeCommons::Cc0 => { - "https://creativecommons.org/publicdomain/zero/1.0/" - }, - // CC-BY-1 - CreativeCommons::CcBy { - version: CreativeCommonsVersion::One, - non_commercial: false, - share_alike: false, - } => "http://creativecommons.org/licenses/by/1.0/", - // CC-BY-2 - CreativeCommons::CcBy { - version: CreativeCommonsVersion::Two, - non_commercial: false, - share_alike: false, - } => "http://creativecommons.org/licenses/by/2.0/", - // CC-BY-3 - CreativeCommons::CcBy { - version: CreativeCommonsVersion::Three, - non_commercial: false, - share_alike: false, - } => "http://creativecommons.org/licenses/by/3.0/", - // CC-BY-4 - CreativeCommons::CcBy { - version: CreativeCommonsVersion::Four, - non_commercial: false, - share_alike: false, - } => "http://creativecommons.org/licenses/by/4.0/", - // CC-BY-SA-1 - CreativeCommons::CcBy { - version: CreativeCommonsVersion::One, - non_commercial: false, - share_alike: true, - } => "http://creativecommons.org/licenses/by-sa/1.0/", - // CC-BY-SA-2 - CreativeCommons::CcBy { - version: CreativeCommonsVersion::Two, - non_commercial: false, - share_alike: true, - } => "http://creativecommons.org/licenses/by-sa/2.0/", - // CC-BY-SA-3 - CreativeCommons::CcBy { - version: CreativeCommonsVersion::Three, - non_commercial: false, - share_alike: true, - } => "http://creativecommons.org/licenses/by-sa/3.0/", - // CC-BY-SA-4 - CreativeCommons::CcBy { - version: CreativeCommonsVersion::Four, - non_commercial: false, - share_alike: true, - } => "http://creativecommons.org/licenses/by-sa/4.0/", - // CC-BY-NC-1 - CreativeCommons::CcBy { - version: CreativeCommonsVersion::One, - non_commercial: true, - share_alike: false, - } => "http://creativecommons.org/licenses/by-nc/1.0/", - // CC-BY-NC-2 - CreativeCommons::CcBy { - version: CreativeCommonsVersion::Two, - non_commercial: true, - share_alike: false, - } => "http://creativecommons.org/licenses/by-nc/2.0/", - // CC-BY-NC-3 - CreativeCommons::CcBy { - version: CreativeCommonsVersion::Three, - non_commercial: true, - share_alike: false, - } => "http://creativecommons.org/licenses/by-nc/3.0/", - // CC-BY-NC-4 - CreativeCommons::CcBy { - version: CreativeCommonsVersion::Four, - non_commercial: true, - share_alike: false, - } => "http://creativecommons.org/licenses/by-nc/4.0/", - // CC-BY-NC-SA-1 - CreativeCommons::CcBy { - version: CreativeCommonsVersion::One, - non_commercial: true, - share_alike: true, - } => "http://creativecommons.org/licenses/by-nc-sa/1.0/", - // CC-BY-NC-SA-2 - CreativeCommons::CcBy { - version: CreativeCommonsVersion::Two, - non_commercial: true, - share_alike: true, - } => "http://creativecommons.org/licenses/by-nc-sa/2.0/", - // CC-BY-NC-SA-3 - CreativeCommons::CcBy { - version: CreativeCommonsVersion::Three, - non_commercial: true, - share_alike: true, - } => "http://creativecommons.org/licenses/by-nc-sa/3.0/", - // CC-BY-NC-SA-4 - CreativeCommons::CcBy { - version: CreativeCommonsVersion::Four, - non_commercial: true, - share_alike: true, - } => "http://creativecommons.org/licenses/by-nc-sa/4.0/", - // CC-BY-ND-1 - CreativeCommons::CcByNd { - version: CreativeCommonsVersion::One, - non_commercial: false, - } => "http://creativecommons.org/licenses/by-nd/1.0/", - // CC-BY-ND-2 - CreativeCommons::CcByNd { - version: CreativeCommonsVersion::Two, - non_commercial: false, - } => "http://creativecommons.org/licenses/by-nd/2.0/", - // CC-BY-ND-3 - CreativeCommons::CcByNd { - version: CreativeCommonsVersion::Three, - non_commercial: false, - } => "http://creativecommons.org/licenses/by-nd/3.0/", - // CC-BY-ND-4 - CreativeCommons::CcByNd { - version: CreativeCommonsVersion::Four, - non_commercial: false, - } => "http://creativecommons.org/licenses/by-nd/4.0/", - // CC-BY-NC-ND-1 - CreativeCommons::CcByNd { - version: CreativeCommonsVersion::One, - non_commercial: true, - } => "http://creativecommons.org/licenses/by-nc-nd/1.0/", - // CC-BY-NC-ND-2 - CreativeCommons::CcByNd { - version: CreativeCommonsVersion::Two, - non_commercial: true, - } => "http://creativecommons.org/licenses/by-nc-nd/2.0/", - // CC-BY-NC-ND-3 - CreativeCommons::CcByNd { - version: CreativeCommonsVersion::Three, - non_commercial: true, - } => "http://creativecommons.org/licenses/by-nc-nd/3.0/", - // CC-BY-NC-ND-4 - CreativeCommons::CcByNd { - version: CreativeCommonsVersion::Four, - non_commercial: true, - } => "http://creativecommons.org/licenses/by-nc-nd/4.0/", - } - } - - pub fn parse(s: &str) -> Result<Option<Self>, ()> { - if !LICENSES.contains(&s) { - return Err(()); - } - - if s == "PD" { - return Ok(None); - } else if s == "CC0" { - return Ok(Some(Self(CreativeCommons::Cc0))); - } - - assert!(s.len() >= 3, - "if s is in LICENSES it should contain at least 3 chars"); - - let version = match &s[s.len() - 1..] { - "1" => CreativeCommonsVersion::One, - "2" => CreativeCommonsVersion::Two, - "3" => CreativeCommonsVersion::Three, - "4" => CreativeCommonsVersion::Four, - _ => { - unreachable!("if s is in LICENSES we should be able to parse the license version") - }, - }; - - match &s[..s.len() - 1] { - "CC-BY-" => { - Ok( - Some( - Self( - CreativeCommons::CcBy { - version, - non_commercial: false, - share_alike: false, - } - ) - ) - ) - }, - "CC-BY-NC-" => { - Ok( - Some( - Self( - CreativeCommons::CcBy { - version, - non_commercial: true, - share_alike: false, - } - ) - ) - ) - }, - "CC-BY-SA-" => { - Ok( - Some( - Self( - CreativeCommons::CcBy { - version, - non_commercial: false, - share_alike: true, - } - ) - ) - ) - }, - "CC-BY-NC-SA-" => { - Ok( - Some( - Self( - CreativeCommons::CcBy { - version, - non_commercial: true, - share_alike: true, - } - ) - ) - ) - }, - "CC-BY-ND-" => { - Ok( - Some( - Self( - CreativeCommons::CcByNd { - version, - non_commercial: false, - } - ) - ) - ) - }, - "CC-BY-NC-ND-" => { - Ok( - Some( - Self( - CreativeCommons::CcByNd { - version, - non_commercial: true, - } - ) - ) - ) - }, - _ => { - unreachable!("if s is in LICENSES we should be able to parse the license-type") - }, - } - } -} - -impl<'de> Deserialize<'de> for Picture { - fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> - where - D: Deserializer<'de>, - { - #[derive(Deserialize)] - struct Info { - path: String, - alt: String, - caption: Option<String>, - license: String, - author: String, - #[serde(alias = "author-url")] - author_url: Option<String>, - } - - let Info { - path: path_str, - alt, - caption, - license, - author, - author_url, - } = Info::deserialize(deserializer)?; - - let license = LicenseType::parse(&license) - .map_err(|_| D::Error::unknown_variant(&license, LICENSES))?; - let path = PathBuf::from(&path_str); - - if let Some(file_name) = path.file_name().and_then(|s| s.to_str()) { - Ok(Self { - path: path.clone(), - alt: alt.trim().to_string(), - file_name: String::from(file_name), - caption, - author: author.trim().to_string(), - author_url: author_url.map(|s| s.trim().to_string()), - license, - }) - } else { - Err(D::Error::invalid_value( - Unexpected::Str(&path_str), - &"valid file path (couldn't extract file name)", - )) - } - } -} - -impl Display for LicenseType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - match self.0 { - CreativeCommons::Cc0 => write!(f, "CC0"), - CreativeCommons::CcBy { version, non_commercial, share_alike } => { - write!(f, "CC-BY")?; - if non_commercial { - write!(f, "-NC")?; - } - if share_alike { - write!(f, "-SA")?; - } - write!(f, " {version}") - }, - CreativeCommons::CcByNd { version, non_commercial } => { - write!(f, "CC-BY")?; - if non_commercial { - write!(f, "-NC")?; - } - write!(f, "-ND {version}") - } - } - } -} - -impl Display for CreativeCommonsVersion { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - match self { - CreativeCommonsVersion::One => write!(f, "1.0"), - CreativeCommonsVersion::Two => write!(f, "2.0"), - CreativeCommonsVersion::Three => write!(f, "3.0"), - CreativeCommonsVersion::Four => write!(f, "4.0"), - } - } -}