From c03bfe50215aac4d237cdd85ceca340f2533b2f5 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Wed, 1 Jan 2025 18:12:37 +0100 Subject: [PATCH 01/16] Collect library id --- src/core/collection/album.rs | 8 +++ src/core/interface/library/mod.rs | 14 ++++- src/core/interface/library/testmod.rs | 24 +++++++- src/external/library/beets/mod.rs | 37 ++++++++---- src/external/library/beets/testmod.rs | 44 +++++++------- tests/library/testmod.rs | 82 ++++++++++++++++++++++++++- 6 files changed, 171 insertions(+), 38 deletions(-) diff --git a/src/core/collection/album.rs b/src/core/collection/album.rs index 6356692..7919d6a 100644 --- a/src/core/collection/album.rs +++ b/src/core/collection/album.rs @@ -47,6 +47,14 @@ pub struct AlbumId { pub title: String, } +/// Unique library identifier. +#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)] +pub enum AlbumLibId { + Some(u32), + Singleton, + None, +} + // There are crates for handling dates, but we don't need much complexity beyond year-month-day. /// The album's release date. #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] diff --git a/src/core/interface/library/mod.rs b/src/core/interface/library/mod.rs index 76609bc..aedbe01 100644 --- a/src/core/interface/library/mod.rs +++ b/src/core/interface/library/mod.rs @@ -1,11 +1,11 @@ //! Module for interacting with the music library. -use std::{collections::HashSet, fmt, num::ParseIntError, str::Utf8Error}; +use std::{collections::HashSet, fmt, num::ParseIntError, str::{ParseBoolError, Utf8Error}}; #[cfg(test)] use mockall::automock; -use crate::core::collection::track::TrackFormat; +use crate::{collection::album::AlbumLibId, core::collection::track::TrackFormat}; /// Trait for interacting with the music library. #[cfg_attr(test, automock)] @@ -32,6 +32,7 @@ pub struct Item { pub album_month: u8, pub album_day: u8, pub album_title: String, + pub album_lib_id: AlbumLibId, pub track_number: u32, pub track_title: String, pub track_artist: Vec, @@ -90,6 +91,8 @@ pub enum Error { Io(String), /// The library received invalid data. Invalid(String), + /// The library failed to parse a boolean. + ParseBool(String), /// The library failed to parse an integer. ParseInt(String), /// The library failed to parse a UTF-8 string. @@ -102,6 +105,7 @@ impl fmt::Display for Error { Self::Executor(ref s) => write!(f, "the library's executor failed: {s}"), Self::Io(ref s) => write!(f, "the library experienced an I/O error: {s}"), Self::Invalid(ref s) => write!(f, "the library received invalid data: {s}"), + Self::ParseBool(ref s) => write!(f, "the library failed to parse a boolean: {s}"), Self::ParseInt(ref s) => write!(f, "the library failed to parse an integer: {s}"), Self::Utf8(ref s) => write!(f, "the library failed to parse a UTF-8 string: {s}"), } @@ -114,6 +118,12 @@ impl From for Error { } } +impl From for Error { + fn from(err: ParseBoolError) -> Error { + Error::ParseBool(err.to_string()) + } +} + impl From for Error { fn from(err: ParseIntError) -> Error { Error::ParseInt(err.to_string()) diff --git a/src/core/interface/library/testmod.rs b/src/core/interface/library/testmod.rs index 6afc5b9..8650732 100644 --- a/src/core/interface/library/testmod.rs +++ b/src/core/interface/library/testmod.rs @@ -1,6 +1,6 @@ use once_cell::sync::Lazy; -use crate::core::{collection::track::TrackFormat, interface::library::Item}; +use crate::{collection::album::AlbumLibId, core::{collection::track::TrackFormat, interface::library::Item}}; pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { vec![ @@ -11,6 +11,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title a.a"), + album_lib_id: AlbumLibId::Some(1), track_number: 1, track_title: String::from("track a.a.1"), track_artist: vec![String::from("artist a.a.1")], @@ -24,6 +25,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title a.a"), + album_lib_id: AlbumLibId::Some(1), track_number: 2, track_title: String::from("track a.a.2"), track_artist: vec![ @@ -40,6 +42,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title a.a"), + album_lib_id: AlbumLibId::Some(1), track_number: 3, track_title: String::from("track a.a.3"), track_artist: vec![String::from("artist a.a.3")], @@ -53,6 +56,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title a.a"), + album_lib_id: AlbumLibId::Some(1), track_number: 4, track_title: String::from("track a.a.4"), track_artist: vec![String::from("artist a.a.4")], @@ -66,6 +70,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 4, album_day: 0, album_title: String::from("album_title a.b"), + album_lib_id: AlbumLibId::Some(2), track_number: 1, track_title: String::from("track a.b.1"), track_artist: vec![String::from("artist a.b.1")], @@ -79,6 +84,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 4, album_day: 0, album_title: String::from("album_title a.b"), + album_lib_id: AlbumLibId::Some(2), track_number: 2, track_title: String::from("track a.b.2"), track_artist: vec![String::from("artist a.b.2")], @@ -92,6 +98,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 6, album_day: 6, album_title: String::from("album_title b.a"), + album_lib_id: AlbumLibId::Some(3), track_number: 1, track_title: String::from("track b.a.1"), track_artist: vec![String::from("artist b.a.1")], @@ -105,6 +112,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 6, album_day: 6, album_title: String::from("album_title b.a"), + album_lib_id: AlbumLibId::Some(3), track_number: 2, track_title: String::from("track b.a.2"), track_artist: vec![ @@ -121,6 +129,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title b.b"), + album_lib_id: AlbumLibId::Some(4), track_number: 1, track_title: String::from("track b.b.1"), track_artist: vec![String::from("artist b.b.1")], @@ -134,6 +143,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title b.b"), + album_lib_id: AlbumLibId::Some(4), track_number: 2, track_title: String::from("track b.b.2"), track_artist: vec![ @@ -150,6 +160,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title b.c"), + album_lib_id: AlbumLibId::Some(5), track_number: 1, track_title: String::from("track b.c.1"), track_artist: vec![String::from("artist b.c.1")], @@ -163,6 +174,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title b.c"), + album_lib_id: AlbumLibId::Some(5), track_number: 2, track_title: String::from("track b.c.2"), track_artist: vec![ @@ -179,6 +191,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title b.d"), + album_lib_id: AlbumLibId::Some(6), track_number: 1, track_title: String::from("track b.d.1"), track_artist: vec![String::from("artist b.d.1")], @@ -192,6 +205,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title b.d"), + album_lib_id: AlbumLibId::Some(6), track_number: 2, track_title: String::from("track b.d.2"), track_artist: vec![ @@ -208,6 +222,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title c.a"), + album_lib_id: AlbumLibId::Some(7), track_number: 1, track_title: String::from("track c.a.1"), track_artist: vec![String::from("artist c.a.1")], @@ -221,6 +236,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title c.a"), + album_lib_id: AlbumLibId::Some(7), track_number: 2, track_title: String::from("track c.a.2"), track_artist: vec![ @@ -237,6 +253,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title c.b"), + album_lib_id: AlbumLibId::Some(8), track_number: 1, track_title: String::from("track c.b.1"), track_artist: vec![String::from("artist c.b.1")], @@ -250,6 +267,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title c.b"), + album_lib_id: AlbumLibId::Some(8), track_number: 2, track_title: String::from("track c.b.2"), track_artist: vec![ @@ -266,6 +284,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title d.a"), + album_lib_id: AlbumLibId::Some(9), track_number: 1, track_title: String::from("track d.a.1"), track_artist: vec![String::from("artist d.a.1")], @@ -279,6 +298,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title d.a"), + album_lib_id: AlbumLibId::Some(9), track_number: 2, track_title: String::from("track d.a.2"), track_artist: vec![ @@ -295,6 +315,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title d.b"), + album_lib_id: AlbumLibId::Some(10), track_number: 1, track_title: String::from("track d.b.1"), track_artist: vec![String::from("artist d.b.1")], @@ -308,6 +329,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title d.b"), + album_lib_id: AlbumLibId::Some(10), track_number: 2, track_title: String::from("track d.b.2"), track_artist: vec![ diff --git a/src/external/library/beets/mod.rs b/src/external/library/beets/mod.rs index e157029..2cbfd9d 100644 --- a/src/external/library/beets/mod.rs +++ b/src/external/library/beets/mod.rs @@ -6,9 +6,12 @@ pub mod executor; #[cfg(test)] use mockall::automock; -use crate::core::{ - collection::track::TrackFormat, - interface::library::{Error, Field, ILibrary, Item, Query}, +use crate::{ + collection::album::AlbumLibId, + core::{ + collection::track::TrackFormat, + interface::library::{Error, Field, ILibrary, Item, Query}, + }, }; macro_rules! list_format_separator { @@ -31,8 +34,12 @@ const LIST_FORMAT_ARG: &str = concat!( list_format_separator!(), "$day", list_format_separator!(), + "$singleton", + list_format_separator!(), "$album", list_format_separator!(), + "$album_id", + list_format_separator!(), "$track", list_format_separator!(), "$title", @@ -144,7 +151,7 @@ impl BeetsLibrary { } let split: Vec<&str> = line.split(LIST_FORMAT_SEPARATOR).collect(); - if split.len() != 11 { + if split.len() != 13 { return Err(Error::Invalid(line.to_string())); } @@ -156,15 +163,20 @@ impl BeetsLibrary { let album_year = split[2].parse::()?; let album_month = split[3].parse::()?; let album_day = split[4].parse::()?; - let album_title = split[5].to_string(); - let track_number = split[6].parse::()?; - let track_title = split[7].to_string(); - let track_artist = split[8].split("; ").map(|s| s.to_owned()).collect(); - let track_format = match str_to_format(split[9].to_string().as_str()) { + let singleton = split[5].to_lowercase().parse::()?; + let album_title = split[6].to_string(); + let album_lib_id = match singleton { + true => AlbumLibId::Singleton, + false => AlbumLibId::Some(split[7].parse::()?), + }; + let track_number = split[8].parse::()?; + let track_title = split[9].to_string(); + let track_artist = split[10].split("; ").map(|s| s.to_owned()).collect(); + let track_format = match str_to_format(split[11].to_string().as_str()) { Some(format) => format, None => return Err(Error::Invalid(line.to_string())), }; - let track_bitrate = split[10].trim_end_matches("kbps").parse::()?; + let track_bitrate = split[12].trim_end_matches("kbps").parse::()?; items.push(Item { album_artist, @@ -173,6 +185,7 @@ impl BeetsLibrary { album_month, album_day, album_title, + album_lib_id, track_number, track_title, track_artist, @@ -358,8 +371,8 @@ mod tests { .split(LIST_FORMAT_SEPARATOR) .map(|s| s.to_owned()) .collect::>(); - invalid_string[9].clear(); - invalid_string[9].push_str("invalid format"); + invalid_string[11].clear(); + invalid_string[11].push_str("invalid format"); let invalid_string = invalid_string.join(LIST_FORMAT_SEPARATOR); output[2] = invalid_string.clone(); let result = Ok(output); diff --git a/src/external/library/beets/testmod.rs b/src/external/library/beets/testmod.rs index b0fc10a..e75f1f4 100644 --- a/src/external/library/beets/testmod.rs +++ b/src/external/library/beets/testmod.rs @@ -4,112 +4,112 @@ pub static LIBRARY_BEETS: Lazy> = Lazy::new(|| -> Vec { vec![ String::from( "Album_Artist ‘A’ -*^- -*^- \ - 1998 -*^- 00 -*^- 00 -*^- album_title a.a -*^- \ + 1998 -*^- 00 -*^- 00 -*^- False -*^- album_title a.a -*^- 1 -*^- \ 1 -*^- track a.a.1 -*^- artist a.a.1 -*^- FLAC -*^- 992", ), String::from( "Album_Artist ‘A’ -*^- -*^- \ - 1998 -*^- 00 -*^- 00 -*^- album_title a.a -*^- \ + 1998 -*^- 00 -*^- 00 -*^- False -*^- album_title a.a -*^- 1 -*^- \ 2 -*^- track a.a.2 -*^- artist a.a.2.1; artist a.a.2.2 -*^- MP3 -*^- 320", ), String::from( "Album_Artist ‘A’ -*^- -*^- \ - 1998 -*^- 00 -*^- 00 -*^- album_title a.a -*^- \ + 1998 -*^- 00 -*^- 00 -*^- False -*^- album_title a.a -*^- 1 -*^- \ 3 -*^- track a.a.3 -*^- artist a.a.3 -*^- FLAC -*^- 1061", ), String::from( "Album_Artist ‘A’ -*^- -*^- \ - 1998 -*^- 00 -*^- 00 -*^- album_title a.a -*^- \ + 1998 -*^- 00 -*^- 00 -*^- False -*^- album_title a.a -*^- 1 -*^- \ 4 -*^- track a.a.4 -*^- artist a.a.4 -*^- FLAC -*^- 1042", ), String::from( "Album_Artist ‘A’ -*^- -*^- \ - 2015 -*^- 04 -*^- 00 -*^- album_title a.b -*^- \ + 2015 -*^- 04 -*^- 00 -*^- False -*^- album_title a.b -*^- 2 -*^- \ 1 -*^- track a.b.1 -*^- artist a.b.1 -*^- FLAC -*^- 1004", ), String::from( "Album_Artist ‘A’ -*^- -*^- \ - 2015 -*^- 04 -*^- 00 -*^- album_title a.b -*^- \ + 2015 -*^- 04 -*^- 00 -*^- False -*^- album_title a.b -*^- 2 -*^- \ 2 -*^- track a.b.2 -*^- artist a.b.2 -*^- FLAC -*^- 1077", ), String::from( "Album_Artist ‘B’ -*^- -*^- \ - 2003 -*^- 06 -*^- 06 -*^- album_title b.a -*^- \ + 2003 -*^- 06 -*^- 06 -*^- False -*^- album_title b.a -*^- 3 -*^- \ 1 -*^- track b.a.1 -*^- artist b.a.1 -*^- MP3 -*^- 190", ), String::from( "Album_Artist ‘B’ -*^- -*^- \ - 2003 -*^- 06 -*^- 06 -*^- album_title b.a -*^- \ + 2003 -*^- 06 -*^- 06 -*^- False -*^- album_title b.a -*^- 3 -*^- \ 2 -*^- track b.a.2 -*^- artist b.a.2.1; artist b.a.2.2 -*^- MP3 -*^- 120", ), String::from( "Album_Artist ‘B’ -*^- -*^- \ - 2008 -*^- 00 -*^- 00 -*^- album_title b.b -*^- \ + 2008 -*^- 00 -*^- 00 -*^- False -*^- album_title b.b -*^- 4 -*^- \ 1 -*^- track b.b.1 -*^- artist b.b.1 -*^- FLAC -*^- 1077", ), String::from( "Album_Artist ‘B’ -*^- -*^- \ - 2008 -*^- 00 -*^- 00 -*^- album_title b.b -*^- \ + 2008 -*^- 00 -*^- 00 -*^- False -*^- album_title b.b -*^- 4 -*^- \ 2 -*^- track b.b.2 -*^- artist b.b.2.1; artist b.b.2.2 -*^- MP3 -*^- 320", ), String::from( "Album_Artist ‘B’ -*^- -*^- \ - 2009 -*^- 00 -*^- 00 -*^- album_title b.c -*^- \ + 2009 -*^- 00 -*^- 00 -*^- False -*^- album_title b.c -*^- 5 -*^- \ 1 -*^- track b.c.1 -*^- artist b.c.1 -*^- MP3 -*^- 190", ), String::from( "Album_Artist ‘B’ -*^- -*^- \ - 2009 -*^- 00 -*^- 00 -*^- album_title b.c -*^- \ + 2009 -*^- 00 -*^- 00 -*^- False -*^- album_title b.c -*^- 5 -*^- \ 2 -*^- track b.c.2 -*^- artist b.c.2.1; artist b.c.2.2 -*^- MP3 -*^- 120", ), String::from( "Album_Artist ‘B’ -*^- -*^- \ - 2015 -*^- 00 -*^- 00 -*^- album_title b.d -*^- \ + 2015 -*^- 00 -*^- 00 -*^- False -*^- album_title b.d -*^- 6 -*^- \ 1 -*^- track b.d.1 -*^- artist b.d.1 -*^- MP3 -*^- 190", ), String::from( "Album_Artist ‘B’ -*^- -*^- \ - 2015 -*^- 00 -*^- 00 -*^- album_title b.d -*^- \ + 2015 -*^- 00 -*^- 00 -*^- False -*^- album_title b.d -*^- 6 -*^- \ 2 -*^- track b.d.2 -*^- artist b.d.2.1; artist b.d.2.2 -*^- MP3 -*^- 120", ), String::from( "The Album_Artist ‘C’ -*^- Album_Artist ‘C’, The -*^- \ - 1985 -*^- 00 -*^- 00 -*^- album_title c.a -*^- \ + 1985 -*^- 00 -*^- 00 -*^- False -*^- album_title c.a -*^- 7 -*^- \ 1 -*^- track c.a.1 -*^- artist c.a.1 -*^- MP3 -*^- 320", ), String::from( "The Album_Artist ‘C’ -*^- Album_Artist ‘C’, The -*^- \ - 1985 -*^- 00 -*^- 00 -*^- album_title c.a -*^- \ + 1985 -*^- 00 -*^- 00 -*^- False -*^- album_title c.a -*^- 7 -*^- \ 2 -*^- track c.a.2 -*^- artist c.a.2.1; artist c.a.2.2 -*^- MP3 -*^- 120", ), String::from( "The Album_Artist ‘C’ -*^- Album_Artist ‘C’, The -*^- \ - 2018 -*^- 00 -*^- 00 -*^- album_title c.b -*^- \ + 2018 -*^- 00 -*^- 00 -*^- False -*^- album_title c.b -*^- 8 -*^- \ 1 -*^- track c.b.1 -*^- artist c.b.1 -*^- FLAC -*^- 1041", ), String::from( "The Album_Artist ‘C’ -*^- Album_Artist ‘C’, The -*^- \ - 2018 -*^- 00 -*^- 00 -*^- album_title c.b -*^- \ + 2018 -*^- 00 -*^- 00 -*^- False -*^- album_title c.b -*^- 8 -*^- \ 2 -*^- track c.b.2 -*^- artist c.b.2.1; artist c.b.2.2 -*^- FLAC -*^- 756", ), String::from( "Album_Artist ‘D’ -*^- -*^- \ - 1995 -*^- 00 -*^- 00 -*^- album_title d.a -*^- \ + 1995 -*^- 00 -*^- 00 -*^- False -*^- album_title d.a -*^- 9 -*^- \ 1 -*^- track d.a.1 -*^- artist d.a.1 -*^- MP3 -*^- 120", ), String::from( "Album_Artist ‘D’ -*^- -*^- \ - 1995 -*^- 00 -*^- 00 -*^- album_title d.a -*^- \ + 1995 -*^- 00 -*^- 00 -*^- False -*^- album_title d.a -*^- 9 -*^- \ 2 -*^- track d.a.2 -*^- artist d.a.2.1; artist d.a.2.2 -*^- MP3 -*^- 120", ), String::from( "Album_Artist ‘D’ -*^- -*^- \ - 2028 -*^- 00 -*^- 00 -*^- album_title d.b -*^- \ + 2028 -*^- 00 -*^- 00 -*^- False -*^- album_title d.b -*^- 10 -*^- \ 1 -*^- track d.b.1 -*^- artist d.b.1 -*^- FLAC -*^- 841", ), String::from( "Album_Artist ‘D’ -*^- -*^- \ - 2028 -*^- 00 -*^- 00 -*^- album_title d.b -*^- \ + 2028 -*^- 00 -*^- 00 -*^- False -*^- album_title d.b -*^- 10 -*^- \ 2 -*^- track d.b.2 -*^- artist d.b.2.1; artist d.b.2.2 -*^- FLAC -*^- 756", ), ] diff --git a/tests/library/testmod.rs b/tests/library/testmod.rs index ba62508..295268d 100644 --- a/tests/library/testmod.rs +++ b/tests/library/testmod.rs @@ -1,6 +1,6 @@ use once_cell::sync::Lazy; -use musichoard::{collection::track::TrackFormat, interface::library::Item}; +use musichoard::{collection::{album::AlbumLibId, track::TrackFormat}, interface::library::Item}; pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { vec![ @@ -11,6 +11,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), + album_lib_id: AlbumLibId::Some(7), track_number: 1, track_title: String::from("Az’"), track_artist: vec![String::from("Аркона")], @@ -24,6 +25,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), + album_lib_id: AlbumLibId::Some(7), track_number: 2, track_title: String::from("Arkaim"), track_artist: vec![String::from("Аркона")], @@ -37,6 +39,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), + album_lib_id: AlbumLibId::Some(7), track_number: 3, track_title: String::from("Bol’no mne"), track_artist: vec![String::from("Аркона")], @@ -50,6 +53,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), + album_lib_id: AlbumLibId::Some(7), track_number: 4, track_title: String::from("Leshiy"), track_artist: vec![String::from("Аркона")], @@ -63,6 +67,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), + album_lib_id: AlbumLibId::Some(7), track_number: 5, track_title: String::from("Zakliatie"), track_artist: vec![String::from("Аркона")], @@ -76,6 +81,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), + album_lib_id: AlbumLibId::Some(7), track_number: 6, track_title: String::from("Predok"), track_artist: vec![String::from("Аркона")], @@ -89,6 +95,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), + album_lib_id: AlbumLibId::Some(7), track_number: 7, track_title: String::from("Nikogda"), track_artist: vec![String::from("Аркона")], @@ -102,6 +109,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), + album_lib_id: AlbumLibId::Some(7), track_number: 8, track_title: String::from("Tam za tumanami"), track_artist: vec![String::from("Аркона")], @@ -115,6 +123,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), + album_lib_id: AlbumLibId::Some(7), track_number: 9, track_title: String::from("Potomok"), track_artist: vec![String::from("Аркона")], @@ -128,6 +137,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), + album_lib_id: AlbumLibId::Some(7), track_number: 10, track_title: String::from("Slovo"), track_artist: vec![String::from("Аркона")], @@ -141,6 +151,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), + album_lib_id: AlbumLibId::Some(7), track_number: 11, track_title: String::from("Odna"), track_artist: vec![String::from("Аркона")], @@ -154,6 +165,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), + album_lib_id: AlbumLibId::Some(7), track_number: 12, track_title: String::from("Vo moiom sadochke…"), track_artist: vec![String::from("Аркона")], @@ -167,6 +179,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), + album_lib_id: AlbumLibId::Some(7), track_number: 13, track_title: String::from("Stenka na stenku"), track_artist: vec![String::from("Аркона")], @@ -180,6 +193,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), + album_lib_id: AlbumLibId::Some(7), track_number: 14, track_title: String::from("Zimushka"), track_artist: vec![String::from("Аркона")], @@ -193,6 +207,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Vên [re‐recorded]"), + album_lib_id: AlbumLibId::Some(1), track_number: 1, track_title: String::from("Verja Urit an Bitus"), track_artist: vec![String::from("Eluveitie")], @@ -206,6 +221,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Vên [re‐recorded]"), + album_lib_id: AlbumLibId::Some(1), track_number: 2, track_title: String::from("Uis Elveti"), track_artist: vec![String::from("Eluveitie")], @@ -219,6 +235,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Vên [re‐recorded]"), + album_lib_id: AlbumLibId::Some(1), track_number: 3, track_title: String::from("Ôrô"), track_artist: vec![String::from("Eluveitie")], @@ -232,6 +249,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Vên [re‐recorded]"), + album_lib_id: AlbumLibId::Some(1), track_number: 4, track_title: String::from("Lament"), track_artist: vec![String::from("Eluveitie")], @@ -245,6 +263,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Vên [re‐recorded]"), + album_lib_id: AlbumLibId::Some(1), track_number: 5, track_title: String::from("Druid"), track_artist: vec![String::from("Eluveitie")], @@ -258,6 +277,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Vên [re‐recorded]"), + album_lib_id: AlbumLibId::Some(1), track_number: 6, track_title: String::from("Jêzaïg"), track_artist: vec![String::from("Eluveitie")], @@ -271,6 +291,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), + album_lib_id: AlbumLibId::Some(2), track_number: 1, track_title: String::from("Samon"), track_artist: vec![String::from("Eluveitie")], @@ -284,6 +305,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), + album_lib_id: AlbumLibId::Some(2), track_number: 2, track_title: String::from("Primordial Breath"), track_artist: vec![String::from("Eluveitie")], @@ -297,6 +319,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), + album_lib_id: AlbumLibId::Some(2), track_number: 3, track_title: String::from("Inis Mona"), track_artist: vec![String::from("Eluveitie")], @@ -310,6 +333,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), + album_lib_id: AlbumLibId::Some(2), track_number: 4, track_title: String::from("Gray Sublime Archon"), track_artist: vec![String::from("Eluveitie")], @@ -323,6 +347,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), + album_lib_id: AlbumLibId::Some(2), track_number: 5, track_title: String::from("Anagantios"), track_artist: vec![String::from("Eluveitie")], @@ -336,6 +361,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), + album_lib_id: AlbumLibId::Some(2), track_number: 6, track_title: String::from("Bloodstained Ground"), track_artist: vec![String::from("Eluveitie")], @@ -349,6 +375,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), + album_lib_id: AlbumLibId::Some(2), track_number: 7, track_title: String::from("The Somber Lay"), track_artist: vec![String::from("Eluveitie")], @@ -362,6 +389,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), + album_lib_id: AlbumLibId::Some(2), track_number: 8, track_title: String::from("Slanias Song"), track_artist: vec![String::from("Eluveitie")], @@ -375,6 +403,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), + album_lib_id: AlbumLibId::Some(2), track_number: 9, track_title: String::from("Giamonios"), track_artist: vec![String::from("Eluveitie")], @@ -388,6 +417,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), + album_lib_id: AlbumLibId::Some(2), track_number: 10, track_title: String::from("Tarvos"), track_artist: vec![String::from("Eluveitie")], @@ -401,6 +431,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), + album_lib_id: AlbumLibId::Some(2), track_number: 11, track_title: String::from("Calling the Rain"), track_artist: vec![String::from("Eluveitie")], @@ -414,6 +445,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), + album_lib_id: AlbumLibId::Some(2), track_number: 12, track_title: String::from("Elembivos"), track_artist: vec![String::from("Eluveitie")], @@ -427,6 +459,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), + album_lib_id: AlbumLibId::Some(3), track_number: 1, track_title: String::from("Intro = Chaos"), track_artist: vec![String::from("Frontside")], @@ -440,6 +473,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), + album_lib_id: AlbumLibId::Some(3), track_number: 2, track_title: String::from("Modlitwa"), track_artist: vec![String::from("Frontside")], @@ -453,6 +487,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), + album_lib_id: AlbumLibId::Some(3), track_number: 3, track_title: String::from("Długa droga z piekła"), track_artist: vec![String::from("Frontside")], @@ -466,6 +501,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), + album_lib_id: AlbumLibId::Some(3), track_number: 4, track_title: String::from("Synowie ognia"), track_artist: vec![String::from("Frontside")], @@ -479,6 +515,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), + album_lib_id: AlbumLibId::Some(3), track_number: 5, track_title: String::from("1902"), track_artist: vec![String::from("Frontside")], @@ -492,6 +529,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), + album_lib_id: AlbumLibId::Some(3), track_number: 6, track_title: String::from("Krew za krew"), track_artist: vec![String::from("Frontside")], @@ -505,6 +543,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), + album_lib_id: AlbumLibId::Some(3), track_number: 7, track_title: String::from("Kulminacja"), track_artist: vec![String::from("Frontside")], @@ -518,6 +557,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), + album_lib_id: AlbumLibId::Some(3), track_number: 8, track_title: String::from("Judasz"), track_artist: vec![String::from("Frontside")], @@ -531,6 +571,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), + album_lib_id: AlbumLibId::Some(3), track_number: 9, track_title: String::from("Więzy"), track_artist: vec![String::from("Frontside")], @@ -544,6 +585,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), + album_lib_id: AlbumLibId::Some(3), track_number: 10, track_title: String::from("Zagubione dusze"), track_artist: vec![String::from("Frontside")], @@ -557,6 +599,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), + album_lib_id: AlbumLibId::Some(3), track_number: 11, track_title: String::from("Linia życia"), track_artist: vec![String::from("Frontside")], @@ -570,6 +613,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Paper Plague"), + album_lib_id: AlbumLibId::Singleton, track_number: 0, track_title: String::from("Paper Plague"), track_artist: vec![String::from("Heaven’s Basement")], @@ -583,6 +627,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Unbreakable"), + album_lib_id: AlbumLibId::Some(4), track_number: 1, track_title: String::from("Unbreakable"), track_artist: vec![String::from("Heaven’s Basement")], @@ -596,6 +641,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Unbreakable"), + album_lib_id: AlbumLibId::Some(4), track_number: 2, track_title: String::from("Guilt Trips and Sins"), track_artist: vec![String::from("Heaven’s Basement")], @@ -609,6 +655,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Unbreakable"), + album_lib_id: AlbumLibId::Some(4), track_number: 3, track_title: String::from("The Long Goodbye"), track_artist: vec![String::from("Heaven’s Basement")], @@ -622,6 +669,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Unbreakable"), + album_lib_id: AlbumLibId::Some(4), track_number: 4, track_title: String::from("Close Encounters"), track_artist: vec![String::from("Heaven’s Basement")], @@ -635,6 +683,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Unbreakable"), + album_lib_id: AlbumLibId::Some(4), track_number: 5, track_title: String::from("Paranoia"), track_artist: vec![String::from("Heaven’s Basement")], @@ -648,6 +697,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Unbreakable"), + album_lib_id: AlbumLibId::Some(4), track_number: 6, track_title: String::from("Let Me Out of Here"), track_artist: vec![String::from("Heaven’s Basement")], @@ -661,6 +711,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Unbreakable"), + album_lib_id: AlbumLibId::Some(4), track_number: 7, track_title: String::from("Leeches"), track_artist: vec![String::from("Heaven’s Basement")], @@ -674,6 +725,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Ride the Lightning"), + album_lib_id: AlbumLibId::Some(5), track_number: 1, track_title: String::from("Fight Fire with Fire"), track_artist: vec![String::from("Metallica")], @@ -687,6 +739,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Ride the Lightning"), + album_lib_id: AlbumLibId::Some(5), track_number: 2, track_title: String::from("Ride the Lightning"), track_artist: vec![String::from("Metallica")], @@ -700,6 +753,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Ride the Lightning"), + album_lib_id: AlbumLibId::Some(5), track_number: 3, track_title: String::from("For Whom the Bell Tolls"), track_artist: vec![String::from("Metallica")], @@ -713,6 +767,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Ride the Lightning"), + album_lib_id: AlbumLibId::Some(5), track_number: 4, track_title: String::from("Fade to Black"), track_artist: vec![String::from("Metallica")], @@ -726,6 +781,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Ride the Lightning"), + album_lib_id: AlbumLibId::Some(5), track_number: 5, track_title: String::from("Trapped under Ice"), track_artist: vec![String::from("Metallica")], @@ -739,6 +795,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Ride the Lightning"), + album_lib_id: AlbumLibId::Some(5), track_number: 6, track_title: String::from("Escape"), track_artist: vec![String::from("Metallica")], @@ -752,6 +809,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Ride the Lightning"), + album_lib_id: AlbumLibId::Some(5), track_number: 7, track_title: String::from("Creeping Death"), track_artist: vec![String::from("Metallica")], @@ -765,6 +823,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Ride the Lightning"), + album_lib_id: AlbumLibId::Some(5), track_number: 8, track_title: String::from("The Call of Ktulu"), track_artist: vec![String::from("Metallica")], @@ -778,6 +837,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 1, track_title: String::from("The Ecstasy of Gold"), track_artist: vec![String::from("Metallica")], @@ -791,6 +851,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 2, track_title: String::from("The Call of Ktulu"), track_artist: vec![String::from("Metallica")], @@ -804,6 +865,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 3, track_title: String::from("Master of Puppets"), track_artist: vec![String::from("Metallica")], @@ -817,6 +879,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 4, track_title: String::from("Of Wolf and Man"), track_artist: vec![String::from("Metallica")], @@ -830,6 +893,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 5, track_title: String::from("The Thing That Should Not Be"), track_artist: vec![String::from("Metallica")], @@ -843,6 +907,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 6, track_title: String::from("Fuel"), track_artist: vec![String::from("Metallica")], @@ -856,6 +921,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 7, track_title: String::from("The Memory Remains"), track_artist: vec![String::from("Metallica")], @@ -869,6 +935,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 8, track_title: String::from("No Leaf Clover"), track_artist: vec![String::from("Metallica")], @@ -882,6 +949,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 9, track_title: String::from("Hero of the Day"), track_artist: vec![String::from("Metallica")], @@ -895,6 +963,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 10, track_title: String::from("Devil’s Dance"), track_artist: vec![String::from("Metallica")], @@ -908,6 +977,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 11, track_title: String::from("Bleeding Me"), track_artist: vec![String::from("Metallica")], @@ -921,6 +991,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 12, track_title: String::from("Nothing Else Matters"), track_artist: vec![String::from("Metallica")], @@ -934,6 +1005,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 13, track_title: String::from("Until It Sleeps"), track_artist: vec![String::from("Metallica")], @@ -947,6 +1019,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 14, track_title: String::from("For Whom the Bell Tolls"), track_artist: vec![String::from("Metallica")], @@ -960,6 +1033,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 15, track_title: String::from("−Human"), track_artist: vec![String::from("Metallica")], @@ -973,6 +1047,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 16, track_title: String::from("Wherever I May Roam"), track_artist: vec![String::from("Metallica")], @@ -986,6 +1061,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 17, track_title: String::from("Outlaw Torn"), track_artist: vec![String::from("Metallica")], @@ -999,6 +1075,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 18, track_title: String::from("Sad but True"), track_artist: vec![String::from("Metallica")], @@ -1012,6 +1089,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 19, track_title: String::from("One"), track_artist: vec![String::from("Metallica")], @@ -1025,6 +1103,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 20, track_title: String::from("Enter Sandman"), track_artist: vec![String::from("Metallica")], @@ -1038,6 +1117,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), + album_lib_id: AlbumLibId::Some(6), track_number: 21, track_title: String::from("Battery"), track_artist: vec![String::from("Metallica")], -- 2.47.1 From 5f992b4b2ceb622732876ef4476920c56e5499e7 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 2 Jan 2025 09:19:33 +0100 Subject: [PATCH 02/16] Merge and write library id --- src/core/collection/album.rs | 36 +++++++-------- src/core/collection/artist.rs | 52 ++++++++++++++++++++-- src/core/collection/merge.rs | 4 +- src/core/musichoard/library.rs | 1 + src/core/testmod.rs | 2 +- src/external/database/json/testmod.rs | 22 ++++----- src/external/database/serde/common.rs | 10 ++++- src/external/database/serde/deserialize.rs | 7 ++- src/external/database/serde/serialize.rs | 22 +++++++-- src/testmod/full.rs | 10 +++++ src/testmod/library.rs | 10 +++++ src/tui/testmod.rs | 2 +- src/tui/ui/display.rs | 10 ++++- src/tui/ui/info_state.rs | 4 ++ tests/testlib.rs | 13 +++++- 15 files changed, 159 insertions(+), 46 deletions(-) diff --git a/src/core/collection/album.rs b/src/core/collection/album.rs index 7919d6a..a8b19c0 100644 --- a/src/core/collection/album.rs +++ b/src/core/collection/album.rs @@ -4,7 +4,7 @@ use std::{ }; use crate::core::collection::{ - merge::{Merge, MergeSorted, WithId}, + merge::{Merge, MergeSorted}, musicbrainz::{MbAlbumRef, MbRefOption}, track::{Track, TrackFormat}, }; @@ -33,28 +33,27 @@ pub struct AlbumInfo { pub secondary_types: Vec, } -impl WithId for Album { - type Id = AlbumId; - - fn id(&self) -> &Self::Id { - &self.meta.id - } -} - /// The album identifier. #[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)] pub struct AlbumId { pub title: String, + pub lib_id: AlbumLibId, } /// Unique library identifier. -#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)] pub enum AlbumLibId { Some(u32), Singleton, None, } +impl AlbumLibId { + pub fn is_none(&self) -> bool { + matches!(self, AlbumLibId::None) + } +} + // There are crates for handling dates, but we don't need much complexity beyond year-month-day. /// The album's release date. #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] @@ -260,7 +259,12 @@ impl Ord for AlbumMeta { impl Merge for AlbumMeta { fn merge_in_place(&mut self, other: Self) { - assert_eq!(self.id, other.id); + if !self.id.lib_id.is_none() && !other.id.lib_id.is_none() { + assert_eq!(self.id, other.id); + } else { + assert_eq!(self.id.title, other.id.title); + } + self.seq = std::cmp::max(self.seq, other.seq); self.info.merge_in_place(other.info); @@ -291,7 +295,7 @@ impl AsRef for AlbumId { impl AlbumId { pub fn new>(name: S) -> AlbumId { - AlbumId { title: name.into() } + AlbumId { title: name.into(), lib_id: AlbumLibId::None } } } @@ -323,15 +327,11 @@ mod tests { fn same_date_seq_cmp() { let date: AlbumDate = (2024, 3, 2).into(); - let album_id_1 = AlbumId { - title: String::from("album z"), - }; + let album_id_1 = AlbumId::new("album z"); let mut album_1 = Album::new(album_id_1).with_date(date.clone()); album_1.meta.set_seq(AlbumSeq(1)); - let album_id_2 = AlbumId { - title: String::from("album a"), - }; + let album_id_2 = AlbumId::new("album a"); let mut album_2 = Album::new(album_id_2).with_date(date.clone()); album_2.meta.set_seq(AlbumSeq(2)); diff --git a/src/core/collection/artist.rs b/src/core/collection/artist.rs index 730ef87..239089c 100644 --- a/src/core/collection/artist.rs +++ b/src/core/collection/artist.rs @@ -6,10 +6,12 @@ use std::{ use crate::core::collection::{ album::Album, - merge::{Merge, MergeCollections, WithId}, + merge::{Merge, MergeId}, musicbrainz::{MbArtistRef, MbRefOption}, }; +use super::album::AlbumLibId; + /// An artist. #[derive(Clone, Debug, PartialEq, Eq)] pub struct Artist { @@ -32,7 +34,7 @@ pub struct ArtistInfo { pub properties: HashMap>, } -impl WithId for Artist { +impl MergeId for Artist { type Id = ArtistId; fn id(&self) -> &Self::Id { @@ -71,8 +73,50 @@ impl Ord for Artist { impl Merge for Artist { fn merge_in_place(&mut self, other: Self) { self.meta.merge_in_place(other.meta); - let albums = mem::take(&mut self.albums); - self.albums = MergeCollections::merge_iter(albums, other.albums); + + let mut primary_albums = mem::take(&mut self.albums); + let mut secondary_albums = other.albums; + + let mut secondary_without_id = HashMap::>::new(); + for mut secondary_album in secondary_albums.drain(..) { + match secondary_album.meta.id.lib_id { + lib_id @ AlbumLibId::Some(_) | lib_id @ AlbumLibId::Singleton => { + match primary_albums + .iter_mut() + .find(|album| album.meta.id.lib_id == lib_id) + { + Some(ref mut primary_album) => { + primary_album.merge_in_place(secondary_album) + } + None => { + secondary_album.meta.id.lib_id = AlbumLibId::None; + primary_albums.push(secondary_album); + } + } + } + AlbumLibId::None => secondary_without_id + .entry(secondary_album.meta.id.title.clone()) + .or_default() + .push(secondary_album), + } + } + + for (title, mut secondary_albums) in secondary_without_id.drain() { + match primary_albums + .iter_mut() + .find(|album| album.meta.id.title == title) + { + Some(ref mut primary_album) => { + // We do not support merging multiple DB albums with same title yet. + assert_eq!(secondary_albums.len(), 1); + primary_album.merge_in_place(secondary_albums.pop().unwrap()) + } + None => primary_albums.append(&mut secondary_albums), + } + } + + primary_albums.sort_unstable(); + self.albums = primary_albums; } } diff --git a/src/core/collection/merge.rs b/src/core/collection/merge.rs index 2173801..704e8e6 100644 --- a/src/core/collection/merge.rs +++ b/src/core/collection/merge.rs @@ -80,7 +80,7 @@ where } } -pub trait WithId { +pub trait MergeId { type Id; fn id(&self) -> &Self::Id; @@ -95,7 +95,7 @@ pub struct MergeCollections { impl MergeCollections where ID: Eq + Hash + Clone, - T: WithId + Merge + Ord, + T: MergeId + Merge + Ord, IT: IntoIterator, { pub fn merge_iter(primary: IT, secondary: IT) -> Vec { diff --git a/src/core/musichoard/library.rs b/src/core/musichoard/library.rs index 5272b6d..b14c0ce 100644 --- a/src/core/musichoard/library.rs +++ b/src/core/musichoard/library.rs @@ -56,6 +56,7 @@ impl MusicHoard { let album_id = AlbumId { title: item.album_title, + lib_id: item.album_lib_id, }; let album_date = AlbumDate { diff --git a/src/core/testmod.rs b/src/core/testmod.rs index 32dab21..2ef6236 100644 --- a/src/core/testmod.rs +++ b/src/core/testmod.rs @@ -2,7 +2,7 @@ use once_cell::sync::Lazy; use std::collections::HashMap; use crate::core::collection::{ - album::{Album, AlbumId, AlbumInfo, AlbumMeta, AlbumPrimaryType, AlbumSeq}, + album::{Album, AlbumId, AlbumInfo, AlbumLibId, AlbumMeta, AlbumPrimaryType, AlbumSeq}, artist::{Artist, ArtistId, ArtistInfo, ArtistMeta}, musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption}, track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality}, diff --git a/src/external/database/json/testmod.rs b/src/external/database/json/testmod.rs index d7b1255..31dae78 100644 --- a/src/external/database/json/testmod.rs +++ b/src/external/database/json/testmod.rs @@ -1,5 +1,5 @@ pub static DATABASE_JSON: &str = "{\ - \"V20240924\":\ + \"V20250101\":\ [\ {\ \"name\":\"Album_Artist ‘A’\",\ @@ -11,12 +11,12 @@ pub static DATABASE_JSON: &str = "{\ },\ \"albums\":[\ {\ - \"title\":\"album_title a.a\",\"seq\":1,\ + \"title\":\"album_title a.a\",\"lib_id\":{\"Some\":1},\"seq\":1,\ \"musicbrainz\":{\"Some\":\"00000000-0000-0000-0000-000000000000\"},\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title a.b\",\"seq\":1,\"musicbrainz\":\"None\",\ + \"title\":\"album_title a.b\",\"lib_id\":{\"Some\":2},\"seq\":1,\"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ }\ ]\ @@ -35,21 +35,21 @@ pub static DATABASE_JSON: &str = "{\ },\ \"albums\":[\ {\ - \"title\":\"album_title b.a\",\"seq\":1,\"musicbrainz\":\"None\",\ + \"title\":\"album_title b.a\",\"lib_id\":{\"Some\":3},\"seq\":1,\"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title b.b\",\"seq\":3,\ + \"title\":\"album_title b.b\",\"lib_id\":{\"Some\":4},\"seq\":3,\ \"musicbrainz\":{\"Some\":\"11111111-1111-1111-1111-111111111111\"},\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title b.c\",\"seq\":2,\ + \"title\":\"album_title b.c\",\"lib_id\":{\"Some\":5},\"seq\":2,\ \"musicbrainz\":{\"Some\":\"11111111-1111-1111-1111-111111111112\"},\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title b.d\",\"seq\":4,\"musicbrainz\":\"None\",\ + \"title\":\"album_title b.d\",\"lib_id\":{\"Some\":6},\"seq\":4,\"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ }\ ]\ @@ -61,11 +61,11 @@ pub static DATABASE_JSON: &str = "{\ \"properties\":{},\ \"albums\":[\ {\ - \"title\":\"album_title c.a\",\"seq\":0,\"musicbrainz\":\"None\",\ + \"title\":\"album_title c.a\",\"lib_id\":{\"Some\":7},\"seq\":0,\"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title c.b\",\"seq\":0,\"musicbrainz\":\"None\",\ + \"title\":\"album_title c.b\",\"lib_id\":{\"Some\":8},\"seq\":0,\"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ }\ ]\ @@ -77,11 +77,11 @@ pub static DATABASE_JSON: &str = "{\ \"properties\":{},\ \"albums\":[\ {\ - \"title\":\"album_title d.a\",\"seq\":0,\"musicbrainz\":\"None\",\ + \"title\":\"album_title d.a\",\"lib_id\":{\"Some\":9},\"seq\":0,\"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title d.b\",\"seq\":0,\"musicbrainz\":\"None\",\ + \"title\":\"album_title d.b\",\"lib_id\":{\"Some\":10},\"seq\":0,\"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ }\ ]\ diff --git a/src/external/database/serde/common.rs b/src/external/database/serde/common.rs index fb10599..fdf9827 100644 --- a/src/external/database/serde/common.rs +++ b/src/external/database/serde/common.rs @@ -2,9 +2,17 @@ use serde::{Deserialize, Serialize}; use crate::{ collection::musicbrainz::MbRefOption, - core::collection::album::{AlbumPrimaryType, AlbumSecondaryType}, + core::collection::album::{AlbumLibId, AlbumPrimaryType, AlbumSecondaryType}, }; +#[derive(Debug, Deserialize, Serialize)] +#[serde(remote = "AlbumLibId")] +pub enum AlbumLibIdDef { + Some(u32), + Singleton, + None, +} + #[derive(Debug, Deserialize, Serialize)] #[serde(remote = "MbRefOption")] pub enum MbRefOptionDef { diff --git a/src/external/database/serde/deserialize.rs b/src/external/database/serde/deserialize.rs index e0ad951..b46968c 100644 --- a/src/external/database/serde/deserialize.rs +++ b/src/external/database/serde/deserialize.rs @@ -4,7 +4,7 @@ use serde::{de::Visitor, Deserialize, Deserializer}; use crate::{ collection::{ - album::{AlbumInfo, AlbumMeta}, + album::{AlbumInfo, AlbumLibId, AlbumMeta}, artist::{ArtistInfo, ArtistMeta}, musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption, Mbid}, }, @@ -129,7 +129,10 @@ impl From for Album { fn from(album: DeserializeAlbum) -> Self { Album { meta: AlbumMeta { - id: AlbumId { title: album.title }, + id: AlbumId { + title: album.title, + lib_id: AlbumLibId::None, + }, date: AlbumDate::default(), seq: AlbumSeq(album.seq), info: AlbumInfo { diff --git a/src/external/database/serde/serialize.rs b/src/external/database/serde/serialize.rs index bc50ce3..4ffd96b 100644 --- a/src/external/database/serde/serialize.rs +++ b/src/external/database/serde/serialize.rs @@ -3,21 +3,24 @@ use std::collections::BTreeMap; use serde::Serialize; use crate::{ - collection::musicbrainz::{MbRefOption, Mbid}, + collection::{ + album::AlbumLibId, + musicbrainz::{MbRefOption, Mbid}, + }, core::collection::{album::Album, artist::Artist, musicbrainz::IMusicBrainzRef, Collection}, external::database::serde::common::{ - MbRefOptionDef, SerdeAlbumPrimaryType, SerdeAlbumSecondaryType, + AlbumLibIdDef, MbRefOptionDef, SerdeAlbumPrimaryType, SerdeAlbumSecondaryType, }, }; #[derive(Debug, Serialize)] pub enum SerializeDatabase<'a> { - V20240924(Vec>), + V20250101(Vec>), } impl<'a> From<&'a Collection> for SerializeDatabase<'a> { fn from(collection: &'a Collection) -> Self { - SerializeDatabase::V20240924(collection.iter().map(Into::into).collect()) + SerializeDatabase::V20250101(collection.iter().map(Into::into).collect()) } } @@ -33,12 +36,22 @@ pub struct SerializeArtist<'a> { #[derive(Debug, Serialize)] pub struct SerializeAlbum<'a> { title: &'a str, + lib_id: SerializeAlbumLibId, seq: u8, musicbrainz: SerializeMbRefOption<'a>, primary_type: Option, secondary_types: Vec, } +#[derive(Debug, Serialize)] +pub struct SerializeAlbumLibId(#[serde(with = "AlbumLibIdDef")] AlbumLibId); + +impl From for SerializeAlbumLibId { + fn from(value: AlbumLibId) -> Self { + SerializeAlbumLibId(value) + } +} + #[derive(Debug, Serialize)] pub struct SerializeMbRefOption<'a>( #[serde(with = "MbRefOptionDef")] MbRefOption>, @@ -90,6 +103,7 @@ impl<'a> From<&'a Album> for SerializeAlbum<'a> { fn from(album: &'a Album) -> Self { SerializeAlbum { title: &album.meta.id.title, + lib_id: album.meta.id.lib_id.into(), seq: album.meta.seq.0, musicbrainz: (&album.meta.info.musicbrainz).into(), primary_type: album.meta.info.primary_type.map(Into::into), diff --git a/src/testmod/full.rs b/src/testmod/full.rs index ea0f159..96805ad 100644 --- a/src/testmod/full.rs +++ b/src/testmod/full.rs @@ -28,6 +28,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title a.a".to_string(), + lib_id: AlbumLibId::Some(1), }, date: 1998.into(), seq: AlbumSeq(1), @@ -93,6 +94,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title a.b".to_string(), + lib_id: AlbumLibId::Some(2), }, date: (2015, 4).into(), seq: AlbumSeq(1), @@ -160,6 +162,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title b.a".to_string(), + lib_id: AlbumLibId::Some(3), }, date: (2003, 6, 6).into(), seq: AlbumSeq(1), @@ -201,6 +204,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title b.b".to_string(), + lib_id: AlbumLibId::Some(4), }, date: 2008.into(), seq: AlbumSeq(3), @@ -244,6 +248,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title b.c".to_string(), + lib_id: AlbumLibId::Some(5), }, date: 2009.into(), seq: AlbumSeq(2), @@ -287,6 +292,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title b.d".to_string(), + lib_id: AlbumLibId::Some(6), }, date: 2015.into(), seq: AlbumSeq(4), @@ -342,6 +348,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title c.a".to_string(), + lib_id: AlbumLibId::Some(7), }, date: 1985.into(), seq: AlbumSeq(0), @@ -383,6 +390,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title c.b".to_string(), + lib_id: AlbumLibId::Some(8), }, date: 2018.into(), seq: AlbumSeq(0), @@ -438,6 +446,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title d.a".to_string(), + lib_id: AlbumLibId::Some(9), }, date: 1995.into(), seq: AlbumSeq(0), @@ -479,6 +488,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title d.b".to_string(), + lib_id: AlbumLibId::Some(10), }, date: 2028.into(), seq: AlbumSeq(0), diff --git a/src/testmod/library.rs b/src/testmod/library.rs index 1024f23..5e7a354 100644 --- a/src/testmod/library.rs +++ b/src/testmod/library.rs @@ -18,6 +18,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title a.a".to_string(), + lib_id: AlbumLibId::Some(1), }, date: 1998.into(), seq: AlbumSeq(0), @@ -77,6 +78,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title a.b".to_string(), + lib_id: AlbumLibId::Some(2), }, date: (2015, 4).into(), seq: AlbumSeq(0), @@ -125,6 +127,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title b.a".to_string(), + lib_id: AlbumLibId::Some(3), }, date: (2003, 6, 6).into(), seq: AlbumSeq(0), @@ -162,6 +165,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title b.b".to_string(), + lib_id: AlbumLibId::Some(4), }, date: 2008.into(), seq: AlbumSeq(0), @@ -199,6 +203,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title b.c".to_string(), + lib_id: AlbumLibId::Some(5), }, date: 2009.into(), seq: AlbumSeq(0), @@ -236,6 +241,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title b.d".to_string(), + lib_id: AlbumLibId::Some(6), }, date: 2015.into(), seq: AlbumSeq(0), @@ -287,6 +293,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title c.a".to_string(), + lib_id: AlbumLibId::Some(7), }, date: 1985.into(), seq: AlbumSeq(0), @@ -324,6 +331,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title c.b".to_string(), + lib_id: AlbumLibId::Some(8), }, date: 2018.into(), seq: AlbumSeq(0), @@ -375,6 +383,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title d.a".to_string(), + lib_id: AlbumLibId::Some(9), }, date: 1995.into(), seq: AlbumSeq(0), @@ -412,6 +421,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title d.b".to_string(), + lib_id: AlbumLibId::Some(10), }, date: 2028.into(), seq: AlbumSeq(0), diff --git a/src/tui/testmod.rs b/src/tui/testmod.rs index 5b7ddc2..6624bac 100644 --- a/src/tui/testmod.rs +++ b/src/tui/testmod.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use musichoard::collection::{ - album::{Album, AlbumId, AlbumInfo, AlbumMeta, AlbumPrimaryType, AlbumSeq}, + album::{Album, AlbumId, AlbumInfo, AlbumLibId, AlbumMeta, AlbumPrimaryType, AlbumSeq}, artist::{Artist, ArtistId, ArtistInfo, ArtistMeta}, musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption}, track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality}, diff --git a/src/tui/ui/display.rs b/src/tui/ui/display.rs index 0210688..7a1ea54 100644 --- a/src/tui/ui/display.rs +++ b/src/tui/ui/display.rs @@ -1,6 +1,6 @@ use musichoard::collection::{ album::{ - AlbumDate, AlbumId, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, AlbumSeq, AlbumStatus, + AlbumDate, AlbumId, AlbumLibId, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, AlbumSeq, AlbumStatus }, artist::ArtistMeta, musicbrainz::{IMusicBrainzRef, MbRefOption}, @@ -20,6 +20,14 @@ impl UiDisplay { } } + pub fn display_album_lib_id(lib_id: &AlbumLibId) -> String { + match lib_id { + AlbumLibId::Some(val) => val.to_string(), + AlbumLibId::Singleton => "Singleton".to_string(), + AlbumLibId::None => "None".to_string(), + } + } + pub fn display_album_date(date: &AlbumDate) -> String { match date.year { Some(year) => match date.month { diff --git a/src/tui/ui/info_state.rs b/src/tui/ui/info_state.rs index 684b914..8a73877 100644 --- a/src/tui/ui/info_state.rs +++ b/src/tui/ui/info_state.rs @@ -101,8 +101,12 @@ impl<'a> AlbumOverlay<'a> { let properties = Paragraph::new(format!( "Album: {}\n\n{item_indent}\ + Library ID: {}\n{item_indent}\ MusicBrainz: {}", album.map(|a| a.meta.id.title.as_str()).unwrap_or(""), + album + .map(|a| UiDisplay::display_album_lib_id(&a.meta.id.lib_id)) + .unwrap_or_default(), album .map(|a| UiDisplay::display_mb_ref_option_as_url(&a.meta.info.musicbrainz)) .unwrap_or_default(), diff --git a/tests/testlib.rs b/tests/testlib.rs index e0cd704..170c53f 100644 --- a/tests/testlib.rs +++ b/tests/testlib.rs @@ -2,7 +2,10 @@ use once_cell::sync::Lazy; use std::collections::HashMap; use musichoard::collection::{ - album::{Album, AlbumId, AlbumInfo, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, AlbumSeq}, + album::{ + Album, AlbumId, AlbumInfo, AlbumLibId, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, + AlbumSeq, + }, artist::{Artist, ArtistId, ArtistInfo, ArtistMeta}, musicbrainz::{MbArtistRef, MbRefOption}, track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality}, @@ -38,6 +41,7 @@ pub static COLLECTION: Lazy> = Lazy::new(|| -> Collection { meta: AlbumMeta { id: AlbumId { title: String::from("Slovo"), + lib_id: AlbumLibId::Some(7), }, date: 2011.into(), seq: AlbumSeq(0), @@ -230,6 +234,7 @@ pub static COLLECTION: Lazy> = Lazy::new(|| -> Collection { meta: AlbumMeta { id: AlbumId { title: String::from("Vên [re‐recorded]"), + lib_id: AlbumLibId::Some(1), }, date: 2004.into(), seq: AlbumSeq(0), @@ -312,6 +317,7 @@ pub static COLLECTION: Lazy> = Lazy::new(|| -> Collection { meta: AlbumMeta { id: AlbumId { title: String::from("Slania"), + lib_id: AlbumLibId::Some(2), }, date: 2008.into(), seq: AlbumSeq(0), @@ -482,6 +488,7 @@ pub static COLLECTION: Lazy> = Lazy::new(|| -> Collection { meta: AlbumMeta { id: AlbumId { title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), + lib_id: AlbumLibId::Some(3), }, date: 2001.into(), seq: AlbumSeq(0), @@ -640,6 +647,7 @@ pub static COLLECTION: Lazy> = Lazy::new(|| -> Collection { meta: AlbumMeta { id: AlbumId { title: String::from("Paper Plague"), + lib_id: AlbumLibId::Singleton, }, date: 2011.into(), seq: AlbumSeq(0), @@ -662,6 +670,7 @@ pub static COLLECTION: Lazy> = Lazy::new(|| -> Collection { meta: AlbumMeta { id: AlbumId { title: String::from("Unbreakable"), + lib_id: AlbumLibId::Some(4), }, date: 2011.into(), seq: AlbumSeq(0), @@ -777,6 +786,7 @@ pub static COLLECTION: Lazy> = Lazy::new(|| -> Collection { meta: AlbumMeta { id: AlbumId { title: String::from("Ride the Lightning"), + lib_id: AlbumLibId::Some(5), }, date: 1984.into(), seq: AlbumSeq(0), @@ -881,6 +891,7 @@ pub static COLLECTION: Lazy> = Lazy::new(|| -> Collection { meta: AlbumMeta { id: AlbumId { title: String::from("S&M"), + lib_id: AlbumLibId::Some(6), }, date: 1999.into(), seq: AlbumSeq(0), -- 2.47.1 From a705903b9393e4fa8b801e2f343a8478e4516922 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 2 Jan 2025 11:20:18 +0100 Subject: [PATCH 03/16] Complete unit tests for artist --- src/core/collection/artist.rs | 125 +++++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 40 deletions(-) diff --git a/src/core/collection/artist.rs b/src/core/collection/artist.rs index 239089c..1c0e332 100644 --- a/src/core/collection/artist.rs +++ b/src/core/collection/artist.rs @@ -56,6 +56,64 @@ impl Artist { albums: vec![], } } + + fn merge_album_with_lib_id( + primary_albums: &mut Vec, + mut secondary_album: Album, + ) -> Option { + if let lib_id @ AlbumLibId::Some(_) | lib_id @ AlbumLibId::Singleton = + secondary_album.meta.id.lib_id + { + if let Some(ref mut primary_album) = primary_albums + .iter_mut() + .find(|album| album.meta.id.lib_id == lib_id) + { + primary_album.merge_in_place(secondary_album); + return None; + } + + secondary_album.meta.id.lib_id = AlbumLibId::None; + } + + Some(secondary_album) + } + + fn merge_albums_with_lib_id( + primary_albums: &mut Vec, + mut secondary_albums: Vec, + ) -> HashMap> { + let mut secondary_without_id = HashMap::>::new(); + for secondary_album in secondary_albums.drain(..) { + if let Some(secondary_album) = + Artist::merge_album_with_lib_id(primary_albums, secondary_album) + { + secondary_without_id + .entry(secondary_album.meta.id.title.clone()) + .or_default() + .push(secondary_album); + } + } + secondary_without_id + } + + fn merge_albums_with_title( + primary_albums: &mut Vec, + mut secondary_without_id: HashMap>, + ) { + for (title, mut secondary_albums) in secondary_without_id.drain() { + match primary_albums + .iter_mut() + .find(|album| album.meta.id.title == title) + { + Some(ref mut primary_album) => { + // We do not support merging multiple DB albums with same title yet. + assert_eq!(secondary_albums.len(), 1); + primary_album.merge_in_place(secondary_albums.pop().unwrap()) + } + None => primary_albums.append(&mut secondary_albums), + } + } + } } impl PartialOrd for Artist { @@ -75,45 +133,11 @@ impl Merge for Artist { self.meta.merge_in_place(other.meta); let mut primary_albums = mem::take(&mut self.albums); - let mut secondary_albums = other.albums; + let secondary_albums = other.albums; - let mut secondary_without_id = HashMap::>::new(); - for mut secondary_album in secondary_albums.drain(..) { - match secondary_album.meta.id.lib_id { - lib_id @ AlbumLibId::Some(_) | lib_id @ AlbumLibId::Singleton => { - match primary_albums - .iter_mut() - .find(|album| album.meta.id.lib_id == lib_id) - { - Some(ref mut primary_album) => { - primary_album.merge_in_place(secondary_album) - } - None => { - secondary_album.meta.id.lib_id = AlbumLibId::None; - primary_albums.push(secondary_album); - } - } - } - AlbumLibId::None => secondary_without_id - .entry(secondary_album.meta.id.title.clone()) - .or_default() - .push(secondary_album), - } - } - - for (title, mut secondary_albums) in secondary_without_id.drain() { - match primary_albums - .iter_mut() - .find(|album| album.meta.id.title == title) - { - Some(ref mut primary_album) => { - // We do not support merging multiple DB albums with same title yet. - assert_eq!(secondary_albums.len(), 1); - primary_album.merge_in_place(secondary_albums.pop().unwrap()) - } - None => primary_albums.append(&mut secondary_albums), - } - } + let secondary_without_id = + Artist::merge_albums_with_lib_id(&mut primary_albums, secondary_albums); + Artist::merge_albums_with_title(&mut primary_albums, secondary_without_id); primary_albums.sort_unstable(); self.albums = primary_albums; @@ -454,6 +478,12 @@ mod tests { assert!(info.properties.is_empty()); } + fn reset_lib_id(albums: &mut [Album]) { + for album in albums.iter_mut() { + album.meta.id.lib_id = AlbumLibId::None; + } + } + #[test] fn merge_artist_no_overlap() { let left = FULL_COLLECTION[0].to_owned(); @@ -468,13 +498,25 @@ mod tests { .info .properties .merge(right.clone().meta.info.properties); - expected.albums.append(&mut right.albums.clone()); + + // If an album in the secondary (right) collection has a lib id but there is no match in the + // primary (left) collection then it is removed. + let mut right_albums_without_lib_id = right.albums.clone(); + reset_lib_id(&mut right_albums_without_lib_id); + expected.albums.extend(right_albums_without_lib_id); expected.albums.sort_unstable(); let merged = left.clone().merge(right.clone()); assert_eq!(expected, merged); - // Non-overlapping merge should be commutative. + // Non-overlapping merge should be commutative. Except for lib id which will be erased from + // the albums in the secondary collection. + expected.albums = right.albums.clone(); + let mut left_albums_without_lib_id = left.albums.clone(); + reset_lib_id(&mut left_albums_without_lib_id); + expected.albums.extend(left_albums_without_lib_id); + expected.albums.sort_unstable(); + let merged = right.clone().merge(left.clone()); assert_eq!(expected, merged); } @@ -487,6 +529,9 @@ mod tests { left.albums.push(right.albums[0].clone()); left.albums.sort_unstable(); + // Albums on right without a match on the left will lose their lib id. + reset_lib_id(&mut right.albums[1..]); + let mut expected = left.clone(); expected.meta.info.properties = expected .meta -- 2.47.1 From 6b5b16cece42c472ae283773d397530bccfd99c1 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 2 Jan 2025 11:44:08 +0100 Subject: [PATCH 04/16] Complete unit tests --- src/core/musichoard/library.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/musichoard/library.rs b/src/core/musichoard/library.rs index b14c0ce..09fa249 100644 --- a/src/core/musichoard/library.rs +++ b/src/core/musichoard/library.rs @@ -231,7 +231,7 @@ mod tests { } #[test] - fn rescan_library_album_id_clash() { + fn rescan_library_different_artist_album_title_clash() { let mut library = MockILibrary::new(); let mut expected = LIBRARY_COLLECTION.to_owned(); @@ -246,7 +246,7 @@ mod tests { item.album_title = clashed_album_id.title.clone(); } - expected[0].albums[0].meta.id = clashed_album_id.clone(); + expected[0].albums[0].meta.id.title = clashed_album_id.title.clone(); let library_input = Query::new(); let library_result = Ok(items); -- 2.47.1 From 2c1f6acf09fe5274965bb5aa257acc82d6204ca7 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 2 Jan 2025 11:50:04 +0100 Subject: [PATCH 05/16] Update database deserialize code --- src/external/database/serde/deserialize.rs | 20 ++++++++++++++++---- tests/files/database/database.json | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/external/database/serde/deserialize.rs b/src/external/database/serde/deserialize.rs index b46968c..a24f5ab 100644 --- a/src/external/database/serde/deserialize.rs +++ b/src/external/database/serde/deserialize.rs @@ -13,20 +13,22 @@ use crate::{ artist::{Artist, ArtistId}, Collection, Error as CollectionError, }, - external::database::serde::common::{SerdeAlbumPrimaryType, SerdeAlbumSecondaryType}, + external::database::serde::common::{ + AlbumLibIdDef, SerdeAlbumPrimaryType, SerdeAlbumSecondaryType, + }, }; use super::common::MbRefOptionDef; #[derive(Debug, Deserialize)] pub enum DeserializeDatabase { - V20240924(Vec), + V20250101(Vec), } impl From for Collection { fn from(database: DeserializeDatabase) -> Self { match database { - DeserializeDatabase::V20240924(collection) => { + DeserializeDatabase::V20250101(collection) => { collection.into_iter().map(Into::into).collect() } } @@ -45,12 +47,22 @@ pub struct DeserializeArtist { #[derive(Debug, Deserialize)] pub struct DeserializeAlbum { title: String, + lib_id: DeserializeAlbumLibId, seq: u8, musicbrainz: DeserializeMbRefOption, primary_type: Option, secondary_types: Vec, } +#[derive(Debug, Deserialize)] +pub struct DeserializeAlbumLibId(#[serde(with = "AlbumLibIdDef")] AlbumLibId); + +impl From for AlbumLibId { + fn from(value: DeserializeAlbumLibId) -> Self { + value.0 + } +} + #[derive(Debug, Deserialize)] pub struct DeserializeMbRefOption(#[serde(with = "MbRefOptionDef")] MbRefOption); @@ -131,7 +143,7 @@ impl From for Album { meta: AlbumMeta { id: AlbumId { title: album.title, - lib_id: AlbumLibId::None, + lib_id: album.lib_id.into(), }, date: AlbumDate::default(), seq: AlbumSeq(album.seq), diff --git a/tests/files/database/database.json b/tests/files/database/database.json index 401d0d0..e0420a3 100644 --- a/tests/files/database/database.json +++ b/tests/files/database/database.json @@ -1 +1 @@ -{"V20240924":[{"name":"Аркона","sort":"Arkona","musicbrainz":{"Some":"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":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Eluveitie","sort":null,"musicbrainz":{"Some":"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":"None","primary_type":"Ep","secondary_types":[]},{"title":"Slania","seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Frontside","sort":null,"musicbrainz":{"Some":"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":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Heaven’s Basement","sort":"Heaven’s Basement","musicbrainz":{"Some":"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":"None","primary_type":null,"secondary_types":[]},{"title":"Unbreakable","seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Metallica","sort":null,"musicbrainz":{"Some":"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":"None","primary_type":"Album","secondary_types":[]},{"title":"S&M","seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":["Live"]}]}]} \ No newline at end of file +{"V20250101":[{"name":"Аркона","sort":"Arkona","musicbrainz":{"Some":"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","lib_id":{"Some":7},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Eluveitie","sort":null,"musicbrainz":{"Some":"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]","lib_id":{"Some":1},"seq":0,"musicbrainz":"None","primary_type":"Ep","secondary_types":[]},{"title":"Slania","lib_id":{"Some":2},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Frontside","sort":null,"musicbrainz":{"Some":"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…","lib_id":{"Some":3},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Heaven’s Basement","sort":"Heaven’s Basement","musicbrainz":{"Some":"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","lib_id":"Singleton","seq":0,"musicbrainz":"None","primary_type":null,"secondary_types":[]},{"title":"Unbreakable","lib_id":{"Some":4},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Metallica","sort":null,"musicbrainz":{"Some":"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","lib_id":{"Some":5},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]},{"title":"S&M","lib_id":{"Some":6},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":["Live"]}]}]} \ No newline at end of file -- 2.47.1 From 82c60320dcde75fc1cf16d7a34fb978924e6e28f Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 2 Jan 2025 11:55:24 +0100 Subject: [PATCH 06/16] Lints --- src/core/collection/album.rs | 5 ++++- src/core/collection/artist.rs | 4 ++-- src/core/interface/library/mod.rs | 7 ++++++- src/core/interface/library/testmod.rs | 5 ++++- src/tui/ui/display.rs | 3 ++- tests/library/testmod.rs | 5 ++++- 6 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/core/collection/album.rs b/src/core/collection/album.rs index a8b19c0..26a02fe 100644 --- a/src/core/collection/album.rs +++ b/src/core/collection/album.rs @@ -295,7 +295,10 @@ impl AsRef for AlbumId { impl AlbumId { pub fn new>(name: S) -> AlbumId { - AlbumId { title: name.into(), lib_id: AlbumLibId::None } + AlbumId { + title: name.into(), + lib_id: AlbumLibId::None, + } } } diff --git a/src/core/collection/artist.rs b/src/core/collection/artist.rs index 1c0e332..a627e5b 100644 --- a/src/core/collection/artist.rs +++ b/src/core/collection/artist.rs @@ -58,7 +58,7 @@ impl Artist { } fn merge_album_with_lib_id( - primary_albums: &mut Vec, + primary_albums: &mut [Album], mut secondary_album: Album, ) -> Option { if let lib_id @ AlbumLibId::Some(_) | lib_id @ AlbumLibId::Singleton = @@ -79,7 +79,7 @@ impl Artist { } fn merge_albums_with_lib_id( - primary_albums: &mut Vec, + primary_albums: &mut [Album], mut secondary_albums: Vec, ) -> HashMap> { let mut secondary_without_id = HashMap::>::new(); diff --git a/src/core/interface/library/mod.rs b/src/core/interface/library/mod.rs index aedbe01..190f728 100644 --- a/src/core/interface/library/mod.rs +++ b/src/core/interface/library/mod.rs @@ -1,6 +1,11 @@ //! Module for interacting with the music library. -use std::{collections::HashSet, fmt, num::ParseIntError, str::{ParseBoolError, Utf8Error}}; +use std::{ + collections::HashSet, + fmt, + num::ParseIntError, + str::{ParseBoolError, Utf8Error}, +}; #[cfg(test)] use mockall::automock; diff --git a/src/core/interface/library/testmod.rs b/src/core/interface/library/testmod.rs index 8650732..4e447c0 100644 --- a/src/core/interface/library/testmod.rs +++ b/src/core/interface/library/testmod.rs @@ -1,6 +1,9 @@ use once_cell::sync::Lazy; -use crate::{collection::album::AlbumLibId, core::{collection::track::TrackFormat, interface::library::Item}}; +use crate::{ + collection::album::AlbumLibId, + core::{collection::track::TrackFormat, interface::library::Item}, +}; pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { vec![ diff --git a/src/tui/ui/display.rs b/src/tui/ui/display.rs index 7a1ea54..b31da07 100644 --- a/src/tui/ui/display.rs +++ b/src/tui/ui/display.rs @@ -1,6 +1,7 @@ use musichoard::collection::{ album::{ - AlbumDate, AlbumId, AlbumLibId, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, AlbumSeq, AlbumStatus + AlbumDate, AlbumId, AlbumLibId, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, AlbumSeq, + AlbumStatus, }, artist::ArtistMeta, musicbrainz::{IMusicBrainzRef, MbRefOption}, diff --git a/tests/library/testmod.rs b/tests/library/testmod.rs index 295268d..36cd26d 100644 --- a/tests/library/testmod.rs +++ b/tests/library/testmod.rs @@ -1,6 +1,9 @@ use once_cell::sync::Lazy; -use musichoard::{collection::{album::AlbumLibId, track::TrackFormat}, interface::library::Item}; +use musichoard::{ + collection::{album::AlbumLibId, track::TrackFormat}, + interface::library::Item, +}; pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { vec![ -- 2.47.1 From 8667f6a473a1d4e09afa9bee9247d63ce6db2f92 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 2 Jan 2025 12:49:28 +0100 Subject: [PATCH 07/16] Add an alike method --- src/core/collection/album.rs | 17 ++- src/core/collection/artist.rs | 2 +- src/core/collection/merge.rs | 8 -- src/core/interface/library/mod.rs | 3 + src/core/interface/library/testmod.rs | 44 +++---- src/external/database/json/testmod.rs | 20 ++-- src/external/database/serde/common.rs | 2 +- src/external/library/beets/mod.rs | 2 +- src/testmod/full.rs | 20 ++-- src/testmod/library.rs | 20 ++-- src/tui/ui/display.rs | 9 +- tests/files/database/database.json | 2 +- tests/library/testmod.rs | 158 +++++++++++++------------- tests/testlib.rs | 14 +-- 14 files changed, 164 insertions(+), 157 deletions(-) diff --git a/src/core/collection/album.rs b/src/core/collection/album.rs index 26a02fe..c10f9d5 100644 --- a/src/core/collection/album.rs +++ b/src/core/collection/album.rs @@ -40,10 +40,19 @@ pub struct AlbumId { pub lib_id: AlbumLibId, } +impl AlbumId { + pub fn alike(&self, other: &AlbumId) -> bool { + let titles_alike = self.title == other.title; + let lib_id_alike = + self.lib_id.is_none() || other.lib_id.is_none() || (self.lib_id == other.lib_id); + titles_alike && lib_id_alike + } +} + /// Unique library identifier. #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)] pub enum AlbumLibId { - Some(u32), + Value(u32), Singleton, None, } @@ -259,11 +268,7 @@ impl Ord for AlbumMeta { impl Merge for AlbumMeta { fn merge_in_place(&mut self, other: Self) { - if !self.id.lib_id.is_none() && !other.id.lib_id.is_none() { - assert_eq!(self.id, other.id); - } else { - assert_eq!(self.id.title, other.id.title); - } + assert!(self.id.alike(&other.id)); self.seq = std::cmp::max(self.seq, other.seq); diff --git a/src/core/collection/artist.rs b/src/core/collection/artist.rs index a627e5b..3375ade 100644 --- a/src/core/collection/artist.rs +++ b/src/core/collection/artist.rs @@ -61,7 +61,7 @@ impl Artist { primary_albums: &mut [Album], mut secondary_album: Album, ) -> Option { - if let lib_id @ AlbumLibId::Some(_) | lib_id @ AlbumLibId::Singleton = + if let lib_id @ AlbumLibId::Value(_) | lib_id @ AlbumLibId::Singleton = secondary_album.meta.id.lib_id { if let Some(ref mut primary_album) = primary_albums diff --git a/src/core/collection/merge.rs b/src/core/collection/merge.rs index 704e8e6..ebfed09 100644 --- a/src/core/collection/merge.rs +++ b/src/core/collection/merge.rs @@ -98,14 +98,6 @@ where T: MergeId + Merge + Ord, IT: IntoIterator, { - pub fn merge_iter(primary: IT, secondary: IT) -> Vec { - let primary = primary - .into_iter() - .map(|item| (item.id().clone(), item)) - .collect(); - Self::merge(primary, secondary) - } - pub fn merge(mut primary: HashMap, secondary: IT) -> Vec { for secondary_item in secondary { if let Some(ref mut primary_item) = primary.get_mut(secondary_item.id()) { diff --git a/src/core/interface/library/mod.rs b/src/core/interface/library/mod.rs index 190f728..0cdce85 100644 --- a/src/core/interface/library/mod.rs +++ b/src/core/interface/library/mod.rs @@ -177,6 +177,7 @@ mod tests { let exe_err = Error::Executor(String::from("Executor")); let io_err: Error = io::Error::new(io::ErrorKind::Interrupted, "Interrupted").into(); let inv_err = Error::Invalid(String::from("Invalid")); + let bool_err: Error = "f".parse::().unwrap_err().into(); let int_err: Error = "five".parse::().unwrap_err().into(); #[allow(invalid_from_utf8)] let utf_err: Error = std::str::from_utf8(b"\xe2\x28\xa1").unwrap_err().into(); @@ -184,12 +185,14 @@ mod tests { assert!(!exe_err.to_string().is_empty()); assert!(!io_err.to_string().is_empty()); assert!(!inv_err.to_string().is_empty()); + assert!(!bool_err.to_string().is_empty()); assert!(!int_err.to_string().is_empty()); assert!(!utf_err.to_string().is_empty()); assert!(!format!("{:?}", exe_err).is_empty()); assert!(!format!("{:?}", io_err).is_empty()); assert!(!format!("{:?}", inv_err).is_empty()); + assert!(!format!("{:?}", bool_err).is_empty()); assert!(!format!("{:?}", int_err).is_empty()); assert!(!format!("{:?}", utf_err).is_empty()); } diff --git a/src/core/interface/library/testmod.rs b/src/core/interface/library/testmod.rs index 4e447c0..43408b6 100644 --- a/src/core/interface/library/testmod.rs +++ b/src/core/interface/library/testmod.rs @@ -14,7 +14,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title a.a"), - album_lib_id: AlbumLibId::Some(1), + album_lib_id: AlbumLibId::Value(1), track_number: 1, track_title: String::from("track a.a.1"), track_artist: vec![String::from("artist a.a.1")], @@ -28,7 +28,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title a.a"), - album_lib_id: AlbumLibId::Some(1), + album_lib_id: AlbumLibId::Value(1), track_number: 2, track_title: String::from("track a.a.2"), track_artist: vec![ @@ -45,7 +45,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title a.a"), - album_lib_id: AlbumLibId::Some(1), + album_lib_id: AlbumLibId::Value(1), track_number: 3, track_title: String::from("track a.a.3"), track_artist: vec![String::from("artist a.a.3")], @@ -59,7 +59,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title a.a"), - album_lib_id: AlbumLibId::Some(1), + album_lib_id: AlbumLibId::Value(1), track_number: 4, track_title: String::from("track a.a.4"), track_artist: vec![String::from("artist a.a.4")], @@ -73,7 +73,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 4, album_day: 0, album_title: String::from("album_title a.b"), - album_lib_id: AlbumLibId::Some(2), + album_lib_id: AlbumLibId::Value(2), track_number: 1, track_title: String::from("track a.b.1"), track_artist: vec![String::from("artist a.b.1")], @@ -87,7 +87,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 4, album_day: 0, album_title: String::from("album_title a.b"), - album_lib_id: AlbumLibId::Some(2), + album_lib_id: AlbumLibId::Value(2), track_number: 2, track_title: String::from("track a.b.2"), track_artist: vec![String::from("artist a.b.2")], @@ -101,7 +101,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 6, album_day: 6, album_title: String::from("album_title b.a"), - album_lib_id: AlbumLibId::Some(3), + album_lib_id: AlbumLibId::Value(3), track_number: 1, track_title: String::from("track b.a.1"), track_artist: vec![String::from("artist b.a.1")], @@ -115,7 +115,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 6, album_day: 6, album_title: String::from("album_title b.a"), - album_lib_id: AlbumLibId::Some(3), + album_lib_id: AlbumLibId::Value(3), track_number: 2, track_title: String::from("track b.a.2"), track_artist: vec![ @@ -132,7 +132,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title b.b"), - album_lib_id: AlbumLibId::Some(4), + album_lib_id: AlbumLibId::Value(4), track_number: 1, track_title: String::from("track b.b.1"), track_artist: vec![String::from("artist b.b.1")], @@ -146,7 +146,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title b.b"), - album_lib_id: AlbumLibId::Some(4), + album_lib_id: AlbumLibId::Value(4), track_number: 2, track_title: String::from("track b.b.2"), track_artist: vec![ @@ -163,7 +163,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title b.c"), - album_lib_id: AlbumLibId::Some(5), + album_lib_id: AlbumLibId::Value(5), track_number: 1, track_title: String::from("track b.c.1"), track_artist: vec![String::from("artist b.c.1")], @@ -177,7 +177,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title b.c"), - album_lib_id: AlbumLibId::Some(5), + album_lib_id: AlbumLibId::Value(5), track_number: 2, track_title: String::from("track b.c.2"), track_artist: vec![ @@ -194,7 +194,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title b.d"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 1, track_title: String::from("track b.d.1"), track_artist: vec![String::from("artist b.d.1")], @@ -208,7 +208,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title b.d"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 2, track_title: String::from("track b.d.2"), track_artist: vec![ @@ -225,7 +225,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title c.a"), - album_lib_id: AlbumLibId::Some(7), + album_lib_id: AlbumLibId::Value(7), track_number: 1, track_title: String::from("track c.a.1"), track_artist: vec![String::from("artist c.a.1")], @@ -239,7 +239,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title c.a"), - album_lib_id: AlbumLibId::Some(7), + album_lib_id: AlbumLibId::Value(7), track_number: 2, track_title: String::from("track c.a.2"), track_artist: vec![ @@ -256,7 +256,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title c.b"), - album_lib_id: AlbumLibId::Some(8), + album_lib_id: AlbumLibId::Value(8), track_number: 1, track_title: String::from("track c.b.1"), track_artist: vec![String::from("artist c.b.1")], @@ -270,7 +270,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title c.b"), - album_lib_id: AlbumLibId::Some(8), + album_lib_id: AlbumLibId::Value(8), track_number: 2, track_title: String::from("track c.b.2"), track_artist: vec![ @@ -287,7 +287,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title d.a"), - album_lib_id: AlbumLibId::Some(9), + album_lib_id: AlbumLibId::Value(9), track_number: 1, track_title: String::from("track d.a.1"), track_artist: vec![String::from("artist d.a.1")], @@ -301,7 +301,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title d.a"), - album_lib_id: AlbumLibId::Some(9), + album_lib_id: AlbumLibId::Value(9), track_number: 2, track_title: String::from("track d.a.2"), track_artist: vec![ @@ -318,7 +318,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title d.b"), - album_lib_id: AlbumLibId::Some(10), + album_lib_id: AlbumLibId::Value(10), track_number: 1, track_title: String::from("track d.b.1"), track_artist: vec![String::from("artist d.b.1")], @@ -332,7 +332,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("album_title d.b"), - album_lib_id: AlbumLibId::Some(10), + album_lib_id: AlbumLibId::Value(10), track_number: 2, track_title: String::from("track d.b.2"), track_artist: vec![ diff --git a/src/external/database/json/testmod.rs b/src/external/database/json/testmod.rs index 31dae78..0f2f602 100644 --- a/src/external/database/json/testmod.rs +++ b/src/external/database/json/testmod.rs @@ -11,12 +11,12 @@ pub static DATABASE_JSON: &str = "{\ },\ \"albums\":[\ {\ - \"title\":\"album_title a.a\",\"lib_id\":{\"Some\":1},\"seq\":1,\ + \"title\":\"album_title a.a\",\"lib_id\":{\"Value\":1},\"seq\":1,\ \"musicbrainz\":{\"Some\":\"00000000-0000-0000-0000-000000000000\"},\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title a.b\",\"lib_id\":{\"Some\":2},\"seq\":1,\"musicbrainz\":\"None\",\ + \"title\":\"album_title a.b\",\"lib_id\":{\"Value\":2},\"seq\":1,\"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ }\ ]\ @@ -35,21 +35,21 @@ pub static DATABASE_JSON: &str = "{\ },\ \"albums\":[\ {\ - \"title\":\"album_title b.a\",\"lib_id\":{\"Some\":3},\"seq\":1,\"musicbrainz\":\"None\",\ + \"title\":\"album_title b.a\",\"lib_id\":{\"Value\":3},\"seq\":1,\"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title b.b\",\"lib_id\":{\"Some\":4},\"seq\":3,\ + \"title\":\"album_title b.b\",\"lib_id\":{\"Value\":4},\"seq\":3,\ \"musicbrainz\":{\"Some\":\"11111111-1111-1111-1111-111111111111\"},\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title b.c\",\"lib_id\":{\"Some\":5},\"seq\":2,\ + \"title\":\"album_title b.c\",\"lib_id\":{\"Value\":5},\"seq\":2,\ \"musicbrainz\":{\"Some\":\"11111111-1111-1111-1111-111111111112\"},\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title b.d\",\"lib_id\":{\"Some\":6},\"seq\":4,\"musicbrainz\":\"None\",\ + \"title\":\"album_title b.d\",\"lib_id\":{\"Value\":6},\"seq\":4,\"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ }\ ]\ @@ -61,11 +61,11 @@ pub static DATABASE_JSON: &str = "{\ \"properties\":{},\ \"albums\":[\ {\ - \"title\":\"album_title c.a\",\"lib_id\":{\"Some\":7},\"seq\":0,\"musicbrainz\":\"None\",\ + \"title\":\"album_title c.a\",\"lib_id\":{\"Value\":7},\"seq\":0,\"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title c.b\",\"lib_id\":{\"Some\":8},\"seq\":0,\"musicbrainz\":\"None\",\ + \"title\":\"album_title c.b\",\"lib_id\":{\"Value\":8},\"seq\":0,\"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ }\ ]\ @@ -77,11 +77,11 @@ pub static DATABASE_JSON: &str = "{\ \"properties\":{},\ \"albums\":[\ {\ - \"title\":\"album_title d.a\",\"lib_id\":{\"Some\":9},\"seq\":0,\"musicbrainz\":\"None\",\ + \"title\":\"album_title d.a\",\"lib_id\":{\"Value\":9},\"seq\":0,\"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ },\ {\ - \"title\":\"album_title d.b\",\"lib_id\":{\"Some\":10},\"seq\":0,\"musicbrainz\":\"None\",\ + \"title\":\"album_title d.b\",\"lib_id\":{\"Value\":10},\"seq\":0,\"musicbrainz\":\"None\",\ \"primary_type\":\"Album\",\"secondary_types\":[]\ }\ ]\ diff --git a/src/external/database/serde/common.rs b/src/external/database/serde/common.rs index fdf9827..ff75896 100644 --- a/src/external/database/serde/common.rs +++ b/src/external/database/serde/common.rs @@ -8,7 +8,7 @@ use crate::{ #[derive(Debug, Deserialize, Serialize)] #[serde(remote = "AlbumLibId")] pub enum AlbumLibIdDef { - Some(u32), + Value(u32), Singleton, None, } diff --git a/src/external/library/beets/mod.rs b/src/external/library/beets/mod.rs index 2cbfd9d..e72bf56 100644 --- a/src/external/library/beets/mod.rs +++ b/src/external/library/beets/mod.rs @@ -167,7 +167,7 @@ impl BeetsLibrary { let album_title = split[6].to_string(); let album_lib_id = match singleton { true => AlbumLibId::Singleton, - false => AlbumLibId::Some(split[7].parse::()?), + false => AlbumLibId::Value(split[7].parse::()?), }; let track_number = split[8].parse::()?; let track_title = split[9].to_string(); diff --git a/src/testmod/full.rs b/src/testmod/full.rs index 96805ad..87e1cbc 100644 --- a/src/testmod/full.rs +++ b/src/testmod/full.rs @@ -28,7 +28,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title a.a".to_string(), - lib_id: AlbumLibId::Some(1), + lib_id: AlbumLibId::Value(1), }, date: 1998.into(), seq: AlbumSeq(1), @@ -94,7 +94,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title a.b".to_string(), - lib_id: AlbumLibId::Some(2), + lib_id: AlbumLibId::Value(2), }, date: (2015, 4).into(), seq: AlbumSeq(1), @@ -162,7 +162,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title b.a".to_string(), - lib_id: AlbumLibId::Some(3), + lib_id: AlbumLibId::Value(3), }, date: (2003, 6, 6).into(), seq: AlbumSeq(1), @@ -204,7 +204,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title b.b".to_string(), - lib_id: AlbumLibId::Some(4), + lib_id: AlbumLibId::Value(4), }, date: 2008.into(), seq: AlbumSeq(3), @@ -248,7 +248,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title b.c".to_string(), - lib_id: AlbumLibId::Some(5), + lib_id: AlbumLibId::Value(5), }, date: 2009.into(), seq: AlbumSeq(2), @@ -292,7 +292,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title b.d".to_string(), - lib_id: AlbumLibId::Some(6), + lib_id: AlbumLibId::Value(6), }, date: 2015.into(), seq: AlbumSeq(4), @@ -348,7 +348,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title c.a".to_string(), - lib_id: AlbumLibId::Some(7), + lib_id: AlbumLibId::Value(7), }, date: 1985.into(), seq: AlbumSeq(0), @@ -390,7 +390,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title c.b".to_string(), - lib_id: AlbumLibId::Some(8), + lib_id: AlbumLibId::Value(8), }, date: 2018.into(), seq: AlbumSeq(0), @@ -446,7 +446,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title d.a".to_string(), - lib_id: AlbumLibId::Some(9), + lib_id: AlbumLibId::Value(9), }, date: 1995.into(), seq: AlbumSeq(0), @@ -488,7 +488,7 @@ macro_rules! full_collection { meta: AlbumMeta { id: AlbumId { title: "album_title d.b".to_string(), - lib_id: AlbumLibId::Some(10), + lib_id: AlbumLibId::Value(10), }, date: 2028.into(), seq: AlbumSeq(0), diff --git a/src/testmod/library.rs b/src/testmod/library.rs index 5e7a354..a50b16c 100644 --- a/src/testmod/library.rs +++ b/src/testmod/library.rs @@ -18,7 +18,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title a.a".to_string(), - lib_id: AlbumLibId::Some(1), + lib_id: AlbumLibId::Value(1), }, date: 1998.into(), seq: AlbumSeq(0), @@ -78,7 +78,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title a.b".to_string(), - lib_id: AlbumLibId::Some(2), + lib_id: AlbumLibId::Value(2), }, date: (2015, 4).into(), seq: AlbumSeq(0), @@ -127,7 +127,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title b.a".to_string(), - lib_id: AlbumLibId::Some(3), + lib_id: AlbumLibId::Value(3), }, date: (2003, 6, 6).into(), seq: AlbumSeq(0), @@ -165,7 +165,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title b.b".to_string(), - lib_id: AlbumLibId::Some(4), + lib_id: AlbumLibId::Value(4), }, date: 2008.into(), seq: AlbumSeq(0), @@ -203,7 +203,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title b.c".to_string(), - lib_id: AlbumLibId::Some(5), + lib_id: AlbumLibId::Value(5), }, date: 2009.into(), seq: AlbumSeq(0), @@ -241,7 +241,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title b.d".to_string(), - lib_id: AlbumLibId::Some(6), + lib_id: AlbumLibId::Value(6), }, date: 2015.into(), seq: AlbumSeq(0), @@ -293,7 +293,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title c.a".to_string(), - lib_id: AlbumLibId::Some(7), + lib_id: AlbumLibId::Value(7), }, date: 1985.into(), seq: AlbumSeq(0), @@ -331,7 +331,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title c.b".to_string(), - lib_id: AlbumLibId::Some(8), + lib_id: AlbumLibId::Value(8), }, date: 2018.into(), seq: AlbumSeq(0), @@ -383,7 +383,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title d.a".to_string(), - lib_id: AlbumLibId::Some(9), + lib_id: AlbumLibId::Value(9), }, date: 1995.into(), seq: AlbumSeq(0), @@ -421,7 +421,7 @@ macro_rules! library_collection { meta: AlbumMeta { id: AlbumId { title: "album_title d.b".to_string(), - lib_id: AlbumLibId::Some(10), + lib_id: AlbumLibId::Value(10), }, date: 2028.into(), seq: AlbumSeq(0), diff --git a/src/tui/ui/display.rs b/src/tui/ui/display.rs index b31da07..07efca1 100644 --- a/src/tui/ui/display.rs +++ b/src/tui/ui/display.rs @@ -23,7 +23,7 @@ impl UiDisplay { pub fn display_album_lib_id(lib_id: &AlbumLibId) -> String { match lib_id { - AlbumLibId::Some(val) => val.to_string(), + AlbumLibId::Value(val) => val.to_string(), AlbumLibId::Singleton => "Singleton".to_string(), AlbumLibId::None => "None".to_string(), } @@ -205,6 +205,13 @@ mod tests { ); } + #[test] + fn display_album_lib_id() { + assert_eq!(UiDisplay::display_album_lib_id(&AlbumLibId::Value(5)), "5"); + assert_eq!(UiDisplay::display_album_lib_id(&AlbumLibId::Singleton), "Singleton"); + assert_eq!(UiDisplay::display_album_lib_id(&AlbumLibId::None), "None"); + } + #[test] fn display_date() { let date: AlbumDate = 1990.into(); diff --git a/tests/files/database/database.json b/tests/files/database/database.json index e0420a3..93fb18a 100644 --- a/tests/files/database/database.json +++ b/tests/files/database/database.json @@ -1 +1 @@ -{"V20250101":[{"name":"Аркона","sort":"Arkona","musicbrainz":{"Some":"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","lib_id":{"Some":7},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Eluveitie","sort":null,"musicbrainz":{"Some":"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]","lib_id":{"Some":1},"seq":0,"musicbrainz":"None","primary_type":"Ep","secondary_types":[]},{"title":"Slania","lib_id":{"Some":2},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Frontside","sort":null,"musicbrainz":{"Some":"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…","lib_id":{"Some":3},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Heaven’s Basement","sort":"Heaven’s Basement","musicbrainz":{"Some":"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","lib_id":"Singleton","seq":0,"musicbrainz":"None","primary_type":null,"secondary_types":[]},{"title":"Unbreakable","lib_id":{"Some":4},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Metallica","sort":null,"musicbrainz":{"Some":"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","lib_id":{"Some":5},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]},{"title":"S&M","lib_id":{"Some":6},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":["Live"]}]}]} \ No newline at end of file +{"V20250101":[{"name":"Аркона","sort":"Arkona","musicbrainz":{"Some":"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","lib_id":{"Value":7},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Eluveitie","sort":null,"musicbrainz":{"Some":"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]","lib_id":{"Value":1},"seq":0,"musicbrainz":"None","primary_type":"Ep","secondary_types":[]},{"title":"Slania","lib_id":{"Value":2},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Frontside","sort":null,"musicbrainz":{"Some":"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…","lib_id":{"Value":3},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Heaven’s Basement","sort":"Heaven’s Basement","musicbrainz":{"Some":"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","lib_id":"Singleton","seq":0,"musicbrainz":"None","primary_type":null,"secondary_types":[]},{"title":"Unbreakable","lib_id":{"Value":4},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Metallica","sort":null,"musicbrainz":{"Some":"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","lib_id":{"Value":5},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]},{"title":"S&M","lib_id":{"Value":6},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":["Live"]}]}]} \ No newline at end of file diff --git a/tests/library/testmod.rs b/tests/library/testmod.rs index 36cd26d..9889663 100644 --- a/tests/library/testmod.rs +++ b/tests/library/testmod.rs @@ -14,7 +14,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), - album_lib_id: AlbumLibId::Some(7), + album_lib_id: AlbumLibId::Value(7), track_number: 1, track_title: String::from("Az’"), track_artist: vec![String::from("Аркона")], @@ -28,7 +28,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), - album_lib_id: AlbumLibId::Some(7), + album_lib_id: AlbumLibId::Value(7), track_number: 2, track_title: String::from("Arkaim"), track_artist: vec![String::from("Аркона")], @@ -42,7 +42,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), - album_lib_id: AlbumLibId::Some(7), + album_lib_id: AlbumLibId::Value(7), track_number: 3, track_title: String::from("Bol’no mne"), track_artist: vec![String::from("Аркона")], @@ -56,7 +56,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), - album_lib_id: AlbumLibId::Some(7), + album_lib_id: AlbumLibId::Value(7), track_number: 4, track_title: String::from("Leshiy"), track_artist: vec![String::from("Аркона")], @@ -70,7 +70,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), - album_lib_id: AlbumLibId::Some(7), + album_lib_id: AlbumLibId::Value(7), track_number: 5, track_title: String::from("Zakliatie"), track_artist: vec![String::from("Аркона")], @@ -84,7 +84,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), - album_lib_id: AlbumLibId::Some(7), + album_lib_id: AlbumLibId::Value(7), track_number: 6, track_title: String::from("Predok"), track_artist: vec![String::from("Аркона")], @@ -98,7 +98,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), - album_lib_id: AlbumLibId::Some(7), + album_lib_id: AlbumLibId::Value(7), track_number: 7, track_title: String::from("Nikogda"), track_artist: vec![String::from("Аркона")], @@ -112,7 +112,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), - album_lib_id: AlbumLibId::Some(7), + album_lib_id: AlbumLibId::Value(7), track_number: 8, track_title: String::from("Tam za tumanami"), track_artist: vec![String::from("Аркона")], @@ -126,7 +126,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), - album_lib_id: AlbumLibId::Some(7), + album_lib_id: AlbumLibId::Value(7), track_number: 9, track_title: String::from("Potomok"), track_artist: vec![String::from("Аркона")], @@ -140,7 +140,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), - album_lib_id: AlbumLibId::Some(7), + album_lib_id: AlbumLibId::Value(7), track_number: 10, track_title: String::from("Slovo"), track_artist: vec![String::from("Аркона")], @@ -154,7 +154,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), - album_lib_id: AlbumLibId::Some(7), + album_lib_id: AlbumLibId::Value(7), track_number: 11, track_title: String::from("Odna"), track_artist: vec![String::from("Аркона")], @@ -168,7 +168,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), - album_lib_id: AlbumLibId::Some(7), + album_lib_id: AlbumLibId::Value(7), track_number: 12, track_title: String::from("Vo moiom sadochke…"), track_artist: vec![String::from("Аркона")], @@ -182,7 +182,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), - album_lib_id: AlbumLibId::Some(7), + album_lib_id: AlbumLibId::Value(7), track_number: 13, track_title: String::from("Stenka na stenku"), track_artist: vec![String::from("Аркона")], @@ -196,7 +196,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slovo"), - album_lib_id: AlbumLibId::Some(7), + album_lib_id: AlbumLibId::Value(7), track_number: 14, track_title: String::from("Zimushka"), track_artist: vec![String::from("Аркона")], @@ -210,7 +210,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Vên [re‐recorded]"), - album_lib_id: AlbumLibId::Some(1), + album_lib_id: AlbumLibId::Value(1), track_number: 1, track_title: String::from("Verja Urit an Bitus"), track_artist: vec![String::from("Eluveitie")], @@ -224,7 +224,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Vên [re‐recorded]"), - album_lib_id: AlbumLibId::Some(1), + album_lib_id: AlbumLibId::Value(1), track_number: 2, track_title: String::from("Uis Elveti"), track_artist: vec![String::from("Eluveitie")], @@ -238,7 +238,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Vên [re‐recorded]"), - album_lib_id: AlbumLibId::Some(1), + album_lib_id: AlbumLibId::Value(1), track_number: 3, track_title: String::from("Ôrô"), track_artist: vec![String::from("Eluveitie")], @@ -252,7 +252,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Vên [re‐recorded]"), - album_lib_id: AlbumLibId::Some(1), + album_lib_id: AlbumLibId::Value(1), track_number: 4, track_title: String::from("Lament"), track_artist: vec![String::from("Eluveitie")], @@ -266,7 +266,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Vên [re‐recorded]"), - album_lib_id: AlbumLibId::Some(1), + album_lib_id: AlbumLibId::Value(1), track_number: 5, track_title: String::from("Druid"), track_artist: vec![String::from("Eluveitie")], @@ -280,7 +280,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Vên [re‐recorded]"), - album_lib_id: AlbumLibId::Some(1), + album_lib_id: AlbumLibId::Value(1), track_number: 6, track_title: String::from("Jêzaïg"), track_artist: vec![String::from("Eluveitie")], @@ -294,7 +294,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), - album_lib_id: AlbumLibId::Some(2), + album_lib_id: AlbumLibId::Value(2), track_number: 1, track_title: String::from("Samon"), track_artist: vec![String::from("Eluveitie")], @@ -308,7 +308,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), - album_lib_id: AlbumLibId::Some(2), + album_lib_id: AlbumLibId::Value(2), track_number: 2, track_title: String::from("Primordial Breath"), track_artist: vec![String::from("Eluveitie")], @@ -322,7 +322,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), - album_lib_id: AlbumLibId::Some(2), + album_lib_id: AlbumLibId::Value(2), track_number: 3, track_title: String::from("Inis Mona"), track_artist: vec![String::from("Eluveitie")], @@ -336,7 +336,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), - album_lib_id: AlbumLibId::Some(2), + album_lib_id: AlbumLibId::Value(2), track_number: 4, track_title: String::from("Gray Sublime Archon"), track_artist: vec![String::from("Eluveitie")], @@ -350,7 +350,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), - album_lib_id: AlbumLibId::Some(2), + album_lib_id: AlbumLibId::Value(2), track_number: 5, track_title: String::from("Anagantios"), track_artist: vec![String::from("Eluveitie")], @@ -364,7 +364,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), - album_lib_id: AlbumLibId::Some(2), + album_lib_id: AlbumLibId::Value(2), track_number: 6, track_title: String::from("Bloodstained Ground"), track_artist: vec![String::from("Eluveitie")], @@ -378,7 +378,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), - album_lib_id: AlbumLibId::Some(2), + album_lib_id: AlbumLibId::Value(2), track_number: 7, track_title: String::from("The Somber Lay"), track_artist: vec![String::from("Eluveitie")], @@ -392,7 +392,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), - album_lib_id: AlbumLibId::Some(2), + album_lib_id: AlbumLibId::Value(2), track_number: 8, track_title: String::from("Slanias Song"), track_artist: vec![String::from("Eluveitie")], @@ -406,7 +406,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), - album_lib_id: AlbumLibId::Some(2), + album_lib_id: AlbumLibId::Value(2), track_number: 9, track_title: String::from("Giamonios"), track_artist: vec![String::from("Eluveitie")], @@ -420,7 +420,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), - album_lib_id: AlbumLibId::Some(2), + album_lib_id: AlbumLibId::Value(2), track_number: 10, track_title: String::from("Tarvos"), track_artist: vec![String::from("Eluveitie")], @@ -434,7 +434,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), - album_lib_id: AlbumLibId::Some(2), + album_lib_id: AlbumLibId::Value(2), track_number: 11, track_title: String::from("Calling the Rain"), track_artist: vec![String::from("Eluveitie")], @@ -448,7 +448,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Slania"), - album_lib_id: AlbumLibId::Some(2), + album_lib_id: AlbumLibId::Value(2), track_number: 12, track_title: String::from("Elembivos"), track_artist: vec![String::from("Eluveitie")], @@ -462,7 +462,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), - album_lib_id: AlbumLibId::Some(3), + album_lib_id: AlbumLibId::Value(3), track_number: 1, track_title: String::from("Intro = Chaos"), track_artist: vec![String::from("Frontside")], @@ -476,7 +476,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), - album_lib_id: AlbumLibId::Some(3), + album_lib_id: AlbumLibId::Value(3), track_number: 2, track_title: String::from("Modlitwa"), track_artist: vec![String::from("Frontside")], @@ -490,7 +490,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), - album_lib_id: AlbumLibId::Some(3), + album_lib_id: AlbumLibId::Value(3), track_number: 3, track_title: String::from("Długa droga z piekła"), track_artist: vec![String::from("Frontside")], @@ -504,7 +504,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), - album_lib_id: AlbumLibId::Some(3), + album_lib_id: AlbumLibId::Value(3), track_number: 4, track_title: String::from("Synowie ognia"), track_artist: vec![String::from("Frontside")], @@ -518,7 +518,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), - album_lib_id: AlbumLibId::Some(3), + album_lib_id: AlbumLibId::Value(3), track_number: 5, track_title: String::from("1902"), track_artist: vec![String::from("Frontside")], @@ -532,7 +532,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), - album_lib_id: AlbumLibId::Some(3), + album_lib_id: AlbumLibId::Value(3), track_number: 6, track_title: String::from("Krew za krew"), track_artist: vec![String::from("Frontside")], @@ -546,7 +546,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), - album_lib_id: AlbumLibId::Some(3), + album_lib_id: AlbumLibId::Value(3), track_number: 7, track_title: String::from("Kulminacja"), track_artist: vec![String::from("Frontside")], @@ -560,7 +560,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), - album_lib_id: AlbumLibId::Some(3), + album_lib_id: AlbumLibId::Value(3), track_number: 8, track_title: String::from("Judasz"), track_artist: vec![String::from("Frontside")], @@ -574,7 +574,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), - album_lib_id: AlbumLibId::Some(3), + album_lib_id: AlbumLibId::Value(3), track_number: 9, track_title: String::from("Więzy"), track_artist: vec![String::from("Frontside")], @@ -588,7 +588,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), - album_lib_id: AlbumLibId::Some(3), + album_lib_id: AlbumLibId::Value(3), track_number: 10, track_title: String::from("Zagubione dusze"), track_artist: vec![String::from("Frontside")], @@ -602,7 +602,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), - album_lib_id: AlbumLibId::Some(3), + album_lib_id: AlbumLibId::Value(3), track_number: 11, track_title: String::from("Linia życia"), track_artist: vec![String::from("Frontside")], @@ -630,7 +630,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Unbreakable"), - album_lib_id: AlbumLibId::Some(4), + album_lib_id: AlbumLibId::Value(4), track_number: 1, track_title: String::from("Unbreakable"), track_artist: vec![String::from("Heaven’s Basement")], @@ -644,7 +644,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Unbreakable"), - album_lib_id: AlbumLibId::Some(4), + album_lib_id: AlbumLibId::Value(4), track_number: 2, track_title: String::from("Guilt Trips and Sins"), track_artist: vec![String::from("Heaven’s Basement")], @@ -658,7 +658,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Unbreakable"), - album_lib_id: AlbumLibId::Some(4), + album_lib_id: AlbumLibId::Value(4), track_number: 3, track_title: String::from("The Long Goodbye"), track_artist: vec![String::from("Heaven’s Basement")], @@ -672,7 +672,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Unbreakable"), - album_lib_id: AlbumLibId::Some(4), + album_lib_id: AlbumLibId::Value(4), track_number: 4, track_title: String::from("Close Encounters"), track_artist: vec![String::from("Heaven’s Basement")], @@ -686,7 +686,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Unbreakable"), - album_lib_id: AlbumLibId::Some(4), + album_lib_id: AlbumLibId::Value(4), track_number: 5, track_title: String::from("Paranoia"), track_artist: vec![String::from("Heaven’s Basement")], @@ -700,7 +700,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Unbreakable"), - album_lib_id: AlbumLibId::Some(4), + album_lib_id: AlbumLibId::Value(4), track_number: 6, track_title: String::from("Let Me Out of Here"), track_artist: vec![String::from("Heaven’s Basement")], @@ -714,7 +714,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Unbreakable"), - album_lib_id: AlbumLibId::Some(4), + album_lib_id: AlbumLibId::Value(4), track_number: 7, track_title: String::from("Leeches"), track_artist: vec![String::from("Heaven’s Basement")], @@ -728,7 +728,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Ride the Lightning"), - album_lib_id: AlbumLibId::Some(5), + album_lib_id: AlbumLibId::Value(5), track_number: 1, track_title: String::from("Fight Fire with Fire"), track_artist: vec![String::from("Metallica")], @@ -742,7 +742,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Ride the Lightning"), - album_lib_id: AlbumLibId::Some(5), + album_lib_id: AlbumLibId::Value(5), track_number: 2, track_title: String::from("Ride the Lightning"), track_artist: vec![String::from("Metallica")], @@ -756,7 +756,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Ride the Lightning"), - album_lib_id: AlbumLibId::Some(5), + album_lib_id: AlbumLibId::Value(5), track_number: 3, track_title: String::from("For Whom the Bell Tolls"), track_artist: vec![String::from("Metallica")], @@ -770,7 +770,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Ride the Lightning"), - album_lib_id: AlbumLibId::Some(5), + album_lib_id: AlbumLibId::Value(5), track_number: 4, track_title: String::from("Fade to Black"), track_artist: vec![String::from("Metallica")], @@ -784,7 +784,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Ride the Lightning"), - album_lib_id: AlbumLibId::Some(5), + album_lib_id: AlbumLibId::Value(5), track_number: 5, track_title: String::from("Trapped under Ice"), track_artist: vec![String::from("Metallica")], @@ -798,7 +798,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Ride the Lightning"), - album_lib_id: AlbumLibId::Some(5), + album_lib_id: AlbumLibId::Value(5), track_number: 6, track_title: String::from("Escape"), track_artist: vec![String::from("Metallica")], @@ -812,7 +812,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Ride the Lightning"), - album_lib_id: AlbumLibId::Some(5), + album_lib_id: AlbumLibId::Value(5), track_number: 7, track_title: String::from("Creeping Death"), track_artist: vec![String::from("Metallica")], @@ -826,7 +826,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("Ride the Lightning"), - album_lib_id: AlbumLibId::Some(5), + album_lib_id: AlbumLibId::Value(5), track_number: 8, track_title: String::from("The Call of Ktulu"), track_artist: vec![String::from("Metallica")], @@ -840,7 +840,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 1, track_title: String::from("The Ecstasy of Gold"), track_artist: vec![String::from("Metallica")], @@ -854,7 +854,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 2, track_title: String::from("The Call of Ktulu"), track_artist: vec![String::from("Metallica")], @@ -868,7 +868,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 3, track_title: String::from("Master of Puppets"), track_artist: vec![String::from("Metallica")], @@ -882,7 +882,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 4, track_title: String::from("Of Wolf and Man"), track_artist: vec![String::from("Metallica")], @@ -896,7 +896,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 5, track_title: String::from("The Thing That Should Not Be"), track_artist: vec![String::from("Metallica")], @@ -910,7 +910,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 6, track_title: String::from("Fuel"), track_artist: vec![String::from("Metallica")], @@ -924,7 +924,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 7, track_title: String::from("The Memory Remains"), track_artist: vec![String::from("Metallica")], @@ -938,7 +938,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 8, track_title: String::from("No Leaf Clover"), track_artist: vec![String::from("Metallica")], @@ -952,7 +952,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 9, track_title: String::from("Hero of the Day"), track_artist: vec![String::from("Metallica")], @@ -966,7 +966,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 10, track_title: String::from("Devil’s Dance"), track_artist: vec![String::from("Metallica")], @@ -980,7 +980,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 11, track_title: String::from("Bleeding Me"), track_artist: vec![String::from("Metallica")], @@ -994,7 +994,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 12, track_title: String::from("Nothing Else Matters"), track_artist: vec![String::from("Metallica")], @@ -1008,7 +1008,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 13, track_title: String::from("Until It Sleeps"), track_artist: vec![String::from("Metallica")], @@ -1022,7 +1022,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 14, track_title: String::from("For Whom the Bell Tolls"), track_artist: vec![String::from("Metallica")], @@ -1036,7 +1036,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 15, track_title: String::from("−Human"), track_artist: vec![String::from("Metallica")], @@ -1050,7 +1050,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 16, track_title: String::from("Wherever I May Roam"), track_artist: vec![String::from("Metallica")], @@ -1064,7 +1064,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 17, track_title: String::from("Outlaw Torn"), track_artist: vec![String::from("Metallica")], @@ -1078,7 +1078,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 18, track_title: String::from("Sad but True"), track_artist: vec![String::from("Metallica")], @@ -1092,7 +1092,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 19, track_title: String::from("One"), track_artist: vec![String::from("Metallica")], @@ -1106,7 +1106,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 20, track_title: String::from("Enter Sandman"), track_artist: vec![String::from("Metallica")], @@ -1120,7 +1120,7 @@ pub static LIBRARY_ITEMS: Lazy> = Lazy::new(|| -> Vec { album_month: 0, album_day: 0, album_title: String::from("S&M"), - album_lib_id: AlbumLibId::Some(6), + album_lib_id: AlbumLibId::Value(6), track_number: 21, track_title: String::from("Battery"), track_artist: vec![String::from("Metallica")], diff --git a/tests/testlib.rs b/tests/testlib.rs index 170c53f..072b325 100644 --- a/tests/testlib.rs +++ b/tests/testlib.rs @@ -41,7 +41,7 @@ pub static COLLECTION: Lazy> = Lazy::new(|| -> Collection { meta: AlbumMeta { id: AlbumId { title: String::from("Slovo"), - lib_id: AlbumLibId::Some(7), + lib_id: AlbumLibId::Value(7), }, date: 2011.into(), seq: AlbumSeq(0), @@ -234,7 +234,7 @@ pub static COLLECTION: Lazy> = Lazy::new(|| -> Collection { meta: AlbumMeta { id: AlbumId { title: String::from("Vên [re‐recorded]"), - lib_id: AlbumLibId::Some(1), + lib_id: AlbumLibId::Value(1), }, date: 2004.into(), seq: AlbumSeq(0), @@ -317,7 +317,7 @@ pub static COLLECTION: Lazy> = Lazy::new(|| -> Collection { meta: AlbumMeta { id: AlbumId { title: String::from("Slania"), - lib_id: AlbumLibId::Some(2), + lib_id: AlbumLibId::Value(2), }, date: 2008.into(), seq: AlbumSeq(0), @@ -488,7 +488,7 @@ pub static COLLECTION: Lazy> = Lazy::new(|| -> Collection { meta: AlbumMeta { id: AlbumId { title: String::from("…nasze jest królestwo, potęga i chwała na wieki…"), - lib_id: AlbumLibId::Some(3), + lib_id: AlbumLibId::Value(3), }, date: 2001.into(), seq: AlbumSeq(0), @@ -670,7 +670,7 @@ pub static COLLECTION: Lazy> = Lazy::new(|| -> Collection { meta: AlbumMeta { id: AlbumId { title: String::from("Unbreakable"), - lib_id: AlbumLibId::Some(4), + lib_id: AlbumLibId::Value(4), }, date: 2011.into(), seq: AlbumSeq(0), @@ -786,7 +786,7 @@ pub static COLLECTION: Lazy> = Lazy::new(|| -> Collection { meta: AlbumMeta { id: AlbumId { title: String::from("Ride the Lightning"), - lib_id: AlbumLibId::Some(5), + lib_id: AlbumLibId::Value(5), }, date: 1984.into(), seq: AlbumSeq(0), @@ -891,7 +891,7 @@ pub static COLLECTION: Lazy> = Lazy::new(|| -> Collection { meta: AlbumMeta { id: AlbumId { title: String::from("S&M"), - lib_id: AlbumLibId::Some(6), + lib_id: AlbumLibId::Value(6), }, date: 1999.into(), seq: AlbumSeq(0), -- 2.47.1 From e0c6788125ec4bea55c58458e18eb6b57a3e12d9 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 2 Jan 2025 12:50:31 +0100 Subject: [PATCH 08/16] Lint --- src/tui/ui/display.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tui/ui/display.rs b/src/tui/ui/display.rs index 07efca1..68c2281 100644 --- a/src/tui/ui/display.rs +++ b/src/tui/ui/display.rs @@ -208,7 +208,10 @@ mod tests { #[test] fn display_album_lib_id() { assert_eq!(UiDisplay::display_album_lib_id(&AlbumLibId::Value(5)), "5"); - assert_eq!(UiDisplay::display_album_lib_id(&AlbumLibId::Singleton), "Singleton"); + assert_eq!( + UiDisplay::display_album_lib_id(&AlbumLibId::Singleton), + "Singleton" + ); assert_eq!(UiDisplay::display_album_lib_id(&AlbumLibId::None), "None"); } -- 2.47.1 From 02fb023ad1d53999703626ea5b60a62f75956264 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 2 Jan 2025 13:07:21 +0100 Subject: [PATCH 09/16] Complete coverage --- src/core/collection/artist.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/core/collection/artist.rs b/src/core/collection/artist.rs index 3375ade..396561b 100644 --- a/src/core/collection/artist.rs +++ b/src/core/collection/artist.rs @@ -526,11 +526,20 @@ mod tests { let mut left = FULL_COLLECTION[0].to_owned(); let mut right = FULL_COLLECTION[1].to_owned(); right.meta.id = left.meta.id.clone(); + + // The right collection needs more albums than we modify to make sure some do not overlap. + assert!(right.albums.len() > 2); + + // This album will have a lib_id and will match based on lib_id. left.albums.push(right.albums[0].clone()); - left.albums.sort_unstable(); + + // This album will not have a lib_id and will match based on title. + left.albums.push(right.albums[1].clone()); + right.albums[1].meta.id.lib_id = AlbumLibId::None; // Albums on right without a match on the left will lose their lib id. - reset_lib_id(&mut right.albums[1..]); + let mut newly_added = right.albums[2..].to_vec(); + reset_lib_id(&mut newly_added); let mut expected = left.clone(); expected.meta.info.properties = expected @@ -538,9 +547,12 @@ mod tests { .info .properties .merge(right.clone().meta.info.properties); - expected.albums.append(&mut right.albums.clone()); + expected.albums.extend(newly_added); expected.albums.sort_unstable(); - expected.albums.dedup(); + + // Albums are expected to be sorted. + left.albums.sort_unstable(); + right.albums.sort_unstable(); let merged = left.clone().merge(right); assert_eq!(expected, merged); -- 2.47.1 From 8a1447334eb87efb1769434ab5f9b79ec4cad419 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 2 Jan 2025 14:45:11 +0100 Subject: [PATCH 10/16] Rename alike to compatible --- src/core/collection/album.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/collection/album.rs b/src/core/collection/album.rs index c10f9d5..b402008 100644 --- a/src/core/collection/album.rs +++ b/src/core/collection/album.rs @@ -41,11 +41,11 @@ pub struct AlbumId { } impl AlbumId { - pub fn alike(&self, other: &AlbumId) -> bool { - let titles_alike = self.title == other.title; - let lib_id_alike = + pub fn compatible(&self, other: &AlbumId) -> bool { + let titles_compatible = self.title == other.title; + let lib_id_compatible = self.lib_id.is_none() || other.lib_id.is_none() || (self.lib_id == other.lib_id); - titles_alike && lib_id_alike + titles_compatible && lib_id_compatible } } @@ -268,7 +268,7 @@ impl Ord for AlbumMeta { impl Merge for AlbumMeta { fn merge_in_place(&mut self, other: Self) { - assert!(self.id.alike(&other.id)); + assert!(self.id.compatible(&other.id)); self.seq = std::cmp::max(self.seq, other.seq); -- 2.47.1 From 38fa7f82c60c71dd607b2e765b52cf777e7ce38c Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 2 Jan 2025 15:14:11 +0100 Subject: [PATCH 11/16] Prettify code --- src/core/collection/album.rs | 2 -- src/core/collection/artist.rs | 39 ++++++++++++----------------------- 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/src/core/collection/album.rs b/src/core/collection/album.rs index b402008..da49982 100644 --- a/src/core/collection/album.rs +++ b/src/core/collection/album.rs @@ -269,9 +269,7 @@ impl Ord for AlbumMeta { impl Merge for AlbumMeta { fn merge_in_place(&mut self, other: Self) { assert!(self.id.compatible(&other.id)); - self.seq = std::cmp::max(self.seq, other.seq); - self.info.merge_in_place(other.info); } } diff --git a/src/core/collection/artist.rs b/src/core/collection/artist.rs index 396561b..71bf781 100644 --- a/src/core/collection/artist.rs +++ b/src/core/collection/artist.rs @@ -61,32 +61,26 @@ impl Artist { primary_albums: &mut [Album], mut secondary_album: Album, ) -> Option { - if let lib_id @ AlbumLibId::Value(_) | lib_id @ AlbumLibId::Singleton = - secondary_album.meta.id.lib_id - { - if let Some(ref mut primary_album) = primary_albums - .iter_mut() - .find(|album| album.meta.id.lib_id == lib_id) - { + let id_opt = secondary_album.meta.id.lib_id; + if let id @ AlbumLibId::Value(_) | id @ AlbumLibId::Singleton = id_opt { + let mut iter = primary_albums.iter_mut(); + if let Some(ref mut primary_album) = iter.find(|a| a.meta.id.lib_id == id) { primary_album.merge_in_place(secondary_album); return None; } - secondary_album.meta.id.lib_id = AlbumLibId::None; } - Some(secondary_album) } - fn merge_albums_with_lib_id( + fn merge_albums_by_lib_id( primary_albums: &mut [Album], mut secondary_albums: Vec, ) -> HashMap> { let mut secondary_without_id = HashMap::>::new(); for secondary_album in secondary_albums.drain(..) { - if let Some(secondary_album) = - Artist::merge_album_with_lib_id(primary_albums, secondary_album) - { + let unmerged = Artist::merge_album_with_lib_id(primary_albums, secondary_album); + if let Some(secondary_album) = unmerged { secondary_without_id .entry(secondary_album.meta.id.title.clone()) .or_default() @@ -96,15 +90,13 @@ impl Artist { secondary_without_id } - fn merge_albums_with_title( + fn merge_albums_by_title( primary_albums: &mut Vec, mut secondary_without_id: HashMap>, ) { for (title, mut secondary_albums) in secondary_without_id.drain() { - match primary_albums - .iter_mut() - .find(|album| album.meta.id.title == title) - { + let mut iter = primary_albums.iter_mut(); + match iter.find(|album| album.meta.id.title == title) { Some(ref mut primary_album) => { // We do not support merging multiple DB albums with same title yet. assert_eq!(secondary_albums.len(), 1); @@ -132,15 +124,10 @@ impl Merge for Artist { fn merge_in_place(&mut self, other: Self) { self.meta.merge_in_place(other.meta); - let mut primary_albums = mem::take(&mut self.albums); - let secondary_albums = other.albums; + let other_without_id = Artist::merge_albums_by_lib_id(&mut self.albums, other.albums); + Artist::merge_albums_by_title(&mut self.albums, other_without_id); - let secondary_without_id = - Artist::merge_albums_with_lib_id(&mut primary_albums, secondary_albums); - Artist::merge_albums_with_title(&mut primary_albums, secondary_without_id); - - primary_albums.sort_unstable(); - self.albums = primary_albums; + self.albums.sort_unstable(); } } -- 2.47.1 From ba0519d2507e1e951b9aae3c8acc18f4f23852de Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 2 Jan 2025 15:18:25 +0100 Subject: [PATCH 12/16] Fix imports --- src/core/collection/artist.rs | 5 +---- src/external/database/serde/deserialize.rs | 4 +--- src/external/musicbrainz/api/lookup.rs | 7 ++++--- src/tui/ui/info_state.rs | 2 +- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/core/collection/artist.rs b/src/core/collection/artist.rs index 71bf781..209148c 100644 --- a/src/core/collection/artist.rs +++ b/src/core/collection/artist.rs @@ -1,17 +1,14 @@ use std::{ collections::HashMap, fmt::{self, Debug, Display}, - mem, }; use crate::core::collection::{ - album::Album, + album::{Album, AlbumLibId}, merge::{Merge, MergeId}, musicbrainz::{MbArtistRef, MbRefOption}, }; -use super::album::AlbumLibId; - /// An artist. #[derive(Clone, Debug, PartialEq, Eq)] pub struct Artist { diff --git a/src/external/database/serde/deserialize.rs b/src/external/database/serde/deserialize.rs index a24f5ab..5cddf35 100644 --- a/src/external/database/serde/deserialize.rs +++ b/src/external/database/serde/deserialize.rs @@ -14,12 +14,10 @@ use crate::{ Collection, Error as CollectionError, }, external::database::serde::common::{ - AlbumLibIdDef, SerdeAlbumPrimaryType, SerdeAlbumSecondaryType, + AlbumLibIdDef, MbRefOptionDef, SerdeAlbumPrimaryType, SerdeAlbumSecondaryType, }, }; -use super::common::MbRefOptionDef; - #[derive(Debug, Deserialize)] pub enum DeserializeDatabase { V20250101(Vec), diff --git a/src/external/musicbrainz/api/lookup.rs b/src/external/musicbrainz/api/lookup.rs index 82197d5..140eded 100644 --- a/src/external/musicbrainz/api/lookup.rs +++ b/src/external/musicbrainz/api/lookup.rs @@ -4,13 +4,14 @@ use url::form_urlencoded; use crate::{ collection::musicbrainz::Mbid, external::musicbrainz::{ - api::{Error, MusicBrainzClient, MB_BASE_URL}, + api::{ + Error, MbArtistMeta, MbReleaseGroupMeta, MusicBrainzClient, SerdeMbArtistMeta, + SerdeMbReleaseGroupMeta, MB_BASE_URL, + }, IMusicBrainzHttp, }, }; -use super::{MbArtistMeta, MbReleaseGroupMeta, SerdeMbArtistMeta, SerdeMbReleaseGroupMeta}; - impl MusicBrainzClient { pub fn lookup_artist( &mut self, diff --git a/src/tui/ui/info_state.rs b/src/tui/ui/info_state.rs index 8a73877..4a99c0a 100644 --- a/src/tui/ui/info_state.rs +++ b/src/tui/ui/info_state.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use musichoard::collection::{album::Album, artist::Artist}; use ratatui::widgets::{ListState, Paragraph}; -use super::display::UiDisplay; +use crate::tui::ui::display::UiDisplay; struct InfoOverlay; -- 2.47.1 From edac12ada882dffc41842ad27044c51a7b35a074 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 2 Jan 2025 15:20:30 +0100 Subject: [PATCH 13/16] Rename method --- src/core/collection/artist.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/collection/artist.rs b/src/core/collection/artist.rs index 209148c..1ab01b1 100644 --- a/src/core/collection/artist.rs +++ b/src/core/collection/artist.rs @@ -54,7 +54,7 @@ impl Artist { } } - fn merge_album_with_lib_id( + fn merge_album_by_lib_id( primary_albums: &mut [Album], mut secondary_album: Album, ) -> Option { @@ -76,7 +76,7 @@ impl Artist { ) -> HashMap> { let mut secondary_without_id = HashMap::>::new(); for secondary_album in secondary_albums.drain(..) { - let unmerged = Artist::merge_album_with_lib_id(primary_albums, secondary_album); + let unmerged = Artist::merge_album_by_lib_id(primary_albums, secondary_album); if let Some(secondary_album) = unmerged { secondary_without_id .entry(secondary_album.meta.id.title.clone()) -- 2.47.1 From 14ab109197442a1c00513a6b195afdbfa6f0bfbd Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 2 Jan 2025 15:24:45 +0100 Subject: [PATCH 14/16] Prefer into_iter over drain --- src/core/collection/artist.rs | 8 ++++---- src/core/collection/merge.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/collection/artist.rs b/src/core/collection/artist.rs index 1ab01b1..40b395c 100644 --- a/src/core/collection/artist.rs +++ b/src/core/collection/artist.rs @@ -72,10 +72,10 @@ impl Artist { fn merge_albums_by_lib_id( primary_albums: &mut [Album], - mut secondary_albums: Vec, + secondary_albums: Vec, ) -> HashMap> { let mut secondary_without_id = HashMap::>::new(); - for secondary_album in secondary_albums.drain(..) { + for secondary_album in secondary_albums.into_iter() { let unmerged = Artist::merge_album_by_lib_id(primary_albums, secondary_album); if let Some(secondary_album) = unmerged { secondary_without_id @@ -89,9 +89,9 @@ impl Artist { fn merge_albums_by_title( primary_albums: &mut Vec, - mut secondary_without_id: HashMap>, + secondary_without_id: HashMap>, ) { - for (title, mut secondary_albums) in secondary_without_id.drain() { + for (title, mut secondary_albums) in secondary_without_id.into_iter() { let mut iter = primary_albums.iter_mut(); match iter.find(|album| album.meta.id.title == title) { Some(ref mut primary_album) => { diff --git a/src/core/collection/merge.rs b/src/core/collection/merge.rs index ebfed09..42d833a 100644 --- a/src/core/collection/merge.rs +++ b/src/core/collection/merge.rs @@ -23,8 +23,8 @@ impl Merge for Vec { } impl Merge for HashMap> { - fn merge_in_place(&mut self, mut other: Self) { - for (other_key, other_value) in other.drain() { + fn merge_in_place(&mut self, other: Self) { + for (other_key, other_value) in other.into_iter() { if let Some(ref mut value) = self.get_mut(&other_key) { value.merge_in_place(other_value) } else { -- 2.47.1 From fa5d8f84f9a8033af3f189c31cf74e64e43f3b6c Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 2 Jan 2025 15:40:02 +0100 Subject: [PATCH 15/16] Try unvendoring external --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b1f76c8 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ + src/external/** linguist-vendored=false -- 2.47.1 From f66e62f3747a983050e061e7b9c2153ab8d407f6 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Thu, 2 Jan 2025 15:43:14 +0100 Subject: [PATCH 16/16] Remove some whitespace --- src/core/collection/artist.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/collection/artist.rs b/src/core/collection/artist.rs index 40b395c..8851470 100644 --- a/src/core/collection/artist.rs +++ b/src/core/collection/artist.rs @@ -123,7 +123,6 @@ impl Merge for Artist { let other_without_id = Artist::merge_albums_by_lib_id(&mut self.albums, other.albums); Artist::merge_albums_by_title(&mut self.albums, other_without_id); - self.albums.sort_unstable(); } } -- 2.47.1