Use the Deserialize trait for JSON just like for MusicBrainz (#197)
Closes #195 Reviewed-on: #197
This commit is contained in:
parent
43961b3ea1
commit
f82a6376e0
2
src/external/database/json/mod.rs
vendored
2
src/external/database/json/mod.rs
vendored
@ -51,7 +51,7 @@ impl<JDB: IJsonDatabaseBackend> IDatabase for JsonDatabase<JDB> {
|
|||||||
fn load(&self) -> Result<Collection, LoadError> {
|
fn load(&self) -> Result<Collection, LoadError> {
|
||||||
let serialized = self.backend.read()?;
|
let serialized = self.backend.read()?;
|
||||||
let database: DeserializeDatabase = serde_json::from_str(&serialized)?;
|
let database: DeserializeDatabase = serde_json::from_str(&serialized)?;
|
||||||
database.try_into()
|
Ok(database.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save(&mut self, collection: &Collection) -> Result<(), SaveError> {
|
fn save(&mut self, collection: &Collection) -> Result<(), SaveError> {
|
||||||
|
14
src/external/database/json/testmod.rs
vendored
14
src/external/database/json/testmod.rs
vendored
@ -1,10 +1,10 @@
|
|||||||
pub static DATABASE_JSON: &str = "{\
|
pub static DATABASE_JSON: &str = "{\
|
||||||
\"V20240313\":\
|
\"V20240828\":\
|
||||||
[\
|
[\
|
||||||
{\
|
{\
|
||||||
\"name\":\"Album_Artist ‘A’\",\
|
\"name\":\"Album_Artist ‘A’\",\
|
||||||
\"sort\":null,\
|
\"sort\":null,\
|
||||||
\"musicbrainz\":\"https://musicbrainz.org/artist/00000000-0000-0000-0000-000000000000\",\
|
\"musicbrainz\":\"00000000-0000-0000-0000-000000000000\",\
|
||||||
\"properties\":{\
|
\"properties\":{\
|
||||||
\"MusicButler\":[\"https://www.musicbutler.io/artist-page/000000000\"],\
|
\"MusicButler\":[\"https://www.musicbutler.io/artist-page/000000000\"],\
|
||||||
\"Qobuz\":[\"https://www.qobuz.com/nl-nl/interpreter/artist-a/download-streaming-albums\"]\
|
\"Qobuz\":[\"https://www.qobuz.com/nl-nl/interpreter/artist-a/download-streaming-albums\"]\
|
||||||
@ -12,7 +12,7 @@ pub static DATABASE_JSON: &str = "{\
|
|||||||
\"albums\":[\
|
\"albums\":[\
|
||||||
{\
|
{\
|
||||||
\"title\":\"album_title a.a\",\"seq\":1,\
|
\"title\":\"album_title a.a\",\"seq\":1,\
|
||||||
\"musicbrainz\":\"https://musicbrainz.org/release-group/00000000-0000-0000-0000-000000000000\",\
|
\"musicbrainz\":\"00000000-0000-0000-0000-000000000000\",\
|
||||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||||
},\
|
},\
|
||||||
{\
|
{\
|
||||||
@ -24,7 +24,7 @@ pub static DATABASE_JSON: &str = "{\
|
|||||||
{\
|
{\
|
||||||
\"name\":\"Album_Artist ‘B’\",\
|
\"name\":\"Album_Artist ‘B’\",\
|
||||||
\"sort\":null,\
|
\"sort\":null,\
|
||||||
\"musicbrainz\":\"https://musicbrainz.org/artist/11111111-1111-1111-1111-111111111111\",\
|
\"musicbrainz\":\"11111111-1111-1111-1111-111111111111\",\
|
||||||
\"properties\":{\
|
\"properties\":{\
|
||||||
\"Bandcamp\":[\"https://artist-b.bandcamp.com/\"],\
|
\"Bandcamp\":[\"https://artist-b.bandcamp.com/\"],\
|
||||||
\"MusicButler\":[\
|
\"MusicButler\":[\
|
||||||
@ -40,12 +40,12 @@ pub static DATABASE_JSON: &str = "{\
|
|||||||
},\
|
},\
|
||||||
{\
|
{\
|
||||||
\"title\":\"album_title b.b\",\"seq\":3,\
|
\"title\":\"album_title b.b\",\"seq\":3,\
|
||||||
\"musicbrainz\":\"https://musicbrainz.org/release-group/11111111-1111-1111-1111-111111111111\",\
|
\"musicbrainz\":\"11111111-1111-1111-1111-111111111111\",\
|
||||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||||
},\
|
},\
|
||||||
{\
|
{\
|
||||||
\"title\":\"album_title b.c\",\"seq\":2,\
|
\"title\":\"album_title b.c\",\"seq\":2,\
|
||||||
\"musicbrainz\":\"https://musicbrainz.org/release-group/11111111-1111-1111-1111-111111111112\",\
|
\"musicbrainz\":\"11111111-1111-1111-1111-111111111112\",\
|
||||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||||
},\
|
},\
|
||||||
{\
|
{\
|
||||||
@ -57,7 +57,7 @@ pub static DATABASE_JSON: &str = "{\
|
|||||||
{\
|
{\
|
||||||
\"name\":\"The Album_Artist ‘C’\",\
|
\"name\":\"The Album_Artist ‘C’\",\
|
||||||
\"sort\":\"Album_Artist ‘C’, The\",\
|
\"sort\":\"Album_Artist ‘C’, The\",\
|
||||||
\"musicbrainz\":\"https://musicbrainz.org/artist/11111111-1111-1111-1111-111111111111\",\
|
\"musicbrainz\":\"11111111-1111-1111-1111-111111111111\",\
|
||||||
\"properties\":{},\
|
\"properties\":{},\
|
||||||
\"albums\":[\
|
\"albums\":[\
|
||||||
{\
|
{\
|
||||||
|
10
src/external/database/serde/common.rs
vendored
10
src/external/database/serde/common.rs
vendored
@ -4,7 +4,7 @@ use crate::core::collection::album::{AlbumPrimaryType, AlbumSecondaryType};
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(remote = "AlbumPrimaryType")]
|
#[serde(remote = "AlbumPrimaryType")]
|
||||||
pub enum SerdeAlbumPrimaryTypeDef {
|
pub enum AlbumPrimaryTypeDef {
|
||||||
Album,
|
Album,
|
||||||
Single,
|
Single,
|
||||||
Ep,
|
Ep,
|
||||||
@ -13,7 +13,7 @@ pub enum SerdeAlbumPrimaryTypeDef {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct SerdeAlbumPrimaryType(#[serde(with = "SerdeAlbumPrimaryTypeDef")] AlbumPrimaryType);
|
pub struct SerdeAlbumPrimaryType(#[serde(with = "AlbumPrimaryTypeDef")] AlbumPrimaryType);
|
||||||
|
|
||||||
impl From<SerdeAlbumPrimaryType> for AlbumPrimaryType {
|
impl From<SerdeAlbumPrimaryType> for AlbumPrimaryType {
|
||||||
fn from(value: SerdeAlbumPrimaryType) -> Self {
|
fn from(value: SerdeAlbumPrimaryType) -> Self {
|
||||||
@ -29,7 +29,7 @@ impl From<AlbumPrimaryType> for SerdeAlbumPrimaryType {
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(remote = "AlbumSecondaryType")]
|
#[serde(remote = "AlbumSecondaryType")]
|
||||||
pub enum SerdeAlbumSecondaryTypeDef {
|
pub enum AlbumSecondaryTypeDef {
|
||||||
Compilation,
|
Compilation,
|
||||||
Soundtrack,
|
Soundtrack,
|
||||||
Spokenword,
|
Spokenword,
|
||||||
@ -45,9 +45,7 @@ pub enum SerdeAlbumSecondaryTypeDef {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct SerdeAlbumSecondaryType(
|
pub struct SerdeAlbumSecondaryType(#[serde(with = "AlbumSecondaryTypeDef")] AlbumSecondaryType);
|
||||||
#[serde(with = "SerdeAlbumSecondaryTypeDef")] AlbumSecondaryType,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl From<SerdeAlbumSecondaryType> for AlbumSecondaryType {
|
impl From<SerdeAlbumSecondaryType> for AlbumSecondaryType {
|
||||||
fn from(value: SerdeAlbumSecondaryType) -> Self {
|
fn from(value: SerdeAlbumSecondaryType) -> Self {
|
||||||
|
186
src/external/database/serde/deserialize.rs
vendored
186
src/external/database/serde/deserialize.rs
vendored
@ -1,32 +1,27 @@
|
|||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, fmt};
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::{de::Visitor, Deserialize, Deserializer};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{
|
core::collection::{
|
||||||
collection::{
|
album::{Album, AlbumDate, AlbumId, AlbumSeq},
|
||||||
album::{Album, AlbumDate, AlbumId, AlbumSeq},
|
artist::{Artist, ArtistId},
|
||||||
artist::{Artist, ArtistId},
|
musicbrainz::{MbAlbumRef, MbArtistRef},
|
||||||
musicbrainz::{MbAlbumRef, MbArtistRef},
|
Collection, Error as CollectionError,
|
||||||
Collection,
|
|
||||||
},
|
|
||||||
interface::database::LoadError,
|
|
||||||
},
|
},
|
||||||
external::database::serde::common::{SerdeAlbumPrimaryType, SerdeAlbumSecondaryType},
|
external::database::serde::common::{SerdeAlbumPrimaryType, SerdeAlbumSecondaryType},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub enum DeserializeDatabase {
|
pub enum DeserializeDatabase {
|
||||||
V20240313(Vec<DeserializeArtist>),
|
V20240828(Vec<DeserializeArtist>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<DeserializeDatabase> for Collection {
|
impl From<DeserializeDatabase> for Collection {
|
||||||
type Error = LoadError;
|
fn from(database: DeserializeDatabase) -> Self {
|
||||||
|
|
||||||
fn try_from(database: DeserializeDatabase) -> Result<Self, Self::Error> {
|
|
||||||
match database {
|
match database {
|
||||||
DeserializeDatabase::V20240313(collection) => {
|
DeserializeDatabase::V20240828(collection) => {
|
||||||
collection.into_iter().map(TryInto::try_into).collect()
|
collection.into_iter().map(Into::into).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,7 +31,7 @@ impl TryFrom<DeserializeDatabase> for Collection {
|
|||||||
pub struct DeserializeArtist {
|
pub struct DeserializeArtist {
|
||||||
name: String,
|
name: String,
|
||||||
sort: Option<String>,
|
sort: Option<String>,
|
||||||
musicbrainz: Option<String>,
|
musicbrainz: Option<DeserializeMbArtistRef>,
|
||||||
properties: HashMap<String, Vec<String>>,
|
properties: HashMap<String, Vec<String>>,
|
||||||
albums: Vec<DeserializeAlbum>,
|
albums: Vec<DeserializeAlbum>,
|
||||||
}
|
}
|
||||||
@ -45,47 +40,148 @@ pub struct DeserializeArtist {
|
|||||||
pub struct DeserializeAlbum {
|
pub struct DeserializeAlbum {
|
||||||
title: String,
|
title: String,
|
||||||
seq: u8,
|
seq: u8,
|
||||||
musicbrainz: Option<String>,
|
musicbrainz: Option<DeserializeMbAlbumRef>,
|
||||||
primary_type: Option<SerdeAlbumPrimaryType>,
|
primary_type: Option<SerdeAlbumPrimaryType>,
|
||||||
secondary_types: Vec<SerdeAlbumSecondaryType>,
|
secondary_types: Vec<SerdeAlbumSecondaryType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<DeserializeArtist> for Artist {
|
#[derive(Clone, Debug)]
|
||||||
type Error = LoadError;
|
pub struct DeserializeMbArtistRef(MbArtistRef);
|
||||||
|
|
||||||
fn try_from(artist: DeserializeArtist) -> Result<Self, Self::Error> {
|
impl From<DeserializeMbArtistRef> for MbArtistRef {
|
||||||
Ok(Artist {
|
fn from(value: DeserializeMbArtistRef) -> Self {
|
||||||
id: ArtistId::new(artist.name),
|
value.0
|
||||||
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::<Result<Vec<Album>, LoadError>>()?,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<DeserializeAlbum> for Album {
|
struct DeserializeMbArtistRefVisitor;
|
||||||
type Error = LoadError;
|
|
||||||
|
|
||||||
fn try_from(album: DeserializeAlbum) -> Result<Self, Self::Error> {
|
impl<'de> Visitor<'de> for DeserializeMbArtistRefVisitor {
|
||||||
Ok(Album {
|
type Value = DeserializeMbArtistRef;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("a valid MusicBrainz identifier")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
Ok(DeserializeMbArtistRef(
|
||||||
|
MbArtistRef::from_uuid_str(v).map_err(|e: CollectionError| E::custom(e.to_string()))?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for DeserializeMbArtistRef {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
deserializer.deserialize_str(DeserializeMbArtistRefVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct DeserializeMbAlbumRef(MbAlbumRef);
|
||||||
|
|
||||||
|
impl From<DeserializeMbAlbumRef> 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<E>(self, v: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
Ok(DeserializeMbAlbumRef(
|
||||||
|
MbAlbumRef::from_uuid_str(v).map_err(|e: CollectionError| E::custom(e.to_string()))?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for DeserializeMbAlbumRef {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
deserializer.deserialize_str(DeserializeMbAlbumRefVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DeserializeArtist> 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<DeserializeAlbum> for Album {
|
||||||
|
fn from(album: DeserializeAlbum) -> Self {
|
||||||
|
Album {
|
||||||
id: AlbumId { title: album.title },
|
id: AlbumId { title: album.title },
|
||||||
date: AlbumDate::default(),
|
date: AlbumDate::default(),
|
||||||
seq: AlbumSeq(album.seq),
|
seq: AlbumSeq(album.seq),
|
||||||
musicbrainz: album
|
musicbrainz: album.musicbrainz.map(Into::into),
|
||||||
.musicbrainz
|
|
||||||
.map(MbAlbumRef::from_url_str)
|
|
||||||
.transpose()?,
|
|
||||||
primary_type: album.primary_type.map(Into::into),
|
primary_type: album.primary_type.map(Into::into),
|
||||||
secondary_types: album.secondary_types.into_iter().map(Into::into).collect(),
|
secondary_types: album.secondary_types.into_iter().map(Into::into).collect(),
|
||||||
tracks: vec![],
|
tracks: vec![],
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deserialize_mb_artist_ref() {
|
||||||
|
let mbid = "\"d368baa8-21ca-4759-9731-0b2753071ad8\"";
|
||||||
|
let mbref: DeserializeMbArtistRef = serde_json::from_str(mbid).unwrap();
|
||||||
|
let mbref: MbArtistRef = mbref.into();
|
||||||
|
assert_eq!(
|
||||||
|
mbref,
|
||||||
|
MbArtistRef::from_uuid_str("d368baa8-21ca-4759-9731-0b2753071ad8").unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let mbid = "null";
|
||||||
|
let result: Result<DeserializeMbArtistRef, _> = serde_json::from_str(mbid);
|
||||||
|
assert!(result
|
||||||
|
.unwrap_err()
|
||||||
|
.to_string()
|
||||||
|
.contains("a valid MusicBrainz identifier"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deserialize_mb_album_ref() {
|
||||||
|
let mbid = "\"d368baa8-21ca-4759-9731-0b2753071ad8\"";
|
||||||
|
let mbref: DeserializeMbAlbumRef = serde_json::from_str(mbid).unwrap();
|
||||||
|
let mbref: MbAlbumRef = mbref.into();
|
||||||
|
assert_eq!(
|
||||||
|
mbref,
|
||||||
|
MbAlbumRef::from_uuid_str("d368baa8-21ca-4759-9731-0b2753071ad8").unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let mbid = "null";
|
||||||
|
let result: Result<DeserializeMbAlbumRef, _> = serde_json::from_str(mbid);
|
||||||
|
assert!(result
|
||||||
|
.unwrap_err()
|
||||||
|
.to_string()
|
||||||
|
.contains("a valid MusicBrainz identifier"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
37
src/external/database/serde/serialize.rs
vendored
37
src/external/database/serde/serialize.rs
vendored
@ -3,18 +3,19 @@ use std::collections::BTreeMap;
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
collection::musicbrainz::{MbAlbumRef, MbArtistRef},
|
||||||
core::collection::{album::Album, artist::Artist, musicbrainz::IMusicBrainzRef, Collection},
|
core::collection::{album::Album, artist::Artist, musicbrainz::IMusicBrainzRef, Collection},
|
||||||
external::database::serde::common::{SerdeAlbumPrimaryType, SerdeAlbumSecondaryType},
|
external::database::serde::common::{SerdeAlbumPrimaryType, SerdeAlbumSecondaryType},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub enum SerializeDatabase<'a> {
|
pub enum SerializeDatabase<'a> {
|
||||||
V20240313(Vec<SerializeArtist<'a>>),
|
V20240828(Vec<SerializeArtist<'a>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a Collection> for SerializeDatabase<'a> {
|
impl<'a> From<&'a Collection> for SerializeDatabase<'a> {
|
||||||
fn from(collection: &'a Collection) -> Self {
|
fn from(collection: &'a Collection) -> Self {
|
||||||
SerializeDatabase::V20240313(collection.iter().map(Into::into).collect())
|
SerializeDatabase::V20240828(collection.iter().map(Into::into).collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ impl<'a> From<&'a Collection> for SerializeDatabase<'a> {
|
|||||||
pub struct SerializeArtist<'a> {
|
pub struct SerializeArtist<'a> {
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
sort: Option<&'a str>,
|
sort: Option<&'a str>,
|
||||||
musicbrainz: Option<&'a str>,
|
musicbrainz: Option<SerializeMbArtistRef<'a>>,
|
||||||
properties: BTreeMap<&'a str, &'a Vec<String>>,
|
properties: BTreeMap<&'a str, &'a Vec<String>>,
|
||||||
albums: Vec<SerializeAlbum<'a>>,
|
albums: Vec<SerializeAlbum<'a>>,
|
||||||
}
|
}
|
||||||
@ -31,17 +32,41 @@ pub struct SerializeArtist<'a> {
|
|||||||
pub struct SerializeAlbum<'a> {
|
pub struct SerializeAlbum<'a> {
|
||||||
title: &'a str,
|
title: &'a str,
|
||||||
seq: u8,
|
seq: u8,
|
||||||
musicbrainz: Option<&'a str>,
|
musicbrainz: Option<SerializeMbAlbumRef<'a>>,
|
||||||
primary_type: Option<SerdeAlbumPrimaryType>,
|
primary_type: Option<SerdeAlbumPrimaryType>,
|
||||||
secondary_types: Vec<SerdeAlbumSecondaryType>,
|
secondary_types: Vec<SerdeAlbumSecondaryType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct SerializeMbArtistRef<'a>(&'a MbArtistRef);
|
||||||
|
|
||||||
|
impl<'a> Serialize for SerializeMbArtistRef<'a> {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_str(&self.0.mbid().uuid().as_hyphenated().to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct SerializeMbAlbumRef<'a>(&'a MbAlbumRef);
|
||||||
|
|
||||||
|
impl<'a> Serialize for SerializeMbAlbumRef<'a> {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_str(&self.0.mbid().uuid().as_hyphenated().to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a Artist> for SerializeArtist<'a> {
|
impl<'a> From<&'a Artist> for SerializeArtist<'a> {
|
||||||
fn from(artist: &'a Artist) -> Self {
|
fn from(artist: &'a Artist) -> Self {
|
||||||
SerializeArtist {
|
SerializeArtist {
|
||||||
name: &artist.id.name,
|
name: &artist.id.name,
|
||||||
sort: artist.sort.as_ref().map(|id| id.name.as_ref()),
|
sort: artist.sort.as_ref().map(|id| id.name.as_ref()),
|
||||||
musicbrainz: artist.musicbrainz.as_ref().map(|mb| mb.url().as_str()),
|
musicbrainz: artist.musicbrainz.as_ref().map(SerializeMbArtistRef),
|
||||||
properties: artist
|
properties: artist
|
||||||
.properties
|
.properties
|
||||||
.iter()
|
.iter()
|
||||||
@ -57,7 +82,7 @@ impl<'a> From<&'a Album> for SerializeAlbum<'a> {
|
|||||||
SerializeAlbum {
|
SerializeAlbum {
|
||||||
title: &album.id.title,
|
title: &album.id.title,
|
||||||
seq: album.seq.0,
|
seq: album.seq.0,
|
||||||
musicbrainz: album.musicbrainz.as_ref().map(|mb| mb.url().as_str()),
|
musicbrainz: album.musicbrainz.as_ref().map(SerializeMbAlbumRef),
|
||||||
primary_type: album.primary_type.map(Into::into),
|
primary_type: album.primary_type.map(Into::into),
|
||||||
secondary_types: album
|
secondary_types: album
|
||||||
.secondary_types
|
.secondary_types
|
||||||
|
@ -1 +1 @@
|
|||||||
{"V20240313":[{"name":"Аркона","sort":"Arkona","musicbrainz":"https://musicbrainz.org/artist/baad262d-55ef-427a-83c7-f7530964f212","properties":{"Bandcamp":["https://arkonamoscow.bandcamp.com/"],"MusicButler":["https://www.musicbutler.io/artist-page/283448581"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/arkona/download-streaming-albums"]},"albums":[{"title":"Slovo","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":[]}]},{"name":"Eluveitie","sort":null,"musicbrainz":"https://musicbrainz.org/artist/8000598a-5edb-401c-8e6d-36b167feaf38","properties":{"MusicButler":["https://www.musicbutler.io/artist-page/269358403"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/eluveitie/download-streaming-albums"]},"albums":[{"title":"Vên [re‐recorded]","seq":0,"musicbrainz":null,"primary_type":"Ep","secondary_types":[]},{"title":"Slania","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":[]}]},{"name":"Frontside","sort":null,"musicbrainz":"https://musicbrainz.org/artist/3a901353-fccd-4afd-ad01-9c03f451b490","properties":{"MusicButler":["https://www.musicbutler.io/artist-page/826588800"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/frontside/download-streaming-albums"]},"albums":[{"title":"…nasze jest królestwo, potęga i chwała na wieki…","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":[]}]},{"name":"Heaven’s Basement","sort":"Heaven’s Basement","musicbrainz":"https://musicbrainz.org/artist/c2c4d56a-d599-4a18-bd2f-ae644e2198cc","properties":{"MusicButler":["https://www.musicbutler.io/artist-page/291158685"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/heaven-s-basement/download-streaming-albums"]},"albums":[{"title":"Paper Plague","seq":0,"musicbrainz":null,"primary_type":null,"secondary_types":[]},{"title":"Unbreakable","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":[]}]},{"name":"Metallica","sort":null,"musicbrainz":"https://musicbrainz.org/artist/65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab","properties":{"MusicButler":["https://www.musicbutler.io/artist-page/3996865"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/metallica/download-streaming-albums"]},"albums":[{"title":"Ride the Lightning","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":[]},{"title":"S&M","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":["Live"]}]}]}
|
{"V20240828":[{"name":"Аркона","sort":"Arkona","musicbrainz":"baad262d-55ef-427a-83c7-f7530964f212","properties":{"Bandcamp":["https://arkonamoscow.bandcamp.com/"],"MusicButler":["https://www.musicbutler.io/artist-page/283448581"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/arkona/download-streaming-albums"]},"albums":[{"title":"Slovo","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":[]}]},{"name":"Eluveitie","sort":null,"musicbrainz":"8000598a-5edb-401c-8e6d-36b167feaf38","properties":{"MusicButler":["https://www.musicbutler.io/artist-page/269358403"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/eluveitie/download-streaming-albums"]},"albums":[{"title":"Vên [re‐recorded]","seq":0,"musicbrainz":null,"primary_type":"Ep","secondary_types":[]},{"title":"Slania","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":[]}]},{"name":"Frontside","sort":null,"musicbrainz":"3a901353-fccd-4afd-ad01-9c03f451b490","properties":{"MusicButler":["https://www.musicbutler.io/artist-page/826588800"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/frontside/download-streaming-albums"]},"albums":[{"title":"…nasze jest królestwo, potęga i chwała na wieki…","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":[]}]},{"name":"Heaven’s Basement","sort":"Heaven’s Basement","musicbrainz":"c2c4d56a-d599-4a18-bd2f-ae644e2198cc","properties":{"MusicButler":["https://www.musicbutler.io/artist-page/291158685"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/heaven-s-basement/download-streaming-albums"]},"albums":[{"title":"Paper Plague","seq":0,"musicbrainz":null,"primary_type":null,"secondary_types":[]},{"title":"Unbreakable","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":[]}]},{"name":"Metallica","sort":null,"musicbrainz":"65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab","properties":{"MusicButler":["https://www.musicbutler.io/artist-page/3996865"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/metallica/download-streaming-albums"]},"albums":[{"title":"Ride the Lightning","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":[]},{"title":"S&M","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":["Live"]}]}]}
|
Loading…
Reference in New Issue
Block a user