- Commit
- b68e180a1f3e8c9ff6e012df1b4498b6b3de24f1
- Parent
- ccdb0dcabc52c30aeffde118f2a72e90c377e201
- Author
- Pablo <pablo-escobar@riseup.net>
- Date
Renamed the Picture type to GalleryEntry
Also renamed the corresponding module
Custum build of stapix for tikz.pablopie.xyz
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"), - } - } -}