diff --git a/src/external/database/json/mod.rs b/src/external/database/json/mod.rs index b791203..3347c5c 100644 --- a/src/external/database/json/mod.rs +++ b/src/external/database/json/mod.rs @@ -51,7 +51,7 @@ impl IDatabase for JsonDatabase { fn load(&self) -> Result { let serialized = self.backend.read()?; let database: DeserializeDatabase = serde_json::from_str(&serialized)?; - database.try_into() + Ok(database.into()) } fn save(&mut self, collection: &Collection) -> Result<(), SaveError> { diff --git a/src/external/database/serde/deserialize.rs b/src/external/database/serde/deserialize.rs index 84e742c..6a1f731 100644 --- a/src/external/database/serde/deserialize.rs +++ b/src/external/database/serde/deserialize.rs @@ -1,16 +1,13 @@ -use std::collections::HashMap; +use std::{collections::HashMap, fmt}; -use serde::Deserialize; +use serde::{de::Visitor, Deserialize, Deserializer}; use crate::{ - core::{ - collection::{ - album::{Album, AlbumDate, AlbumId, AlbumSeq}, - artist::{Artist, ArtistId}, - musicbrainz::{MbAlbumRef, MbArtistRef}, - Collection, - }, - interface::database::LoadError, + core::collection::{ + album::{Album, AlbumDate, AlbumId, AlbumSeq}, + artist::{Artist, ArtistId}, + musicbrainz::{MbAlbumRef, MbArtistRef}, + Collection, Error as CollectionError, }, external::database::serde::common::{SerdeAlbumPrimaryType, SerdeAlbumSecondaryType}, }; @@ -20,13 +17,11 @@ pub enum DeserializeDatabase { V20240313(Vec), } -impl TryFrom for Collection { - type Error = LoadError; - - fn try_from(database: DeserializeDatabase) -> Result { +impl From for Collection { + fn from(database: DeserializeDatabase) -> Self { match database { DeserializeDatabase::V20240313(collection) => { - collection.into_iter().map(TryInto::try_into).collect() + collection.into_iter().map(Into::into).collect() } } } @@ -36,7 +31,7 @@ impl TryFrom for Collection { pub struct DeserializeArtist { name: String, sort: Option, - musicbrainz: Option, + musicbrainz: Option, properties: HashMap>, albums: Vec, } @@ -45,47 +40,107 @@ pub struct DeserializeArtist { pub struct DeserializeAlbum { title: String, seq: u8, - musicbrainz: Option, + musicbrainz: Option, primary_type: Option, secondary_types: Vec, } -impl TryFrom for Artist { - type Error = LoadError; +#[derive(Clone, Debug)] +pub struct DeserializeMbArtistRef(MbArtistRef); - fn try_from(artist: DeserializeArtist) -> Result { - Ok(Artist { - id: ArtistId::new(artist.name), - sort: artist.sort.map(ArtistId::new), - musicbrainz: artist - .musicbrainz - .map(MbArtistRef::from_url_str) - .transpose()?, - properties: artist.properties, - albums: artist - .albums - .into_iter() - .map(TryInto::try_into) - .collect::, LoadError>>()?, - }) +impl From for MbArtistRef { + fn from(value: DeserializeMbArtistRef) -> Self { + value.0 } } -impl TryFrom for Album { - type Error = LoadError; +struct DeserializeMbArtistRefVisitor; - fn try_from(album: DeserializeAlbum) -> Result { - Ok(Album { +impl<'de> Visitor<'de> for DeserializeMbArtistRefVisitor { + type Value = DeserializeMbArtistRef; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a valid MusicBrainz identifier") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + Ok(DeserializeMbArtistRef( + MbArtistRef::from_url_str(v).map_err(|e: CollectionError| E::custom(e.to_string()))?, + )) + } +} + +impl<'de> Deserialize<'de> for DeserializeMbArtistRef { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(DeserializeMbArtistRefVisitor) + } +} + +#[derive(Clone, Debug)] +pub struct DeserializeMbAlbumRef(MbAlbumRef); + +impl From for MbAlbumRef { + fn from(value: DeserializeMbAlbumRef) -> Self { + value.0 + } +} + +struct DeserializeMbAlbumRefVisitor; + +impl<'de> Visitor<'de> for DeserializeMbAlbumRefVisitor { + type Value = DeserializeMbAlbumRef; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a valid MusicBrainz identifier") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + Ok(DeserializeMbAlbumRef( + MbAlbumRef::from_url_str(v).map_err(|e: CollectionError| E::custom(e.to_string()))?, + )) + } +} + +impl<'de> Deserialize<'de> for DeserializeMbAlbumRef { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(DeserializeMbAlbumRefVisitor) + } +} + +impl From for Artist { + fn from(artist: DeserializeArtist) -> Self { + Artist { + id: ArtistId::new(artist.name), + sort: artist.sort.map(ArtistId::new), + musicbrainz: artist.musicbrainz.map(Into::into), + properties: artist.properties, + albums: artist.albums.into_iter().map(Into::into).collect(), + } + } +} + +impl From for Album { + fn from(album: DeserializeAlbum) -> Self { + Album { id: AlbumId { title: album.title }, date: AlbumDate::default(), seq: AlbumSeq(album.seq), - musicbrainz: album - .musicbrainz - .map(MbAlbumRef::from_url_str) - .transpose()?, + musicbrainz: album.musicbrainz.map(Into::into), primary_type: album.primary_type.map(Into::into), secondary_types: album.secondary_types.into_iter().map(Into::into).collect(), tracks: vec![], - }) + } } } diff --git a/src/external/database/serde/serialize.rs b/src/external/database/serde/serialize.rs index e54fda0..1b1d5f8 100644 --- a/src/external/database/serde/serialize.rs +++ b/src/external/database/serde/serialize.rs @@ -23,7 +23,7 @@ impl<'a> From<&'a Collection> for SerializeDatabase<'a> { pub struct SerializeArtist<'a> { name: &'a str, sort: Option<&'a str>, - musicbrainz: Option>, + musicbrainz: Option>, properties: BTreeMap<&'a str, &'a Vec>, albums: Vec>, } @@ -32,15 +32,15 @@ pub struct SerializeArtist<'a> { pub struct SerializeAlbum<'a> { title: &'a str, seq: u8, - musicbrainz: Option>, + musicbrainz: Option>, primary_type: Option, secondary_types: Vec, } #[derive(Clone, Debug)] -pub struct SerdeMbArtistRef<'a>(&'a MbArtistRef); +pub struct SerializeMbArtistRef<'a>(&'a MbArtistRef); -impl<'a> Serialize for SerdeMbArtistRef<'a> { +impl<'a> Serialize for SerializeMbArtistRef<'a> { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -50,9 +50,9 @@ impl<'a> Serialize for SerdeMbArtistRef<'a> { } #[derive(Clone, Debug)] -pub struct SerdeMbAlbumRef<'a>(&'a MbAlbumRef); +pub struct SerializeMbAlbumRef<'a>(&'a MbAlbumRef); -impl<'a> Serialize for SerdeMbAlbumRef<'a> { +impl<'a> Serialize for SerializeMbAlbumRef<'a> { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -66,7 +66,10 @@ impl<'a> From<&'a Artist> for SerializeArtist<'a> { SerializeArtist { name: &artist.id.name, sort: artist.sort.as_ref().map(|id| id.name.as_ref()), - musicbrainz: artist.musicbrainz.as_ref().map(|mb| SerdeMbArtistRef(mb)), + musicbrainz: artist + .musicbrainz + .as_ref() + .map(|mb| SerializeMbArtistRef(mb)), properties: artist .properties .iter() @@ -82,7 +85,7 @@ impl<'a> From<&'a Album> for SerializeAlbum<'a> { SerializeAlbum { title: &album.id.title, seq: album.seq.0, - musicbrainz: album.musicbrainz.as_ref().map(|mb| SerdeMbAlbumRef(mb)), + musicbrainz: album.musicbrainz.as_ref().map(|mb| SerializeMbAlbumRef(mb)), primary_type: album.primary_type.map(Into::into), secondary_types: album .secondary_types