Compare commits

...

4 Commits

Author SHA1 Message Date
2a32fc8ea7 Add info as substruct for Album as well
Some checks failed
Cargo CI / Build and Test (pull_request) Failing after 1m48s
Cargo CI / Lint (pull_request) Successful in 1m7s
2024-09-28 11:52:17 +02:00
ec0076fb76 Use the new info struct 2024-09-28 11:03:27 +02:00
32b09b2f52 Add info as substruct of meta 2024-09-28 10:48:45 +02:00
50779e2a32 Sort name is a string not an artist id 2024-09-28 10:12:19 +02:00
25 changed files with 527 additions and 628 deletions

View File

@ -171,10 +171,7 @@ impl SortCommand {
fn handle(self, music_hoard: &mut MH, artist_name: &str) { fn handle(self, music_hoard: &mut MH, artist_name: &str) {
match self { match self {
SortCommand::Set(artist_sort_value) => music_hoard SortCommand::Set(artist_sort_value) => music_hoard
.set_artist_sort( .set_artist_sort(ArtistId::new(artist_name), artist_sort_value.sort)
ArtistId::new(artist_name),
ArtistId::new(artist_sort_value.sort),
)
.expect("faild to set artist sort name"), .expect("faild to set artist sort name"),
SortCommand::Clear => music_hoard SortCommand::Clear => music_hoard
.clear_artist_sort(ArtistId::new(artist_name)) .clear_artist_sort(ArtistId::new(artist_name))

View File

@ -22,6 +22,12 @@ pub struct AlbumMeta {
pub id: AlbumId, pub id: AlbumId,
pub date: AlbumDate, pub date: AlbumDate,
pub seq: AlbumSeq, pub seq: AlbumSeq,
pub info: AlbumInfo,
}
/// Album non-identifier metadata.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AlbumInfo {
pub musicbrainz: MbRefOption<MbAlbumRef>, pub musicbrainz: MbRefOption<MbAlbumRef>,
pub primary_type: Option<AlbumPrimaryType>, pub primary_type: Option<AlbumPrimaryType>,
pub secondary_types: Vec<AlbumSecondaryType>, pub secondary_types: Vec<AlbumSecondaryType>,
@ -144,8 +150,9 @@ impl Album {
primary_type: Option<AlbumPrimaryType>, primary_type: Option<AlbumPrimaryType>,
secondary_types: Vec<AlbumSecondaryType>, secondary_types: Vec<AlbumSecondaryType>,
) -> Self { ) -> Self {
let info = AlbumInfo::new(MbRefOption::None, primary_type, secondary_types);
Album { Album {
meta: AlbumMeta::new(id, date, primary_type, secondary_types), meta: AlbumMeta::new(id, date, info),
tracks: vec![], tracks: vec![],
} }
} }
@ -179,16 +186,13 @@ impl AlbumMeta {
pub fn new<Id: Into<AlbumId>, Date: Into<AlbumDate>>( pub fn new<Id: Into<AlbumId>, Date: Into<AlbumDate>>(
id: Id, id: Id,
date: Date, date: Date,
primary_type: Option<AlbumPrimaryType>, info: AlbumInfo,
secondary_types: Vec<AlbumSecondaryType>,
) -> Self { ) -> Self {
AlbumMeta { AlbumMeta {
id: id.into(), id: id.into(),
date: date.into(), date: date.into(),
seq: AlbumSeq::default(), seq: AlbumSeq::default(),
musicbrainz: MbRefOption::None, info,
primary_type,
secondary_types,
} }
} }
@ -203,29 +207,29 @@ impl AlbumMeta {
pub fn clear_seq(&mut self) { pub fn clear_seq(&mut self) {
self.seq = AlbumSeq::default(); self.seq = AlbumSeq::default();
} }
pub fn set_musicbrainz_ref(&mut self, mbref: MbRefOption<MbAlbumRef>) {
_ = mem::replace(&mut self.musicbrainz, mbref);
} }
pub fn clear_musicbrainz_ref(&mut self) { impl Default for AlbumInfo {
self.musicbrainz.take(); fn default() -> Self {
AlbumInfo {
musicbrainz: MbRefOption::None,
primary_type: None,
secondary_types: Vec::new(),
}
}
} }
pub fn set_primary_type(&mut self, primary_type: Option<AlbumPrimaryType>) { impl AlbumInfo {
_ = mem::replace(&mut self.primary_type, primary_type); pub fn new(
musicbrainz: MbRefOption<MbAlbumRef>,
primary_type: Option<AlbumPrimaryType>,
secondary_types: Vec<AlbumSecondaryType>,
) -> Self {
AlbumInfo {
musicbrainz,
primary_type,
secondary_types,
} }
pub fn clear_primary_type(&mut self) {
self.primary_type.take();
}
pub fn set_secondary_types(&mut self, secondary_types: Vec<AlbumSecondaryType>) {
self.secondary_types = secondary_types;
}
pub fn clear_secondary_types(&mut self) {
self.secondary_types.clear();
} }
} }
@ -246,6 +250,12 @@ impl Merge for AlbumMeta {
assert_eq!(self.id, other.id); assert_eq!(self.id, other.id);
self.seq = std::cmp::max(self.seq, other.seq); self.seq = std::cmp::max(self.seq, other.seq);
self.info.merge_in_place(other.info);
}
}
impl Merge for AlbumInfo {
fn merge_in_place(&mut self, other: Self) {
self.musicbrainz = self.musicbrainz.take().or(other.musicbrainz); self.musicbrainz = self.musicbrainz.take().or(other.musicbrainz);
self.primary_type = self.primary_type.take().or(other.primary_type); self.primary_type = self.primary_type.take().or(other.primary_type);
self.secondary_types.merge_in_place(other.secondary_types); self.secondary_types.merge_in_place(other.secondary_types);
@ -370,40 +380,4 @@ mod tests {
let merged = left.clone().merge(right); let merged = left.clone().merge(right);
assert_eq!(expected, merged); assert_eq!(expected, merged);
} }
#[test]
fn set_clear_musicbrainz_url() {
const MUSICBRAINZ: &str =
"https://musicbrainz.org/release-group/c12897a3-af7a-3466-8892-58af84765813";
const MUSICBRAINZ_2: &str =
"https://musicbrainz.org/release-group/0eaa9306-e6df-47be-94ce-04bfe3df782c";
let mut album = Album::new(AlbumId::new("an album"), AlbumDate::default(), None, vec![]);
let mut expected: MbRefOption<MbAlbumRef> = MbRefOption::None;
assert_eq!(album.meta.musicbrainz, expected);
// Setting a URL on an album.
album.meta.set_musicbrainz_ref(MbRefOption::Some(
MbAlbumRef::from_url_str(MUSICBRAINZ).unwrap(),
));
expected.replace(MbAlbumRef::from_url_str(MUSICBRAINZ).unwrap());
assert_eq!(album.meta.musicbrainz, expected);
album.meta.set_musicbrainz_ref(MbRefOption::Some(
MbAlbumRef::from_url_str(MUSICBRAINZ).unwrap(),
));
assert_eq!(album.meta.musicbrainz, expected);
album.meta.set_musicbrainz_ref(MbRefOption::Some(
MbAlbumRef::from_url_str(MUSICBRAINZ_2).unwrap(),
));
expected.replace(MbAlbumRef::from_url_str(MUSICBRAINZ_2).unwrap());
assert_eq!(album.meta.musicbrainz, expected);
// Clearing URLs.
album.meta.clear_musicbrainz_ref();
expected.take();
assert_eq!(album.meta.musicbrainz, expected);
}
} }

View File

@ -21,7 +21,13 @@ pub struct Artist {
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub struct ArtistMeta { pub struct ArtistMeta {
pub id: ArtistId, pub id: ArtistId,
pub sort: Option<ArtistId>, pub sort: Option<String>,
pub info: ArtistInfo,
}
/// Artist non-identifier metadata.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ArtistInfo {
pub musicbrainz: MbRefOption<MbArtistRef>, pub musicbrainz: MbRefOption<MbArtistRef>,
pub properties: HashMap<String, Vec<String>>, pub properties: HashMap<String, Vec<String>>,
} }
@ -75,22 +81,36 @@ impl ArtistMeta {
ArtistMeta { ArtistMeta {
id: id.into(), id: id.into(),
sort: None, sort: None,
musicbrainz: MbRefOption::None, info: ArtistInfo::default(),
properties: HashMap::new(),
} }
} }
pub fn get_sort_key(&self) -> (&ArtistId,) { pub fn get_sort_key(&self) -> (&str,) {
(self.sort.as_ref().unwrap_or(&self.id),) (self.sort.as_ref().unwrap_or(&self.id.name),)
} }
pub fn set_sort_key<SORT: Into<ArtistId>>(&mut self, sort: SORT) { pub fn set_sort_key<S: Into<String>>(&mut self, sort: S) {
self.sort = Some(sort.into()); self.sort = Some(sort.into());
} }
pub fn clear_sort_key(&mut self) { pub fn clear_sort_key(&mut self) {
self.sort.take(); self.sort.take();
} }
}
impl Default for ArtistInfo {
fn default() -> Self {
Self::new()
}
}
impl ArtistInfo {
pub fn new() -> Self {
ArtistInfo {
musicbrainz: MbRefOption::None,
properties: HashMap::new(),
}
}
pub fn set_musicbrainz_ref(&mut self, mbref: MbRefOption<MbArtistRef>) { pub fn set_musicbrainz_ref(&mut self, mbref: MbRefOption<MbArtistRef>) {
self.musicbrainz = mbref self.musicbrainz = mbref
@ -162,6 +182,12 @@ impl Merge for ArtistMeta {
assert_eq!(self.id, other.id); assert_eq!(self.id, other.id);
self.sort = self.sort.take().or(other.sort); self.sort = self.sort.take().or(other.sort);
self.info.merge_in_place(other.info);
}
}
impl Merge for ArtistInfo {
fn merge_in_place(&mut self, other: Self) {
self.musicbrainz = self.musicbrainz.take().or(other.musicbrainz); self.musicbrainz = self.musicbrainz.take().or(other.musicbrainz);
self.properties.merge_in_place(other.properties); self.properties.merge_in_place(other.properties);
} }
@ -207,14 +233,14 @@ mod tests {
#[test] #[test]
fn artist_sort_set_clear() { fn artist_sort_set_clear() {
let artist_id = ArtistId::new("an artist"); let artist_id = ArtistId::new("an artist");
let sort_id_1 = ArtistId::new("sort id 1"); let sort_id_1 = String::from("sort id 1");
let sort_id_2 = ArtistId::new("sort id 2"); let sort_id_2 = String::from("sort id 2");
let mut artist = Artist::new(&artist_id.name); let mut artist = Artist::new(&artist_id.name);
assert_eq!(artist.meta.id, artist_id); assert_eq!(artist.meta.id, artist_id);
assert_eq!(artist.meta.sort, None); assert_eq!(artist.meta.sort, None);
assert_eq!(artist.meta.get_sort_key(), (&artist_id,)); assert_eq!(artist.meta.get_sort_key(), (artist_id.name.as_str(),));
assert!(artist.meta < ArtistMeta::new(sort_id_1.clone())); assert!(artist.meta < ArtistMeta::new(sort_id_1.clone()));
assert!(artist.meta < ArtistMeta::new(sort_id_2.clone())); assert!(artist.meta < ArtistMeta::new(sort_id_2.clone()));
assert!(artist < Artist::new(sort_id_1.clone())); assert!(artist < Artist::new(sort_id_1.clone()));
@ -224,7 +250,7 @@ mod tests {
assert_eq!(artist.meta.id, artist_id); assert_eq!(artist.meta.id, artist_id);
assert_eq!(artist.meta.sort.as_ref(), Some(&sort_id_1)); assert_eq!(artist.meta.sort.as_ref(), Some(&sort_id_1));
assert_eq!(artist.meta.get_sort_key(), (&sort_id_1,)); assert_eq!(artist.meta.get_sort_key(), (sort_id_1.as_str(),));
assert!(artist.meta > ArtistMeta::new(artist_id.clone())); assert!(artist.meta > ArtistMeta::new(artist_id.clone()));
assert!(artist.meta < ArtistMeta::new(sort_id_2.clone())); assert!(artist.meta < ArtistMeta::new(sort_id_2.clone()));
assert!(artist > Artist::new(artist_id.clone())); assert!(artist > Artist::new(artist_id.clone()));
@ -234,7 +260,7 @@ mod tests {
assert_eq!(artist.meta.id, artist_id); assert_eq!(artist.meta.id, artist_id);
assert_eq!(artist.meta.sort.as_ref(), Some(&sort_id_2)); assert_eq!(artist.meta.sort.as_ref(), Some(&sort_id_2));
assert_eq!(artist.meta.get_sort_key(), (&sort_id_2,)); assert_eq!(artist.meta.get_sort_key(), (sort_id_2.as_str(),));
assert!(artist.meta > ArtistMeta::new(artist_id.clone())); assert!(artist.meta > ArtistMeta::new(artist_id.clone()));
assert!(artist.meta > ArtistMeta::new(sort_id_1.clone())); assert!(artist.meta > ArtistMeta::new(sort_id_1.clone()));
assert!(artist > Artist::new(artist_id.clone())); assert!(artist > Artist::new(artist_id.clone()));
@ -244,7 +270,7 @@ mod tests {
assert_eq!(artist.meta.id, artist_id); assert_eq!(artist.meta.id, artist_id);
assert_eq!(artist.meta.sort, None); assert_eq!(artist.meta.sort, None);
assert_eq!(artist.meta.get_sort_key(), (&artist_id,)); assert_eq!(artist.meta.get_sort_key(), (artist_id.name.as_str(),));
assert!(artist.meta < ArtistMeta::new(sort_id_1.clone())); assert!(artist.meta < ArtistMeta::new(sort_id_1.clone()));
assert!(artist.meta < ArtistMeta::new(sort_id_2.clone())); assert!(artist.meta < ArtistMeta::new(sort_id_2.clone()));
assert!(artist < Artist::new(sort_id_1.clone())); assert!(artist < Artist::new(sort_id_1.clone()));
@ -256,160 +282,132 @@ mod tests {
let mut artist = Artist::new(ArtistId::new("an artist")); let mut artist = Artist::new(ArtistId::new("an artist"));
let mut expected: MbRefOption<MbArtistRef> = MbRefOption::None; let mut expected: MbRefOption<MbArtistRef> = MbRefOption::None;
assert_eq!(artist.meta.musicbrainz, expected); assert_eq!(artist.meta.info.musicbrainz, expected);
// Setting a URL on an artist. // Setting a URL on an artist.
artist.meta.set_musicbrainz_ref(MbRefOption::Some( artist.meta.info.set_musicbrainz_ref(MbRefOption::Some(
MbArtistRef::from_url_str(MUSICBRAINZ).unwrap(), MbArtistRef::from_url_str(MUSICBRAINZ).unwrap(),
)); ));
expected.replace(MbArtistRef::from_url_str(MUSICBRAINZ).unwrap()); expected.replace(MbArtistRef::from_url_str(MUSICBRAINZ).unwrap());
assert_eq!(artist.meta.musicbrainz, expected); assert_eq!(artist.meta.info.musicbrainz, expected);
artist.meta.set_musicbrainz_ref(MbRefOption::Some( artist.meta.info.set_musicbrainz_ref(MbRefOption::Some(
MbArtistRef::from_url_str(MUSICBRAINZ).unwrap(), MbArtistRef::from_url_str(MUSICBRAINZ).unwrap(),
)); ));
assert_eq!(artist.meta.musicbrainz, expected); assert_eq!(artist.meta.info.musicbrainz, expected);
artist.meta.set_musicbrainz_ref(MbRefOption::Some( artist.meta.info.set_musicbrainz_ref(MbRefOption::Some(
MbArtistRef::from_url_str(MUSICBRAINZ_2).unwrap(), MbArtistRef::from_url_str(MUSICBRAINZ_2).unwrap(),
)); ));
expected.replace(MbArtistRef::from_url_str(MUSICBRAINZ_2).unwrap()); expected.replace(MbArtistRef::from_url_str(MUSICBRAINZ_2).unwrap());
assert_eq!(artist.meta.musicbrainz, expected); assert_eq!(artist.meta.info.musicbrainz, expected);
// Clearing URLs. // Clearing URLs.
artist.meta.clear_musicbrainz_ref(); artist.meta.info.clear_musicbrainz_ref();
expected.take(); expected.take();
assert_eq!(artist.meta.musicbrainz, expected); assert_eq!(artist.meta.info.musicbrainz, expected);
} }
#[test] #[test]
fn add_to_remove_from_property() { fn add_to_remove_from_property() {
let mut artist = Artist::new(ArtistId::new("an artist")); let mut artist = Artist::new(ArtistId::new("an artist"));
let info = &mut artist.meta.info;
let mut expected: Vec<String> = vec![]; let mut expected: Vec<String> = vec![];
assert!(artist.meta.properties.is_empty()); assert!(info.properties.is_empty());
// Adding a single URL. // Adding a single URL.
artist info.add_to_property("MusicButler", vec![MUSICBUTLER]);
.meta
.add_to_property("MusicButler", vec![MUSICBUTLER]);
expected.push(MUSICBUTLER.to_owned()); expected.push(MUSICBUTLER.to_owned());
assert_eq!(artist.meta.properties.get("MusicButler"), Some(&expected)); assert_eq!(info.properties.get("MusicButler"), Some(&expected));
// Adding a URL that already exists is ok, but does not do anything. // Adding a URL that already exists is ok, but does not do anything.
artist info.add_to_property("MusicButler", vec![MUSICBUTLER]);
.meta assert_eq!(info.properties.get("MusicButler"), Some(&expected));
.add_to_property("MusicButler", vec![MUSICBUTLER]);
assert_eq!(artist.meta.properties.get("MusicButler"), Some(&expected));
// Adding another single URL. // Adding another single URL.
artist info.add_to_property("MusicButler", vec![MUSICBUTLER_2]);
.meta
.add_to_property("MusicButler", vec![MUSICBUTLER_2]);
expected.push(MUSICBUTLER_2.to_owned()); expected.push(MUSICBUTLER_2.to_owned());
assert_eq!(artist.meta.properties.get("MusicButler"), Some(&expected)); assert_eq!(info.properties.get("MusicButler"), Some(&expected));
artist info.add_to_property("MusicButler", vec![MUSICBUTLER_2]);
.meta assert_eq!(info.properties.get("MusicButler"), Some(&expected));
.add_to_property("MusicButler", vec![MUSICBUTLER_2]);
assert_eq!(artist.meta.properties.get("MusicButler"), Some(&expected));
// Removing a URL. // Removing a URL.
artist info.remove_from_property("MusicButler", vec![MUSICBUTLER]);
.meta
.remove_from_property("MusicButler", vec![MUSICBUTLER]);
expected.retain(|url| url != MUSICBUTLER); expected.retain(|url| url != MUSICBUTLER);
assert_eq!(artist.meta.properties.get("MusicButler"), Some(&expected)); assert_eq!(info.properties.get("MusicButler"), Some(&expected));
// Removing URls that do not exist is okay, they will be ignored. // Removing URls that do not exist is okay, they will be ignored.
artist info.remove_from_property("MusicButler", vec![MUSICBUTLER]);
.meta assert_eq!(info.properties.get("MusicButler"), Some(&expected));
.remove_from_property("MusicButler", vec![MUSICBUTLER]);
assert_eq!(artist.meta.properties.get("MusicButler"), Some(&expected));
// Removing a URL. // Removing a URL.
artist info.remove_from_property("MusicButler", vec![MUSICBUTLER_2]);
.meta
.remove_from_property("MusicButler", vec![MUSICBUTLER_2]);
expected.retain(|url| url.as_str() != MUSICBUTLER_2); expected.retain(|url| url.as_str() != MUSICBUTLER_2);
assert!(artist.meta.properties.is_empty()); assert!(info.properties.is_empty());
artist info.remove_from_property("MusicButler", vec![MUSICBUTLER_2]);
.meta assert!(info.properties.is_empty());
.remove_from_property("MusicButler", vec![MUSICBUTLER_2]);
assert!(artist.meta.properties.is_empty());
// Adding URLs if some exist is okay, they will be ignored. // Adding URLs if some exist is okay, they will be ignored.
artist info.add_to_property("MusicButler", vec![MUSICBUTLER]);
.meta
.add_to_property("MusicButler", vec![MUSICBUTLER]);
expected.push(MUSICBUTLER.to_owned()); expected.push(MUSICBUTLER.to_owned());
assert_eq!(artist.meta.properties.get("MusicButler"), Some(&expected)); assert_eq!(info.properties.get("MusicButler"), Some(&expected));
artist info.add_to_property("MusicButler", vec![MUSICBUTLER, MUSICBUTLER_2]);
.meta
.add_to_property("MusicButler", vec![MUSICBUTLER, MUSICBUTLER_2]);
expected.push(MUSICBUTLER_2.to_owned()); expected.push(MUSICBUTLER_2.to_owned());
assert_eq!(artist.meta.properties.get("MusicButler"), Some(&expected)); assert_eq!(info.properties.get("MusicButler"), Some(&expected));
// Removing URLs if some do not exist is okay, they will be ignored. // Removing URLs if some do not exist is okay, they will be ignored.
artist info.remove_from_property("MusicButler", vec![MUSICBUTLER]);
.meta
.remove_from_property("MusicButler", vec![MUSICBUTLER]);
expected.retain(|url| url.as_str() != MUSICBUTLER); expected.retain(|url| url.as_str() != MUSICBUTLER);
assert_eq!(artist.meta.properties.get("MusicButler"), Some(&expected)); assert_eq!(info.properties.get("MusicButler"), Some(&expected));
artist info.remove_from_property("MusicButler", vec![MUSICBUTLER, MUSICBUTLER_2]);
.meta
.remove_from_property("MusicButler", vec![MUSICBUTLER, MUSICBUTLER_2]);
expected.retain(|url| url.as_str() != MUSICBUTLER_2); expected.retain(|url| url.as_str() != MUSICBUTLER_2);
assert!(artist.meta.properties.is_empty()); assert!(info.properties.is_empty());
// Adding mutliple URLs without clashes. // Adding mutliple URLs without clashes.
artist info.add_to_property("MusicButler", vec![MUSICBUTLER, MUSICBUTLER_2]);
.meta
.add_to_property("MusicButler", vec![MUSICBUTLER, MUSICBUTLER_2]);
expected.push(MUSICBUTLER.to_owned()); expected.push(MUSICBUTLER.to_owned());
expected.push(MUSICBUTLER_2.to_owned()); expected.push(MUSICBUTLER_2.to_owned());
assert_eq!(artist.meta.properties.get("MusicButler"), Some(&expected)); assert_eq!(info.properties.get("MusicButler"), Some(&expected));
// Removing multiple URLs without clashes. // Removing multiple URLs without clashes.
artist info.remove_from_property("MusicButler", vec![MUSICBUTLER, MUSICBUTLER_2]);
.meta
.remove_from_property("MusicButler", vec![MUSICBUTLER, MUSICBUTLER_2]);
expected.clear(); expected.clear();
assert!(artist.meta.properties.is_empty()); assert!(info.properties.is_empty());
} }
#[test] #[test]
fn set_clear_musicbutler_urls() { fn set_clear_musicbutler_urls() {
let mut artist = Artist::new(ArtistId::new("an artist")); let mut artist = Artist::new(ArtistId::new("an artist"));
let info = &mut artist.meta.info;
let mut expected: Vec<String> = vec![]; let mut expected: Vec<String> = vec![];
assert!(artist.meta.properties.is_empty()); assert!(info.properties.is_empty());
// Set URLs. // Set URLs.
artist.meta.set_property("MusicButler", vec![MUSICBUTLER]); info.set_property("MusicButler", vec![MUSICBUTLER]);
expected.push(MUSICBUTLER.to_owned()); expected.push(MUSICBUTLER.to_owned());
assert_eq!(artist.meta.properties.get("MusicButler"), Some(&expected)); assert_eq!(info.properties.get("MusicButler"), Some(&expected));
artist.meta.set_property("MusicButler", vec![MUSICBUTLER_2]); info.set_property("MusicButler", vec![MUSICBUTLER_2]);
expected.clear(); expected.clear();
expected.push(MUSICBUTLER_2.to_owned()); expected.push(MUSICBUTLER_2.to_owned());
assert_eq!(artist.meta.properties.get("MusicButler"), Some(&expected)); assert_eq!(info.properties.get("MusicButler"), Some(&expected));
artist info.set_property("MusicButler", vec![MUSICBUTLER, MUSICBUTLER_2]);
.meta
.set_property("MusicButler", vec![MUSICBUTLER, MUSICBUTLER_2]);
expected.clear(); expected.clear();
expected.push(MUSICBUTLER.to_owned()); expected.push(MUSICBUTLER.to_owned());
expected.push(MUSICBUTLER_2.to_owned()); expected.push(MUSICBUTLER_2.to_owned());
assert_eq!(artist.meta.properties.get("MusicButler"), Some(&expected)); assert_eq!(info.properties.get("MusicButler"), Some(&expected));
// Clear URLs. // Clear URLs.
artist.meta.clear_property("MusicButler"); info.clear_property("MusicButler");
expected.clear(); expected.clear();
assert!(artist.meta.properties.is_empty()); assert!(info.properties.is_empty());
} }
#[test] #[test]
@ -417,14 +415,15 @@ mod tests {
let left = FULL_COLLECTION[0].to_owned(); let left = FULL_COLLECTION[0].to_owned();
let mut right = FULL_COLLECTION[1].to_owned(); let mut right = FULL_COLLECTION[1].to_owned();
right.meta.id = left.meta.id.clone(); right.meta.id = left.meta.id.clone();
right.meta.musicbrainz = MbRefOption::None; right.meta.info.musicbrainz = MbRefOption::None;
right.meta.properties = HashMap::new(); right.meta.info.properties = HashMap::new();
let mut expected = left.clone(); let mut expected = left.clone();
expected.meta.properties = expected expected.meta.info.properties = expected
.meta .meta
.info
.properties .properties
.merge(right.clone().meta.properties); .merge(right.clone().meta.info.properties);
expected.albums.append(&mut right.albums.clone()); expected.albums.append(&mut right.albums.clone());
expected.albums.sort_unstable(); expected.albums.sort_unstable();
@ -445,10 +444,11 @@ mod tests {
left.albums.sort_unstable(); left.albums.sort_unstable();
let mut expected = left.clone(); let mut expected = left.clone();
expected.meta.properties = expected expected.meta.info.properties = expected
.meta .meta
.info
.properties .properties
.merge(right.clone().meta.properties); .merge(right.clone().meta.info.properties);
expected.albums.append(&mut right.albums.clone()); expected.albums.append(&mut right.albums.clone());
expected.albums.sort_unstable(); expected.albums.sort_unstable();
expected.albums.dedup(); expected.albums.dedup();

View File

@ -97,7 +97,7 @@ impl<Database, Library> IMusicHoardBasePrivate for MusicHoard<Database, Library>
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::core::{collection::artist::ArtistId, testmod::FULL_COLLECTION}; use crate::core::testmod::FULL_COLLECTION;
use super::*; use super::*;
@ -190,7 +190,7 @@ mod tests {
let mut right: Vec<Artist> = vec![left.last().unwrap().clone()]; let mut right: Vec<Artist> = vec![left.last().unwrap().clone()];
assert!(right.first().unwrap() > left.first().unwrap()); assert!(right.first().unwrap() > left.first().unwrap());
let artist_sort = Some(ArtistId::new("Album_Artist 0")); let artist_sort = Some(String::from("Album_Artist 0"));
right[0].meta.sort = artist_sort.clone(); right[0].meta.sort = artist_sort.clone();
assert!(right.first().unwrap() < left.first().unwrap()); assert!(right.first().unwrap() < left.first().unwrap());

View File

@ -1,13 +1,9 @@
use crate::{ use crate::{
collection::{ collection::{album::AlbumInfo, artist::ArtistInfo},
album::{AlbumPrimaryType, AlbumSecondaryType},
musicbrainz::{MbAlbumRef, MbRefOption},
},
core::{ core::{
collection::{ collection::{
album::{Album, AlbumId, AlbumSeq}, album::{Album, AlbumId, AlbumSeq},
artist::{Artist, ArtistId}, artist::{Artist, ArtistId},
musicbrainz::MbArtistRef,
Collection, Collection,
}, },
interface::database::IDatabase, interface::database::IDatabase,
@ -21,20 +17,19 @@ pub trait IMusicHoardDatabase {
fn add_artist<IntoId: Into<ArtistId>>(&mut self, artist_id: IntoId) -> Result<(), Error>; fn add_artist<IntoId: Into<ArtistId>>(&mut self, artist_id: IntoId) -> Result<(), Error>;
fn remove_artist<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error>; fn remove_artist<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error>;
fn set_artist_sort<Id: AsRef<ArtistId>, IntoId: Into<ArtistId>>( fn set_artist_sort<Id: AsRef<ArtistId>, S: Into<String>>(
&mut self, &mut self,
artist_id: Id, artist_id: Id,
artist_sort: IntoId, artist_sort: S,
) -> Result<(), Error>; ) -> Result<(), Error>;
fn clear_artist_sort<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error>; fn clear_artist_sort<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error>;
fn set_artist_musicbrainz<Id: AsRef<ArtistId>>( fn set_artist_info<Id: AsRef<ArtistId>>(
&mut self, &mut self,
artist_id: Id, artist_id: Id,
mbid: MbRefOption<MbArtistRef>, info: ArtistInfo,
) -> Result<(), Error>; ) -> Result<(), Error>;
fn clear_artist_musicbrainz<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) fn clear_artist_info<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error>;
-> Result<(), Error>;
fn add_to_artist_property<Id: AsRef<ArtistId>, S: AsRef<str> + Into<String>>( fn add_to_artist_property<Id: AsRef<ArtistId>, S: AsRef<str> + Into<String>>(
&mut self, &mut self,
@ -60,17 +55,6 @@ pub trait IMusicHoardDatabase {
property: S, property: S,
) -> Result<(), Error>; ) -> Result<(), Error>;
fn set_album_musicbrainz<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
&mut self,
artist_id: Id,
album_id: AlbumIdRef,
mbid: MbRefOption<MbAlbumRef>,
) -> Result<(), Error>;
fn clear_album_musicbrainz<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
&mut self,
artist_id: Id,
album_id: AlbumIdRef,
) -> Result<(), Error>;
fn set_album_seq<ArtistIdRef: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>( fn set_album_seq<ArtistIdRef: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
&mut self, &mut self,
artist_id: ArtistIdRef, artist_id: ArtistIdRef,
@ -82,24 +66,13 @@ pub trait IMusicHoardDatabase {
artist_id: ArtistIdRef, artist_id: ArtistIdRef,
album_id: AlbumIdRef, album_id: AlbumIdRef,
) -> Result<(), Error>; ) -> Result<(), Error>;
fn set_album_primary_type<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>( fn set_album_info<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
&mut self, &mut self,
artist_id: Id, artist_id: Id,
album_id: AlbumIdRef, album_id: AlbumIdRef,
primary_type: Option<AlbumPrimaryType>, info: AlbumInfo,
) -> Result<(), Error>; ) -> Result<(), Error>;
fn clear_album_primary_type<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>( fn clear_album_info<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
&mut self,
artist_id: Id,
album_id: AlbumIdRef,
) -> Result<(), Error>;
fn set_album_secondary_types<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
&mut self,
artist_id: Id,
album_id: AlbumIdRef,
secondary_types: Vec<AlbumSecondaryType>,
) -> Result<(), Error>;
fn clear_album_secondary_types<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
&mut self, &mut self,
artist_id: Id, artist_id: Id,
album_id: AlbumIdRef, album_id: AlbumIdRef,
@ -139,10 +112,10 @@ impl<Database: IDatabase, Library> IMusicHoardDatabase for MusicHoard<Database,
}) })
} }
fn set_artist_sort<Id: AsRef<ArtistId>, IntoId: Into<ArtistId>>( fn set_artist_sort<Id: AsRef<ArtistId>, S: Into<String>>(
&mut self, &mut self,
artist_id: Id, artist_id: Id,
artist_sort: IntoId, artist_sort: S,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.update_artist_and( self.update_artist_and(
artist_id.as_ref(), artist_id.as_ref(),
@ -159,22 +132,17 @@ impl<Database: IDatabase, Library> IMusicHoardDatabase for MusicHoard<Database,
) )
} }
fn set_artist_musicbrainz<Id: AsRef<ArtistId>>( fn set_artist_info<Id: AsRef<ArtistId>>(
&mut self, &mut self,
artist_id: Id, artist_id: Id,
mbid: MbRefOption<MbArtistRef>, info: ArtistInfo,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.update_artist(artist_id.as_ref(), |artist| { self.update_artist(artist_id.as_ref(), |artist| artist.meta.info = info)
artist.meta.set_musicbrainz_ref(mbid)
})
} }
fn clear_artist_musicbrainz<Id: AsRef<ArtistId>>( fn clear_artist_info<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error> {
&mut self,
artist_id: Id,
) -> Result<(), Error> {
self.update_artist(artist_id.as_ref(), |artist| { self.update_artist(artist_id.as_ref(), |artist| {
artist.meta.clear_musicbrainz_ref() artist.meta.info = ArtistInfo::default()
}) })
} }
@ -185,7 +153,7 @@ impl<Database: IDatabase, Library> IMusicHoardDatabase for MusicHoard<Database,
values: Vec<S>, values: Vec<S>,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.update_artist(artist_id.as_ref(), |artist| { self.update_artist(artist_id.as_ref(), |artist| {
artist.meta.add_to_property(property, values) artist.meta.info.add_to_property(property, values)
}) })
} }
@ -196,7 +164,7 @@ impl<Database: IDatabase, Library> IMusicHoardDatabase for MusicHoard<Database,
values: Vec<S>, values: Vec<S>,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.update_artist(artist_id.as_ref(), |artist| { self.update_artist(artist_id.as_ref(), |artist| {
artist.meta.remove_from_property(property, values) artist.meta.info.remove_from_property(property, values)
}) })
} }
@ -207,7 +175,7 @@ impl<Database: IDatabase, Library> IMusicHoardDatabase for MusicHoard<Database,
values: Vec<S>, values: Vec<S>,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.update_artist(artist_id.as_ref(), |artist| { self.update_artist(artist_id.as_ref(), |artist| {
artist.meta.set_property(property, values) artist.meta.info.set_property(property, values)
}) })
} }
@ -217,28 +185,7 @@ impl<Database: IDatabase, Library> IMusicHoardDatabase for MusicHoard<Database,
property: S, property: S,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.update_artist(artist_id.as_ref(), |artist| { self.update_artist(artist_id.as_ref(), |artist| {
artist.meta.clear_property(property) artist.meta.info.clear_property(property)
})
}
fn set_album_musicbrainz<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
&mut self,
artist_id: Id,
album_id: AlbumIdRef,
mbid: MbRefOption<MbAlbumRef>,
) -> Result<(), Error> {
self.update_album(artist_id.as_ref(), album_id.as_ref(), |album| {
album.meta.set_musicbrainz_ref(mbid)
})
}
fn clear_album_musicbrainz<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
&mut self,
artist_id: Id,
album_id: AlbumIdRef,
) -> Result<(), Error> {
self.update_album(artist_id.as_ref(), album_id.as_ref(), |album| {
album.meta.clear_musicbrainz_ref()
}) })
} }
@ -269,45 +216,24 @@ impl<Database: IDatabase, Library> IMusicHoardDatabase for MusicHoard<Database,
) )
} }
fn set_album_primary_type<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>( fn set_album_info<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
&mut self, &mut self,
artist_id: Id, artist_id: Id,
album_id: AlbumIdRef, album_id: AlbumIdRef,
primary_type: Option<AlbumPrimaryType>, info: AlbumInfo,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.update_album(artist_id.as_ref(), album_id.as_ref(), |album| { self.update_album(artist_id.as_ref(), album_id.as_ref(), |album| {
album.meta.set_primary_type(primary_type) album.meta.info = info
}) })
} }
fn clear_album_primary_type<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>( fn clear_album_info<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
&mut self, &mut self,
artist_id: Id, artist_id: Id,
album_id: AlbumIdRef, album_id: AlbumIdRef,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.update_album(artist_id.as_ref(), album_id.as_ref(), |album| { self.update_album(artist_id.as_ref(), album_id.as_ref(), |album| {
album.meta.clear_primary_type() album.meta.info = AlbumInfo::default()
})
}
fn set_album_secondary_types<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
&mut self,
artist_id: Id,
album_id: AlbumIdRef,
secondary_types: Vec<AlbumSecondaryType>,
) -> Result<(), Error> {
self.update_album(artist_id.as_ref(), album_id.as_ref(), |album| {
album.meta.set_secondary_types(secondary_types)
})
}
fn clear_album_secondary_types<Id: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
&mut self,
artist_id: Id,
album_id: AlbumIdRef,
) -> Result<(), Error> {
self.update_album(artist_id.as_ref(), album_id.as_ref(), |album| {
album.meta.clear_secondary_types()
}) })
} }
} }
@ -407,7 +333,7 @@ mod tests {
use mockall::{predicate, Sequence}; use mockall::{predicate, Sequence};
use crate::{ use crate::{
collection::musicbrainz::MbRefOption, collection::musicbrainz::{MbArtistRef, MbRefOption},
core::{ core::{
collection::{album::AlbumDate, artist::ArtistId}, collection::{album::AlbumDate, artist::ArtistId},
interface::database::{self, MockIDatabase}, interface::database::{self, MockIDatabase},
@ -478,12 +404,12 @@ mod tests {
let mut music_hoard: MH = MusicHoard::database(database).unwrap(); let mut music_hoard: MH = MusicHoard::database(database).unwrap();
let artist_1_id = ArtistId::new("the artist"); let artist_1_id = ArtistId::new("the artist");
let artist_1_sort = ArtistId::new("artist, the"); let artist_1_sort = String::from("artist, the");
// Must be after "artist, the", but before "the artist" // Must be after "artist, the", but before "the artist"
let artist_2_id = ArtistId::new("b-artist"); let artist_2_id = ArtistId::new("b-artist");
assert!(artist_1_sort < artist_2_id); assert!(artist_1_sort < artist_2_id.name);
assert!(artist_2_id < artist_1_id); assert!(artist_2_id < artist_1_id);
assert!(music_hoard.add_artist(artist_1_id.clone()).is_ok()); assert!(music_hoard.add_artist(artist_1_id.clone()).is_ok());
@ -521,7 +447,7 @@ mod tests {
} }
#[test] #[test]
fn set_clear_musicbrainz_url() { fn set_clear_info() {
let mut database = MockIDatabase::new(); let mut database = MockIDatabase::new();
database.expect_load().times(1).returning(|| Ok(vec![])); database.expect_load().times(1).returning(|| Ok(vec![]));
database.expect_save().times(3).returning(|_| Ok(())); database.expect_save().times(3).returning(|_| Ok(()));
@ -533,31 +459,32 @@ mod tests {
assert!(music_hoard.add_artist(artist_id.clone()).is_ok()); assert!(music_hoard.add_artist(artist_id.clone()).is_ok());
let mut expected: MbRefOption<MbArtistRef> = MbRefOption::None; let mut expected: MbRefOption<MbArtistRef> = MbRefOption::None;
assert_eq!(music_hoard.collection[0].meta.musicbrainz, expected); assert_eq!(music_hoard.collection[0].meta.info.musicbrainz, expected);
let mbref = MbRefOption::Some(MbArtistRef::from_uuid_str(MBID).unwrap()); let mut info = ArtistInfo::new();
info.musicbrainz = MbRefOption::Some(MbArtistRef::from_uuid_str(MBID).unwrap());
// Setting a URL on an artist not in the collection is an error. // Setting a URL on an artist not in the collection is an error.
assert!(music_hoard assert!(music_hoard
.set_artist_musicbrainz(&artist_id_2, mbref.clone()) .set_artist_info(&artist_id_2, info.clone())
.is_err()); .is_err());
assert_eq!(music_hoard.collection[0].meta.musicbrainz, expected); assert_eq!(music_hoard.collection[0].meta.info.musicbrainz, expected);
// Setting a URL on an artist. // Setting a URL on an artist.
assert!(music_hoard assert!(music_hoard
.set_artist_musicbrainz(&artist_id, mbref.clone()) .set_artist_info(&artist_id, info.clone())
.is_ok()); .is_ok());
expected.replace(MbArtistRef::from_uuid_str(MBID).unwrap()); expected.replace(MbArtistRef::from_uuid_str(MBID).unwrap());
assert_eq!(music_hoard.collection[0].meta.musicbrainz, expected); assert_eq!(music_hoard.collection[0].meta.info.musicbrainz, expected);
// Clearing URLs on an artist that does not exist is an error. // Clearing URLs on an artist that does not exist is an error.
assert!(music_hoard.clear_artist_musicbrainz(&artist_id_2).is_err()); assert!(music_hoard.clear_artist_info(&artist_id_2).is_err());
assert_eq!(music_hoard.collection[0].meta.musicbrainz, expected); assert_eq!(music_hoard.collection[0].meta.info.musicbrainz, expected);
// Clearing URLs. // Clearing URLs.
assert!(music_hoard.clear_artist_musicbrainz(&artist_id).is_ok()); assert!(music_hoard.clear_artist_info(&artist_id).is_ok());
expected.take(); expected.take();
assert_eq!(music_hoard.collection[0].meta.musicbrainz, expected); assert_eq!(music_hoard.collection[0].meta.info.musicbrainz, expected);
} }
#[test] #[test]
@ -573,13 +500,13 @@ mod tests {
assert!(music_hoard.add_artist(artist_id.clone()).is_ok()); assert!(music_hoard.add_artist(artist_id.clone()).is_ok());
let mut expected: Vec<String> = vec![]; let mut expected: Vec<String> = vec![];
assert!(music_hoard.collection[0].meta.properties.is_empty()); assert!(music_hoard.collection[0].meta.info.properties.is_empty());
// Adding URLs to an artist not in the collection is an error. // Adding URLs to an artist not in the collection is an error.
assert!(music_hoard assert!(music_hoard
.add_to_artist_property(&artist_id_2, "MusicButler", vec![MUSICBUTLER]) .add_to_artist_property(&artist_id_2, "MusicButler", vec![MUSICBUTLER])
.is_err()); .is_err());
assert!(music_hoard.collection[0].meta.properties.is_empty()); assert!(music_hoard.collection[0].meta.info.properties.is_empty());
// Adding mutliple URLs without clashes. // Adding mutliple URLs without clashes.
assert!(music_hoard assert!(music_hoard
@ -587,19 +514,15 @@ mod tests {
.is_ok()); .is_ok());
expected.push(MUSICBUTLER.to_owned()); expected.push(MUSICBUTLER.to_owned());
expected.push(MUSICBUTLER_2.to_owned()); expected.push(MUSICBUTLER_2.to_owned());
assert_eq!( let info = &music_hoard.collection[0].meta.info;
music_hoard.collection[0].meta.properties.get("MusicButler"), assert_eq!(info.properties.get("MusicButler"), Some(&expected));
Some(&expected)
);
// Removing URLs from an artist not in the collection is an error. // Removing URLs from an artist not in the collection is an error.
assert!(music_hoard assert!(music_hoard
.remove_from_artist_property(&artist_id_2, "MusicButler", vec![MUSICBUTLER]) .remove_from_artist_property(&artist_id_2, "MusicButler", vec![MUSICBUTLER])
.is_err()); .is_err());
assert_eq!( let info = &music_hoard.collection[0].meta.info;
music_hoard.collection[0].meta.properties.get("MusicButler"), assert_eq!(info.properties.get("MusicButler"), Some(&expected));
Some(&expected)
);
// Removing multiple URLs without clashes. // Removing multiple URLs without clashes.
assert!(music_hoard assert!(music_hoard
@ -610,7 +533,7 @@ mod tests {
) )
.is_ok()); .is_ok());
expected.clear(); expected.clear();
assert!(music_hoard.collection[0].meta.properties.is_empty()); assert!(music_hoard.collection[0].meta.info.properties.is_empty());
} }
#[test] #[test]
@ -626,13 +549,13 @@ mod tests {
assert!(music_hoard.add_artist(artist_id.clone()).is_ok()); assert!(music_hoard.add_artist(artist_id.clone()).is_ok());
let mut expected: Vec<String> = vec![]; let mut expected: Vec<String> = vec![];
assert!(music_hoard.collection[0].meta.properties.is_empty()); assert!(music_hoard.collection[0].meta.info.properties.is_empty());
// Seting URL on an artist not in the collection is an error. // Seting URL on an artist not in the collection is an error.
assert!(music_hoard assert!(music_hoard
.set_artist_property(&artist_id_2, "MusicButler", vec![MUSICBUTLER]) .set_artist_property(&artist_id_2, "MusicButler", vec![MUSICBUTLER])
.is_err()); .is_err());
assert!(music_hoard.collection[0].meta.properties.is_empty()); assert!(music_hoard.collection[0].meta.info.properties.is_empty());
// Set URLs. // Set URLs.
assert!(music_hoard assert!(music_hoard
@ -641,10 +564,8 @@ mod tests {
expected.clear(); expected.clear();
expected.push(MUSICBUTLER.to_owned()); expected.push(MUSICBUTLER.to_owned());
expected.push(MUSICBUTLER_2.to_owned()); expected.push(MUSICBUTLER_2.to_owned());
assert_eq!( let info = &music_hoard.collection[0].meta.info;
music_hoard.collection[0].meta.properties.get("MusicButler"), assert_eq!(info.properties.get("MusicButler"), Some(&expected));
Some(&expected)
);
// Clearing URLs on an artist that does not exist is an error. // Clearing URLs on an artist that does not exist is an error.
assert!(music_hoard assert!(music_hoard
@ -656,7 +577,7 @@ mod tests {
.clear_artist_property(&artist_id, "MusicButler") .clear_artist_property(&artist_id, "MusicButler")
.is_ok()); .is_ok());
expected.clear(); expected.clear();
assert!(music_hoard.collection[0].meta.properties.is_empty()); assert!(music_hoard.collection[0].meta.info.properties.is_empty());
} }
#[test] #[test]

View File

@ -52,7 +52,7 @@ impl<Database, Library: ILibrary> MusicHoard<Database, Library> {
name: item.album_artist, name: item.album_artist,
}; };
let artist_sort = item.album_artist_sort.map(|s| ArtistId { name: s }); let artist_sort = item.album_artist_sort;
let album_id = AlbumId { let album_id = AlbumId {
title: item.album_title, title: item.album_title,

View File

@ -2,8 +2,8 @@ use once_cell::sync::Lazy;
use std::collections::HashMap; use std::collections::HashMap;
use crate::core::collection::{ use crate::core::collection::{
album::{Album, AlbumId, AlbumMeta, AlbumPrimaryType, AlbumSeq}, album::{Album, AlbumId, AlbumInfo, AlbumMeta, AlbumPrimaryType, AlbumSeq},
artist::{Artist, ArtistId, ArtistMeta}, artist::{Artist, ArtistId, ArtistInfo, ArtistMeta},
musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption}, musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption},
track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality}, track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality},
}; };

View File

@ -4,8 +4,8 @@ use serde::{de::Visitor, Deserialize, Deserializer};
use crate::{ use crate::{
collection::{ collection::{
album::AlbumMeta, album::{AlbumInfo, AlbumMeta},
artist::ArtistMeta, artist::{ArtistInfo, ArtistMeta},
musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption, Mbid}, musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption, Mbid},
}, },
core::collection::{ core::collection::{
@ -114,10 +114,12 @@ impl From<DeserializeArtist> for Artist {
Artist { Artist {
meta: ArtistMeta { meta: ArtistMeta {
id: ArtistId::new(artist.name), id: ArtistId::new(artist.name),
sort: artist.sort.map(ArtistId::new), sort: artist.sort,
info: ArtistInfo {
musicbrainz: artist.musicbrainz.into(), musicbrainz: artist.musicbrainz.into(),
properties: artist.properties, properties: artist.properties,
}, },
},
albums: artist.albums.into_iter().map(Into::into).collect(), albums: artist.albums.into_iter().map(Into::into).collect(),
} }
} }
@ -130,10 +132,12 @@ impl From<DeserializeAlbum> for 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),
info: AlbumInfo {
musicbrainz: album.musicbrainz.into(), musicbrainz: album.musicbrainz.into(),
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![],
} }
} }

View File

@ -72,10 +72,11 @@ impl<'a> From<&'a Artist> for SerializeArtist<'a> {
fn from(artist: &'a Artist) -> Self { fn from(artist: &'a Artist) -> Self {
SerializeArtist { SerializeArtist {
name: &artist.meta.id.name, name: &artist.meta.id.name,
sort: artist.meta.sort.as_ref().map(|id| id.name.as_ref()), sort: artist.meta.sort.as_deref(),
musicbrainz: (&artist.meta.musicbrainz).into(), musicbrainz: (&artist.meta.info.musicbrainz).into(),
properties: artist properties: artist
.meta .meta
.info
.properties .properties
.iter() .iter()
.map(|(k, v)| (k.as_ref(), v)) .map(|(k, v)| (k.as_ref(), v))
@ -90,10 +91,11 @@ impl<'a> From<&'a Album> for SerializeAlbum<'a> {
SerializeAlbum { SerializeAlbum {
title: &album.meta.id.title, title: &album.meta.id.title,
seq: album.meta.seq.0, seq: album.meta.seq.0,
musicbrainz: (&album.meta.musicbrainz).into(), musicbrainz: (&album.meta.info.musicbrainz).into(),
primary_type: album.meta.primary_type.map(Into::into), primary_type: album.meta.info.primary_type.map(Into::into),
secondary_types: album secondary_types: album
.meta .meta
.info
.secondary_types .secondary_types
.iter() .iter()
.copied() .copied()

View File

@ -4,8 +4,7 @@ use serde::{de::Visitor, Deserialize, Deserializer};
use crate::{ use crate::{
collection::{ collection::{
album::{AlbumDate, AlbumId, AlbumPrimaryType, AlbumSecondaryType}, album::{AlbumDate, AlbumPrimaryType, AlbumSecondaryType},
artist::ArtistId,
musicbrainz::Mbid, musicbrainz::Mbid,
Error as CollectionError, Error as CollectionError,
}, },
@ -62,8 +61,8 @@ impl<Http> MusicBrainzClient<Http> {
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub struct MbArtistMeta { pub struct MbArtistMeta {
pub id: Mbid, pub id: Mbid,
pub name: ArtistId, pub name: String,
pub sort_name: ArtistId, pub sort_name: String,
pub disambiguation: Option<String>, pub disambiguation: Option<String>,
} }
@ -80,8 +79,8 @@ impl From<SerdeMbArtistMeta> for MbArtistMeta {
fn from(value: SerdeMbArtistMeta) -> Self { fn from(value: SerdeMbArtistMeta) -> Self {
MbArtistMeta { MbArtistMeta {
id: value.id.into(), id: value.id.into(),
name: value.name.into(), name: value.name,
sort_name: value.sort_name.into(), sort_name: value.sort_name,
disambiguation: value.disambiguation, disambiguation: value.disambiguation,
} }
} }
@ -90,7 +89,7 @@ impl From<SerdeMbArtistMeta> for MbArtistMeta {
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub struct MbReleaseGroupMeta { pub struct MbReleaseGroupMeta {
pub id: Mbid, pub id: Mbid,
pub title: AlbumId, pub title: String,
pub first_release_date: AlbumDate, pub first_release_date: AlbumDate,
pub primary_type: AlbumPrimaryType, pub primary_type: AlbumPrimaryType,
pub secondary_types: Option<Vec<AlbumSecondaryType>>, pub secondary_types: Option<Vec<AlbumSecondaryType>>,
@ -110,7 +109,7 @@ impl From<SerdeMbReleaseGroupMeta> for MbReleaseGroupMeta {
fn from(value: SerdeMbReleaseGroupMeta) -> Self { fn from(value: SerdeMbReleaseGroupMeta) -> Self {
MbReleaseGroupMeta { MbReleaseGroupMeta {
id: value.id.into(), id: value.id.into(),
title: value.title.into(), title: value.title,
first_release_date: value.first_release_date.into(), first_release_date: value.first_release_date.into(),
primary_type: value.primary_type.into(), primary_type: value.primary_type.into(),
secondary_types: value secondary_types: value

View File

@ -7,6 +7,7 @@ macro_rules! full_collection {
name: "Album_Artist A".to_string(), name: "Album_Artist A".to_string(),
}, },
sort: None, sort: None,
info: ArtistInfo {
musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str( musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str(
"https://musicbrainz.org/artist/00000000-0000-0000-0000-000000000000" "https://musicbrainz.org/artist/00000000-0000-0000-0000-000000000000"
).unwrap()), ).unwrap()),
@ -21,6 +22,7 @@ macro_rules! full_collection {
]), ]),
]), ]),
}, },
},
albums: vec![ albums: vec![
Album { Album {
meta: AlbumMeta { meta: AlbumMeta {
@ -29,12 +31,14 @@ macro_rules! full_collection {
}, },
date: 1998.into(), date: 1998.into(),
seq: AlbumSeq(1), seq: AlbumSeq(1),
info: AlbumInfo {
musicbrainz: MbRefOption::Some(MbAlbumRef::from_url_str( musicbrainz: MbRefOption::Some(MbAlbumRef::from_url_str(
"https://musicbrainz.org/release-group/00000000-0000-0000-0000-000000000000" "https://musicbrainz.org/release-group/00000000-0000-0000-0000-000000000000"
).unwrap()), ).unwrap()),
primary_type: Some(AlbumPrimaryType::Album), primary_type: Some(AlbumPrimaryType::Album),
secondary_types: vec![], secondary_types: vec![],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {
@ -92,10 +96,12 @@ macro_rules! full_collection {
}, },
date: (2015, 4).into(), date: (2015, 4).into(),
seq: AlbumSeq(1), seq: AlbumSeq(1),
info: AlbumInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
primary_type: Some(AlbumPrimaryType::Album), primary_type: Some(AlbumPrimaryType::Album),
secondary_types: vec![], secondary_types: vec![],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {
@ -129,6 +135,7 @@ macro_rules! full_collection {
name: "Album_Artist B".to_string(), name: "Album_Artist B".to_string(),
}, },
sort: None, sort: None,
info: ArtistInfo {
musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str( musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str(
"https://musicbrainz.org/artist/11111111-1111-1111-1111-111111111111" "https://musicbrainz.org/artist/11111111-1111-1111-1111-111111111111"
).unwrap()), ).unwrap()),
@ -147,6 +154,7 @@ macro_rules! full_collection {
]), ]),
]), ]),
}, },
},
albums: vec![ albums: vec![
Album { Album {
meta: AlbumMeta { meta: AlbumMeta {
@ -155,10 +163,12 @@ macro_rules! full_collection {
}, },
date: (2003, 6, 6).into(), date: (2003, 6, 6).into(),
seq: AlbumSeq(1), seq: AlbumSeq(1),
info: AlbumInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
primary_type: Some(AlbumPrimaryType::Album), primary_type: Some(AlbumPrimaryType::Album),
secondary_types: vec![], secondary_types: vec![],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {
@ -194,12 +204,14 @@ macro_rules! full_collection {
}, },
date: 2008.into(), date: 2008.into(),
seq: AlbumSeq(3), seq: AlbumSeq(3),
info: AlbumInfo {
musicbrainz: MbRefOption::Some(MbAlbumRef::from_url_str( musicbrainz: MbRefOption::Some(MbAlbumRef::from_url_str(
"https://musicbrainz.org/release-group/11111111-1111-1111-1111-111111111111" "https://musicbrainz.org/release-group/11111111-1111-1111-1111-111111111111"
).unwrap()), ).unwrap()),
primary_type: Some(AlbumPrimaryType::Album), primary_type: Some(AlbumPrimaryType::Album),
secondary_types: vec![], secondary_types: vec![],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {
@ -235,12 +247,14 @@ macro_rules! full_collection {
}, },
date: 2009.into(), date: 2009.into(),
seq: AlbumSeq(2), seq: AlbumSeq(2),
info: AlbumInfo {
musicbrainz: MbRefOption::Some(MbAlbumRef::from_url_str( musicbrainz: MbRefOption::Some(MbAlbumRef::from_url_str(
"https://musicbrainz.org/release-group/11111111-1111-1111-1111-111111111112" "https://musicbrainz.org/release-group/11111111-1111-1111-1111-111111111112"
).unwrap()), ).unwrap()),
primary_type: Some(AlbumPrimaryType::Album), primary_type: Some(AlbumPrimaryType::Album),
secondary_types: vec![], secondary_types: vec![],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {
@ -276,10 +290,12 @@ macro_rules! full_collection {
}, },
date: 2015.into(), date: 2015.into(),
seq: AlbumSeq(4), seq: AlbumSeq(4),
info: AlbumInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
primary_type: Some(AlbumPrimaryType::Album), primary_type: Some(AlbumPrimaryType::Album),
secondary_types: vec![], secondary_types: vec![],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {
@ -315,12 +331,12 @@ macro_rules! full_collection {
id: ArtistId { id: ArtistId {
name: "The Album_Artist C".to_string(), name: "The Album_Artist C".to_string(),
}, },
sort: Some(ArtistId { sort: Some("Album_Artist C, The".to_string()),
name: "Album_Artist C, The".to_string(), info: ArtistInfo {
}),
musicbrainz: MbRefOption::CannotHaveMbid, musicbrainz: MbRefOption::CannotHaveMbid,
properties: HashMap::new(), properties: HashMap::new(),
}, },
},
albums: vec![ albums: vec![
Album { Album {
meta: AlbumMeta { meta: AlbumMeta {
@ -329,10 +345,12 @@ macro_rules! full_collection {
}, },
date: 1985.into(), date: 1985.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
info: AlbumInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
primary_type: Some(AlbumPrimaryType::Album), primary_type: Some(AlbumPrimaryType::Album),
secondary_types: vec![], secondary_types: vec![],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {
@ -368,10 +386,12 @@ macro_rules! full_collection {
}, },
date: 2018.into(), date: 2018.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
info: AlbumInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
primary_type: Some(AlbumPrimaryType::Album), primary_type: Some(AlbumPrimaryType::Album),
secondary_types: vec![], secondary_types: vec![],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {
@ -408,9 +428,11 @@ macro_rules! full_collection {
name: "Album_Artist D".to_string(), name: "Album_Artist D".to_string(),
}, },
sort: None, sort: None,
info: ArtistInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
properties: HashMap::new(), properties: HashMap::new(),
}, },
},
albums: vec![ albums: vec![
Album { Album {
meta: AlbumMeta { meta: AlbumMeta {
@ -419,10 +441,12 @@ macro_rules! full_collection {
}, },
date: 1995.into(), date: 1995.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
info: AlbumInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
primary_type: Some(AlbumPrimaryType::Album), primary_type: Some(AlbumPrimaryType::Album),
secondary_types: vec![], secondary_types: vec![],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {
@ -458,10 +482,12 @@ macro_rules! full_collection {
}, },
date: 2028.into(), date: 2028.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
info: AlbumInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
primary_type: Some(AlbumPrimaryType::Album), primary_type: Some(AlbumPrimaryType::Album),
secondary_types: vec![], secondary_types: vec![],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {

View File

@ -8,9 +8,11 @@ macro_rules! library_collection {
name: "Album_Artist A".to_string(), name: "Album_Artist A".to_string(),
}, },
sort: None, sort: None,
info: ArtistInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
properties: HashMap::new(), properties: HashMap::new(),
}, },
},
albums: vec![ albums: vec![
Album { Album {
meta: AlbumMeta { meta: AlbumMeta {
@ -19,9 +21,7 @@ macro_rules! library_collection {
}, },
date: 1998.into(), date: 1998.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
musicbrainz: MbRefOption::None, info: AlbumInfo::default(),
primary_type: None,
secondary_types: vec![],
}, },
tracks: vec![ tracks: vec![
Track { Track {
@ -80,9 +80,7 @@ macro_rules! library_collection {
}, },
date: (2015, 4).into(), date: (2015, 4).into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
musicbrainz: MbRefOption::None, info: AlbumInfo::default(),
primary_type: None,
secondary_types: vec![],
}, },
tracks: vec![ tracks: vec![
Track { Track {
@ -117,9 +115,11 @@ macro_rules! library_collection {
name: "Album_Artist B".to_string(), name: "Album_Artist B".to_string(),
}, },
sort: None, sort: None,
info: ArtistInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
properties: HashMap::new(), properties: HashMap::new(),
}, },
},
albums: vec![ albums: vec![
Album { Album {
meta: AlbumMeta { meta: AlbumMeta {
@ -128,9 +128,7 @@ macro_rules! library_collection {
}, },
date: (2003, 6, 6).into(), date: (2003, 6, 6).into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
musicbrainz: MbRefOption::None, info: AlbumInfo::default(),
primary_type: None,
secondary_types: vec![],
}, },
tracks: vec![ tracks: vec![
Track { Track {
@ -167,9 +165,7 @@ macro_rules! library_collection {
}, },
date: 2008.into(), date: 2008.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
musicbrainz: MbRefOption::None, info: AlbumInfo::default(),
primary_type: None,
secondary_types: vec![],
}, },
tracks: vec![ tracks: vec![
Track { Track {
@ -206,9 +202,7 @@ macro_rules! library_collection {
}, },
date: 2009.into(), date: 2009.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
musicbrainz: MbRefOption::None, info: AlbumInfo::default(),
primary_type: None,
secondary_types: vec![],
}, },
tracks: vec![ tracks: vec![
Track { Track {
@ -245,9 +239,7 @@ macro_rules! library_collection {
}, },
date: 2015.into(), date: 2015.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
musicbrainz: MbRefOption::None, info: AlbumInfo::default(),
primary_type: None,
secondary_types: vec![],
}, },
tracks: vec![ tracks: vec![
Track { Track {
@ -284,12 +276,12 @@ macro_rules! library_collection {
id: ArtistId { id: ArtistId {
name: "The Album_Artist C".to_string(), name: "The Album_Artist C".to_string(),
}, },
sort: Some(ArtistId { sort: Some("Album_Artist C, The".to_string()),
name: "Album_Artist C, The".to_string(), info: ArtistInfo {
}),
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
properties: HashMap::new(), properties: HashMap::new(),
}, },
},
albums: vec![ albums: vec![
Album { Album {
meta: AlbumMeta { meta: AlbumMeta {
@ -298,9 +290,7 @@ macro_rules! library_collection {
}, },
date: 1985.into(), date: 1985.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
musicbrainz: MbRefOption::None, info: AlbumInfo::default(),
primary_type: None,
secondary_types: vec![],
}, },
tracks: vec![ tracks: vec![
Track { Track {
@ -337,9 +327,7 @@ macro_rules! library_collection {
}, },
date: 2018.into(), date: 2018.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
musicbrainz: MbRefOption::None, info: AlbumInfo::default(),
primary_type: None,
secondary_types: vec![],
}, },
tracks: vec![ tracks: vec![
Track { Track {
@ -377,9 +365,11 @@ macro_rules! library_collection {
name: "Album_Artist D".to_string(), name: "Album_Artist D".to_string(),
}, },
sort: None, sort: None,
info: ArtistInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
properties: HashMap::new(), properties: HashMap::new(),
}, },
},
albums: vec![ albums: vec![
Album { Album {
meta: AlbumMeta { meta: AlbumMeta {
@ -388,9 +378,7 @@ macro_rules! library_collection {
}, },
date: 1995.into(), date: 1995.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
musicbrainz: MbRefOption::None, info: AlbumInfo::default(),
primary_type: None,
secondary_types: vec![],
}, },
tracks: vec![ tracks: vec![
Track { Track {
@ -427,9 +415,7 @@ macro_rules! library_collection {
}, },
date: 2028.into(), date: 2028.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
musicbrainz: MbRefOption::None, info: AlbumInfo::default(),
primary_type: None,
secondary_types: vec![],
}, },
tracks: vec![ tracks: vec![
Track { Track {

View File

@ -156,12 +156,12 @@ impl AppMachine<FetchState> {
result_sender: ResultSender, result_sender: ResultSender,
artist: &Artist, artist: &Artist,
) -> Result<(), FetchError> { ) -> Result<(), FetchError> {
let requests = match artist.meta.musicbrainz { let requests = match artist.meta.info.musicbrainz {
MbRefOption::Some(ref arid) => { MbRefOption::Some(ref arid) => {
let arid = arid.mbid(); let arid = arid.mbid();
let albums = artist.albums.iter(); let albums = artist.albums.iter();
albums albums
.filter(|album| matches!(album.meta.musicbrainz, MbRefOption::None)) .filter(|album| matches!(album.meta.info.musicbrainz, MbRefOption::None))
.map(|album| { .map(|album| {
MbParams::search_release_group( MbParams::search_release_group(
artist.meta.id.clone(), artist.meta.id.clone(),

View File

@ -26,12 +26,13 @@ macro_rules! item_option_artist_set {
music_hoard: &mut dyn IMusicHoard, music_hoard: &mut dyn IMusicHoard,
meta: &ArtistMeta, meta: &ArtistMeta,
) -> Result<(), musichoard::Error> { ) -> Result<(), musichoard::Error> {
let mbref = match self { let mut info = meta.info.clone();
MatchOption::Some(m) => m.item.musicbrainz, info.musicbrainz = match self {
MatchOption::Some(m) => m.item.info.musicbrainz,
MatchOption::CannotHaveMbid => MbRefOption::CannotHaveMbid, MatchOption::CannotHaveMbid => MbRefOption::CannotHaveMbid,
MatchOption::ManualInputMbid => panic!(), MatchOption::ManualInputMbid => panic!(),
}; };
music_hoard.set_artist_musicbrainz(&meta.id, mbref) music_hoard.set_artist_info(&meta.id, info)
} }
} }
}; };
@ -49,19 +50,17 @@ macro_rules! item_option_album_set {
artist: &ArtistId, artist: &ArtistId,
meta: &AlbumMeta, meta: &AlbumMeta,
) -> Result<(), musichoard::Error> { ) -> Result<(), musichoard::Error> {
let (mbref, primary_type, secondary_types) = match self { let mut info = meta.info.clone();
(info.musicbrainz, info.primary_type, info.secondary_types) = match self {
MatchOption::Some(m) => ( MatchOption::Some(m) => (
m.item.musicbrainz, m.item.info.musicbrainz,
m.item.primary_type, m.item.info.primary_type,
m.item.secondary_types, m.item.info.secondary_types,
), ),
MatchOption::CannotHaveMbid => (MbRefOption::CannotHaveMbid, None, Vec::new()), MatchOption::CannotHaveMbid => (MbRefOption::CannotHaveMbid, None, Vec::new()),
MatchOption::ManualInputMbid => panic!(), MatchOption::ManualInputMbid => panic!(),
}; };
music_hoard.set_album_musicbrainz(artist, &meta.id, mbref)?; music_hoard.set_album_info(artist, &meta.id, info)
music_hoard.set_album_primary_type(artist, &meta.id, primary_type)?;
music_hoard.set_album_secondary_types(artist, &meta.id, secondary_types)?;
Ok(())
} }
} }
}; };
@ -343,7 +342,7 @@ mod tests {
use mockall::predicate; use mockall::predicate;
use musichoard::collection::{ use musichoard::collection::{
album::{AlbumDate, AlbumId, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType}, album::{AlbumDate, AlbumId, AlbumInfo, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType},
artist::{ArtistId, ArtistMeta}, artist::{ArtistId, ArtistMeta},
}; };
@ -404,8 +403,11 @@ mod tests {
let album = AlbumMeta::new( let album = AlbumMeta::new(
AlbumId::new("Album"), AlbumId::new("Album"),
AlbumDate::new(Some(1990), Some(5), None), AlbumDate::new(Some(1990), Some(5), None),
AlbumInfo::new(
MbRefOption::None,
Some(AlbumPrimaryType::Album), Some(AlbumPrimaryType::Album),
vec![AlbumSecondaryType::Live, AlbumSecondaryType::Compilation], vec![AlbumSecondaryType::Live, AlbumSecondaryType::Compilation],
),
); );
let album_1 = album.clone(); let album_1 = album.clone();
@ -413,7 +415,7 @@ mod tests {
let mut album_2 = album.clone(); let mut album_2 = album.clone();
album_2.id.title.push_str(" extra title part"); album_2.id.title.push_str(" extra title part");
album_2.secondary_types.pop(); album_2.info.secondary_types.pop();
let album_match_2 = Match::new(100, album_2); let album_match_2 = Match::new(100, album_2);
let list = vec![album_match_1.clone(), album_match_2.clone()]; let list = vec![album_match_1.clone(), album_match_2.clone()];
@ -425,8 +427,11 @@ mod tests {
let album = AlbumMeta::new( let album = AlbumMeta::new(
AlbumId::new("Album"), AlbumId::new("Album"),
AlbumDate::new(Some(1990), Some(5), None), AlbumDate::new(Some(1990), Some(5), None),
AlbumInfo::new(
MbRefOption::None,
Some(AlbumPrimaryType::Album), Some(AlbumPrimaryType::Album),
vec![AlbumSecondaryType::Live, AlbumSecondaryType::Compilation], vec![AlbumSecondaryType::Live, AlbumSecondaryType::Compilation],
),
); );
let lookup = Lookup::new(album.clone()); let lookup = Lookup::new(album.clone());
MatchStateInfo::album_lookup(artist_id, album, lookup) MatchStateInfo::album_lookup(artist_id, album, lookup)
@ -642,7 +647,7 @@ mod tests {
fn select_manual_input_album() { fn select_manual_input_album() {
let mut mb_job_sender = MockIMbJobSender::new(); let mut mb_job_sender = MockIMbJobSender::new();
let artist_id = ArtistId::new("Artist"); let artist_id = ArtistId::new("Artist");
let album = AlbumMeta::new("Album", 1990, None, vec![]); let album = AlbumMeta::new("Album", 1990, AlbumInfo::default());
let requests = VecDeque::from([MbParams::lookup_release_group( let requests = VecDeque::from([MbParams::lookup_release_group(
artist_id.clone(), artist_id.clone(),
album.clone(), album.clone(),

View File

@ -182,7 +182,7 @@ impl IAppInteractSearchPrivate for AppMachine<SearchState> {
if let Some(ref probe_sort) = probe.meta.sort { if let Some(ref probe_sort) = probe.meta.sort {
if !result { if !result {
let name = Self::normalize_search(&probe_sort.name, !case_sens, !char_sens); let name = Self::normalize_search(probe_sort, !case_sens, !char_sens);
result = name.starts_with(search); result = name.starts_with(search);
} }
} }

View File

@ -205,14 +205,14 @@ impl KeySelectArtist {
let artist = &artists[index]; let artist = &artists[index];
let key = artist.meta.get_sort_key(); let key = artist.meta.get_sort_key();
KeySelectArtist { KeySelectArtist {
key: (key.0.to_owned(),), key: (key.0.into(),),
album: KeySelectAlbum::get(&artist.albums, &selection.album), album: KeySelectAlbum::get(&artist.albums, &selection.album),
} }
}) })
} }
pub fn get_sort_key(&self) -> (&ArtistId,) { pub fn get_sort_key(&self) -> (&str,) {
(&self.key.0,) (&self.key.0.name,)
} }
} }

View File

@ -4,8 +4,8 @@ use std::collections::HashMap;
use musichoard::{ use musichoard::{
collection::{ collection::{
album::{AlbumDate, AlbumMeta, AlbumSeq}, album::{AlbumDate, AlbumInfo, AlbumMeta, AlbumSeq},
artist::{ArtistId, ArtistMeta}, artist::{ArtistInfo, ArtistMeta},
musicbrainz::{MbRefOption, Mbid}, musicbrainz::{MbRefOption, Mbid},
}, },
external::musicbrainz::{ external::musicbrainz::{
@ -93,16 +93,16 @@ impl<Http: IMusicBrainzHttp> IMusicBrainz for MusicBrainz<Http> {
} }
fn from_lookup_artist_response(entity: LookupArtistResponse) -> Lookup<ArtistMeta> { fn from_lookup_artist_response(entity: LookupArtistResponse) -> Lookup<ArtistMeta> {
let sort: Option<ArtistId> = Some(entity.meta.sort_name) let sort = Some(entity.meta.sort_name).filter(|s| s != &entity.meta.name);
.filter(|s| s != &entity.meta.name)
.map(Into::into);
Lookup { Lookup {
item: ArtistMeta { item: ArtistMeta {
id: entity.meta.name, id: entity.meta.name.into(),
sort, sort,
info: ArtistInfo {
musicbrainz: MbRefOption::Some(entity.meta.id.into()), musicbrainz: MbRefOption::Some(entity.meta.id.into()),
properties: HashMap::new(), properties: HashMap::new(),
}, },
},
disambiguation: entity.meta.disambiguation, disambiguation: entity.meta.disambiguation,
} }
} }
@ -110,29 +110,31 @@ fn from_lookup_artist_response(entity: LookupArtistResponse) -> Lookup<ArtistMet
fn from_lookup_release_group_response(entity: LookupReleaseGroupResponse) -> Lookup<AlbumMeta> { fn from_lookup_release_group_response(entity: LookupReleaseGroupResponse) -> Lookup<AlbumMeta> {
Lookup { Lookup {
item: AlbumMeta { item: AlbumMeta {
id: entity.meta.title, id: entity.meta.title.into(),
date: entity.meta.first_release_date, date: entity.meta.first_release_date,
seq: AlbumSeq::default(), seq: AlbumSeq::default(),
info: AlbumInfo {
musicbrainz: MbRefOption::Some(entity.meta.id.into()), musicbrainz: MbRefOption::Some(entity.meta.id.into()),
primary_type: Some(entity.meta.primary_type), primary_type: Some(entity.meta.primary_type),
secondary_types: entity.meta.secondary_types.unwrap_or_default(), secondary_types: entity.meta.secondary_types.unwrap_or_default(),
}, },
},
disambiguation: None, disambiguation: None,
} }
} }
fn from_search_artist_response_artist(entity: SearchArtistResponseArtist) -> Match<ArtistMeta> { fn from_search_artist_response_artist(entity: SearchArtistResponseArtist) -> Match<ArtistMeta> {
let sort: Option<ArtistId> = Some(entity.meta.sort_name) let sort = Some(entity.meta.sort_name).filter(|s| s != &entity.meta.name);
.filter(|s| s != &entity.meta.name)
.map(Into::into);
Match { Match {
score: entity.score, score: entity.score,
item: ArtistMeta { item: ArtistMeta {
id: entity.meta.name, id: entity.meta.name.into(),
sort, sort,
info: ArtistInfo {
musicbrainz: MbRefOption::Some(entity.meta.id.into()), musicbrainz: MbRefOption::Some(entity.meta.id.into()),
properties: HashMap::new(), properties: HashMap::new(),
}, },
},
disambiguation: entity.meta.disambiguation, disambiguation: entity.meta.disambiguation,
} }
} }
@ -143,13 +145,15 @@ fn from_search_release_group_response_release_group(
Match { Match {
score: entity.score, score: entity.score,
item: AlbumMeta { item: AlbumMeta {
id: entity.meta.title, id: entity.meta.title.into(),
date: entity.meta.first_release_date, date: entity.meta.first_release_date,
seq: AlbumSeq::default(), seq: AlbumSeq::default(),
info: AlbumInfo {
musicbrainz: MbRefOption::Some(entity.meta.id.into()), musicbrainz: MbRefOption::Some(entity.meta.id.into()),
primary_type: Some(entity.meta.primary_type), primary_type: Some(entity.meta.primary_type),
secondary_types: entity.meta.secondary_types.unwrap_or_default(), secondary_types: entity.meta.secondary_types.unwrap_or_default(),
}, },
},
disambiguation: None, disambiguation: None,
} }
} }

View File

@ -419,7 +419,7 @@ mod tests {
} }
fn search_albums_requests() -> VecDeque<MbParams> { fn search_albums_requests() -> VecDeque<MbParams> {
let mbref = mb_ref_opt_as_ref(&COLLECTION[1].meta.musicbrainz); let mbref = mb_ref_opt_as_ref(&COLLECTION[1].meta.info.musicbrainz);
let arid = mb_ref_opt_unwrap(mbref).mbid().clone(); let arid = mb_ref_opt_unwrap(mbref).mbid().clone();
let artist_id = COLLECTION[1].meta.id.clone(); let artist_id = COLLECTION[1].meta.id.clone();
@ -437,7 +437,7 @@ mod tests {
} }
fn album_arid_expectation() -> Mbid { fn album_arid_expectation() -> Mbid {
let mbref = mb_ref_opt_as_ref(&COLLECTION[1].meta.musicbrainz); let mbref = mb_ref_opt_as_ref(&COLLECTION[1].meta.info.musicbrainz);
mb_ref_opt_unwrap(mbref).mbid().clone() mb_ref_opt_unwrap(mbref).mbid().clone()
} }

View File

@ -3,9 +3,8 @@ pub mod interface;
use musichoard::{ use musichoard::{
collection::{ collection::{
album::{AlbumId, AlbumPrimaryType, AlbumSecondaryType}, album::{AlbumId, AlbumInfo},
artist::ArtistId, artist::{ArtistId, ArtistInfo},
musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption},
Collection, Collection,
}, },
interface::{database::IDatabase, library::ILibrary}, interface::{database::IDatabase, library::ILibrary},
@ -21,28 +20,13 @@ pub trait IMusicHoard {
fn reload_database(&mut self) -> Result<(), musichoard::Error>; fn reload_database(&mut self) -> Result<(), musichoard::Error>;
fn get_collection(&self) -> &Collection; fn get_collection(&self) -> &Collection;
fn set_artist_musicbrainz( fn set_artist_info(&mut self, id: &ArtistId, info: ArtistInfo)
&mut self, -> Result<(), musichoard::Error>;
id: &ArtistId, fn set_album_info(
mbref: MbRefOption<MbArtistRef>,
) -> Result<(), musichoard::Error>;
fn set_album_musicbrainz(
&mut self, &mut self,
artist_id: &ArtistId, artist_id: &ArtistId,
album_id: &AlbumId, album_id: &AlbumId,
mbref: MbRefOption<MbAlbumRef>, info: AlbumInfo,
) -> Result<(), musichoard::Error>;
fn set_album_primary_type(
&mut self,
artist_id: &ArtistId,
album_id: &AlbumId,
primary_type: Option<AlbumPrimaryType>,
) -> Result<(), musichoard::Error>;
fn set_album_secondary_types(
&mut self,
artist_id: &ArtistId,
album_id: &AlbumId,
secondary_types: Vec<AlbumSecondaryType>,
) -> Result<(), musichoard::Error>; ) -> Result<(), musichoard::Error>;
} }
@ -60,49 +44,21 @@ impl<Database: IDatabase, Library: ILibrary> IMusicHoard for MusicHoard<Database
<Self as IMusicHoardBase>::get_collection(self) <Self as IMusicHoardBase>::get_collection(self)
} }
fn set_artist_musicbrainz( fn set_artist_info(
&mut self, &mut self,
id: &ArtistId, id: &ArtistId,
mbref: MbRefOption<MbArtistRef>, info: ArtistInfo,
) -> Result<(), musichoard::Error> { ) -> Result<(), musichoard::Error> {
<Self as IMusicHoardDatabase>::set_artist_musicbrainz(self, id, mbref) <Self as IMusicHoardDatabase>::set_artist_info(self, id, info)
} }
fn set_album_musicbrainz( fn set_album_info(
&mut self, &mut self,
artist_id: &ArtistId, artist_id: &ArtistId,
album_id: &AlbumId, album_id: &AlbumId,
mbref: MbRefOption<MbAlbumRef>, info: AlbumInfo,
) -> Result<(), musichoard::Error> { ) -> Result<(), musichoard::Error> {
<Self as IMusicHoardDatabase>::set_album_musicbrainz(self, artist_id, album_id, mbref) <Self as IMusicHoardDatabase>::set_album_info(self, artist_id, album_id, info)
}
fn set_album_primary_type(
&mut self,
artist_id: &ArtistId,
album_id: &AlbumId,
primary_type: Option<AlbumPrimaryType>,
) -> Result<(), musichoard::Error> {
<Self as IMusicHoardDatabase>::set_album_primary_type(
self,
artist_id,
album_id,
primary_type,
)
}
fn set_album_secondary_types(
&mut self,
artist_id: &ArtistId,
album_id: &AlbumId,
secondary_types: Vec<AlbumSecondaryType>,
) -> Result<(), musichoard::Error> {
<Self as IMusicHoardDatabase>::set_album_secondary_types(
self,
artist_id,
album_id,
secondary_types,
)
} }
} }
// GRCOV_EXCL_STOP // GRCOV_EXCL_STOP

View File

@ -1,8 +1,8 @@
use std::collections::HashMap; use std::collections::HashMap;
use musichoard::collection::{ use musichoard::collection::{
album::{Album, AlbumId, AlbumMeta, AlbumPrimaryType, AlbumSeq}, album::{Album, AlbumId, AlbumInfo, AlbumMeta, AlbumPrimaryType, AlbumSeq},
artist::{Artist, ArtistId, ArtistMeta}, artist::{Artist, ArtistId, ArtistInfo, ArtistMeta},
musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption}, musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption},
track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality}, track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality},
}; };

View File

@ -169,7 +169,10 @@ impl<'a, 'b> AlbumState<'a, 'b> {
.map(|a| UiDisplay::display_date(&a.meta.date, &a.meta.seq)) .map(|a| UiDisplay::display_date(&a.meta.date, &a.meta.seq))
.unwrap_or_default(), .unwrap_or_default(),
album album
.map(|a| UiDisplay::display_type(&a.meta.primary_type, &a.meta.secondary_types)) .map(|a| UiDisplay::display_type(
&a.meta.info.primary_type,
&a.meta.info.secondary_types
))
.unwrap_or_default(), .unwrap_or_default(),
album album
.map(|a| UiDisplay::display_album_status(&a.get_status())) .map(|a| UiDisplay::display_album_status(&a.get_status()))

View File

@ -195,7 +195,7 @@ impl UiDisplay {
"{:010} | {} [{}]", "{:010} | {} [{}]",
UiDisplay::display_album_date(&album.date), UiDisplay::display_album_date(&album.date),
album.id.title, album.id.title,
UiDisplay::display_type(&album.primary_type, &album.secondary_types), UiDisplay::display_type(&album.info.primary_type, &album.info.secondary_types),
) )
} }

View File

@ -76,10 +76,10 @@ impl<'a> ArtistOverlay<'a> {
Properties: {}", Properties: {}",
artist.map(|a| a.meta.id.name.as_str()).unwrap_or(""), artist.map(|a| a.meta.id.name.as_str()).unwrap_or(""),
artist artist
.map(|a| UiDisplay::display_mb_ref_option_as_url(&a.meta.musicbrainz)) .map(|a| UiDisplay::display_mb_ref_option_as_url(&a.meta.info.musicbrainz))
.unwrap_or_default(), .unwrap_or_default(),
Self::opt_hashmap_to_string( Self::opt_hashmap_to_string(
artist.map(|a| &a.meta.properties), artist.map(|a| &a.meta.info.properties),
&double_item_indent, &double_item_indent,
&double_list_indent &double_list_indent
), ),
@ -104,7 +104,7 @@ impl<'a> AlbumOverlay<'a> {
MusicBrainz: {}", MusicBrainz: {}",
album.map(|a| a.meta.id.title.as_str()).unwrap_or(""), album.map(|a| a.meta.id.title.as_str()).unwrap_or(""),
album album
.map(|a| UiDisplay::display_mb_ref_option_as_url(&a.meta.musicbrainz)) .map(|a| UiDisplay::display_mb_ref_option_as_url(&a.meta.info.musicbrainz))
.unwrap_or_default(), .unwrap_or_default(),
)); ));

View File

@ -201,8 +201,9 @@ impl IUi for Ui {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use musichoard::collection::{ use musichoard::collection::{
album::{AlbumDate, AlbumId, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType}, album::{AlbumDate, AlbumId, AlbumInfo, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType},
artist::{Artist, ArtistId, ArtistMeta}, artist::{Artist, ArtistId, ArtistMeta},
musicbrainz::MbRefOption,
}; };
use crate::tui::{ use crate::tui::{
@ -381,8 +382,11 @@ mod tests {
AlbumMeta::new( AlbumMeta::new(
AlbumId::new("An Album"), AlbumId::new("An Album"),
AlbumDate::new(Some(1990), Some(5), None), AlbumDate::new(Some(1990), Some(5), None),
AlbumInfo::new(
MbRefOption::None,
Some(AlbumPrimaryType::Album), Some(AlbumPrimaryType::Album),
vec![AlbumSecondaryType::Live, AlbumSecondaryType::Compilation], vec![AlbumSecondaryType::Live, AlbumSecondaryType::Compilation],
),
) )
} }

View File

@ -2,8 +2,8 @@ use once_cell::sync::Lazy;
use std::collections::HashMap; use std::collections::HashMap;
use musichoard::collection::{ use musichoard::collection::{
album::{Album, AlbumId, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, AlbumSeq}, album::{Album, AlbumId, AlbumInfo, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, AlbumSeq},
artist::{Artist, ArtistId, ArtistMeta}, artist::{Artist, ArtistId, ArtistInfo, ArtistMeta},
musicbrainz::{MbArtistRef, MbRefOption}, musicbrainz::{MbArtistRef, MbRefOption},
track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality}, track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality},
Collection, Collection,
@ -16,9 +16,8 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
id: ArtistId { id: ArtistId {
name: String::from("Аркона"), name: String::from("Аркона"),
}, },
sort: Some(ArtistId{ sort: Some(String::from("Arkona")),
name: String::from("Arkona") info: ArtistInfo {
}),
musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str( musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str(
"https://musicbrainz.org/artist/baad262d-55ef-427a-83c7-f7530964f212" "https://musicbrainz.org/artist/baad262d-55ef-427a-83c7-f7530964f212"
).unwrap()), ).unwrap()),
@ -34,6 +33,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
)]), )]),
]), ]),
}, },
},
albums: vec![Album { albums: vec![Album {
meta: AlbumMeta { meta: AlbumMeta {
id: AlbumId { id: AlbumId {
@ -41,10 +41,12 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
}, },
date: 2011.into(), date: 2011.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
info: AlbumInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
primary_type: Some(AlbumPrimaryType::Album), primary_type: Some(AlbumPrimaryType::Album),
secondary_types: vec![], secondary_types: vec![],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {
@ -209,6 +211,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
name: String::from("Eluveitie"), name: String::from("Eluveitie"),
}, },
sort: None, sort: None,
info: ArtistInfo {
musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str( musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str(
"https://musicbrainz.org/artist/8000598a-5edb-401c-8e6d-36b167feaf38" "https://musicbrainz.org/artist/8000598a-5edb-401c-8e6d-36b167feaf38"
).unwrap()), ).unwrap()),
@ -221,6 +224,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
)]), )]),
]), ]),
}, },
},
albums: vec![ albums: vec![
Album { Album {
meta: AlbumMeta { meta: AlbumMeta {
@ -229,10 +233,12 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
}, },
date: 2004.into(), date: 2004.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
info: AlbumInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
primary_type: Some(AlbumPrimaryType::Ep), primary_type: Some(AlbumPrimaryType::Ep),
secondary_types: vec![], secondary_types: vec![],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {
@ -309,10 +315,12 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
}, },
date: 2008.into(), date: 2008.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
info: AlbumInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
primary_type: Some(AlbumPrimaryType::Album), primary_type: Some(AlbumPrimaryType::Album),
secondary_types: vec![], secondary_types: vec![],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {
@ -456,6 +464,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
name: String::from("Frontside"), name: String::from("Frontside"),
}, },
sort: None, sort: None,
info: ArtistInfo {
musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str( musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str(
"https://musicbrainz.org/artist/3a901353-fccd-4afd-ad01-9c03f451b490" "https://musicbrainz.org/artist/3a901353-fccd-4afd-ad01-9c03f451b490"
).unwrap()), ).unwrap()),
@ -468,6 +477,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
)]), )]),
]), ]),
}, },
},
albums: vec![Album { albums: vec![Album {
meta: AlbumMeta { meta: AlbumMeta {
id: AlbumId { id: AlbumId {
@ -475,10 +485,12 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
}, },
date: 2001.into(), date: 2001.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
info: AlbumInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
primary_type: Some(AlbumPrimaryType::Album), primary_type: Some(AlbumPrimaryType::Album),
secondary_types: vec![], secondary_types: vec![],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {
@ -609,9 +621,8 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
id: ArtistId { id: ArtistId {
name: String::from("Heavens Basement"), name: String::from("Heavens Basement"),
}, },
sort: Some(ArtistId { sort: Some(String::from("Heavens Basement")),
name: String::from("Heavens Basement"), info: ArtistInfo {
}),
musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str( musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str(
"https://musicbrainz.org/artist/c2c4d56a-d599-4a18-bd2f-ae644e2198cc" "https://musicbrainz.org/artist/c2c4d56a-d599-4a18-bd2f-ae644e2198cc"
).unwrap()), ).unwrap()),
@ -624,6 +635,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
)]), )]),
]), ]),
}, },
},
albums: vec![Album { albums: vec![Album {
meta: AlbumMeta { meta: AlbumMeta {
id: AlbumId { id: AlbumId {
@ -631,9 +643,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
}, },
date: 2011.into(), date: 2011.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
musicbrainz: MbRefOption::None, info: AlbumInfo::default(),
primary_type: None,
secondary_types: vec![],
}, },
tracks: vec![ tracks: vec![
Track { Track {
@ -655,10 +665,12 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
}, },
date: 2011.into(), date: 2011.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
info: AlbumInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
primary_type: Some(AlbumPrimaryType::Album), primary_type: Some(AlbumPrimaryType::Album),
secondary_types: vec![], secondary_types: vec![],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {
@ -746,6 +758,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
name: String::from("Metallica"), name: String::from("Metallica"),
}, },
sort: None, sort: None,
info: ArtistInfo {
musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str( musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str(
"https://musicbrainz.org/artist/65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab" "https://musicbrainz.org/artist/65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab"
).unwrap()), ).unwrap()),
@ -758,6 +771,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
)]), )]),
]), ]),
}, },
},
albums: vec![ albums: vec![
Album { Album {
meta: AlbumMeta { meta: AlbumMeta {
@ -766,10 +780,12 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
}, },
date: 1984.into(), date: 1984.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
info: AlbumInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
primary_type: Some(AlbumPrimaryType::Album), primary_type: Some(AlbumPrimaryType::Album),
secondary_types: vec![], secondary_types: vec![],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {
@ -868,10 +884,12 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
}, },
date: 1999.into(), date: 1999.into(),
seq: AlbumSeq(0), seq: AlbumSeq(0),
info: AlbumInfo {
musicbrainz: MbRefOption::None, musicbrainz: MbRefOption::None,
primary_type: Some(AlbumPrimaryType::Album), primary_type: Some(AlbumPrimaryType::Album),
secondary_types: vec![AlbumSecondaryType::Live], secondary_types: vec![AlbumSecondaryType::Live],
}, },
},
tracks: vec![ tracks: vec![
Track { Track {
id: TrackId { id: TrackId {