From 47f14a3fbe49f991336859d33b8d8142a509a65f Mon Sep 17 00:00:00 2001 From: Kubat <mael.martin31@gmail.com> Date: Thu, 26 Jan 2023 18:35:35 +0100 Subject: [PATCH] AMALIB: Add a way to override kara informations --- src/rust/amalib/src/db_cache.rs | 4 +- src/rust/amalib/src/db_kara.rs | 155 +++++++++++++++++++++++++++++ src/rust/amalib/src/db_objects.rs | 142 -------------------------- src/rust/amalib/src/db_playlist.rs | 56 +++++++++++ src/rust/amalib/src/db_tags.rs | 2 +- src/rust/amalib/src/lib.rs | 6 +- 6 files changed, 218 insertions(+), 147 deletions(-) create mode 100644 src/rust/amalib/src/db_kara.rs delete mode 100644 src/rust/amalib/src/db_objects.rs create mode 100644 src/rust/amalib/src/db_playlist.rs diff --git a/src/rust/amalib/src/db_cache.rs b/src/rust/amalib/src/db_cache.rs index 776c713b..755235fa 100644 --- a/src/rust/amalib/src/db_cache.rs +++ b/src/rust/amalib/src/db_cache.rs @@ -23,7 +23,7 @@ pub struct AmaDB { playlists: LruCache<SmallString, Playlist>, /// The list of overrides, indexed by the local id of the kara. - overrides: HashMap<i64, KaraOverride>, + overrides: HashMap<i64, KaraInfoOverride>, /// The conversion list for `local id <-> repo id`. Overrides are declared /// with the repo ids because it's the only thing that every client have in @@ -74,7 +74,7 @@ impl AmaDB { /// Add an override to the override list. If a previous override is present /// for the specified ID, we merge the new override into the previous one. /// If the kara is present in the cache, we generate the patched version. - pub fn add_kara_override(&mut self, _id: KaraId, _override: KaraOverride) { + pub fn add_kara_override(&mut self, _id: KaraId, _override: KaraInfoOverride) { todo!() } diff --git a/src/rust/amalib/src/db_kara.rs b/src/rust/amalib/src/db_kara.rs new file mode 100644 index 00000000..bda0b88c --- /dev/null +++ b/src/rust/amalib/src/db_kara.rs @@ -0,0 +1,155 @@ +//! Describes karas. + +use crate::*; + +/// Represent the possible types for a song. The custom field is here for +/// flexibility, we box it so it's not too big and because it won't be common. +#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +pub enum SongType { + OP, + ED, + IS, + MV, + OT, + Custom(Box<String>), +} + +/// Represent the possible origins for a song. The custom field is here for +/// flexibility, we box it so it's not too big and because it won't be common. +#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +#[serde(rename_all = "lowercase")] +pub enum SongOrigin { + Anime, + VN, + Game, + Music, + Autre, + Custom(Box<String>), +} + +/// Represent a global id for a kara, the pair (database, id). +#[derive(Debug, Deserialize, Serialize, Getters, CopyGetters)] +pub struct KaraId { + #[getset(get = "pub")] + repo: SmallString, + + #[getset(get_copy = "pub")] + id: i64, +} + +/// A list of informations about a kara. This is the data from lektor. When +/// queried we patch it with the overrides given by the user. +#[derive(Debug, Getters)] +#[getset(get = "pub")] +pub struct KaraInfo { + song_title: SmallString, + song_source: SmallString, + song_type: SongType, + song_origin: SongOrigin, + languages: HashSet<SmallString>, + kara_makers: HashSet<SmallString>, + + #[getset(skip)] + tags: SimpleTagSystem, +} + +impl From<(&str, i64)> for KaraId { + fn from((repo, id): (&str, i64)) -> Self { + let repo = repo.into(); + Self { repo, id } + } +} + +impl From<(SmallString, i64)> for KaraId { + fn from((repo, id): (SmallString, i64)) -> Self { + Self { repo, id } + } +} + +impl<'a> TaggedObject<'a> for KaraInfo { + type TK = <SimpleTagSystem as TaggedObject<'a>>::TK; + type TV = <SimpleTagSystem as TaggedObject<'a>>::TV; + type TKIter = <SimpleTagSystem as TaggedObject<'a>>::TKIter; + type TVIter = <SimpleTagSystem as TaggedObject<'a>>::TVIter; + + fn add_tag(&mut self, tag: Self::TK, value: Option<Self::TV>) -> bool { + self.tags.add_tag(tag, value) + } + + fn remove_tag<S1: AsRef<str>, S2: AsRef<str>>(&mut self, tag: S1, value: S2) -> bool { + self.tags.remove_tag(tag, value) + } + + fn drop_tag<S: AsRef<str>>(&mut self, tag: S) -> bool { + self.tags.drop_tag(tag) + } + + fn empty_tag<S: AsRef<str>>(&mut self, tag: S) -> bool { + self.tags.empty_tag(tag) + } + + fn clear_tags(&mut self) -> bool { + self.tags.clear_tags() + } + + fn tags<'b>(&'b self) -> Self::TKIter + where + 'b: 'a, + { + self.tags.tags() + } + + fn iter_tag<'b, S: AsRef<str>>(&'b self, tag: S) -> Option<Self::TVIter> + where + 'b: 'a, + { + self.tags.iter_tag(tag) + } +} + +/// Represent what we want to override in a kara. +#[derive(Debug, Clone, Deserialize, Serialize)] +pub enum KaraInfoOverride { + SongTitle(SmallString), + SongSource(SmallString), + SongType(SongType), + SongOrigin(SongOrigin), + + AddLanguage(SmallString), + RemoveLanguage(SmallString), + + AddKaraMaker(SmallString), + RemoveKaraMaker(SmallString), +} + +impl KaraInfo { + /// Patch the kara with a list of actions to do in the passed order. If the + /// kara information where patched, return true, otherwise return false. + pub fn patch_infos<I>(&mut self, overrides: I) -> bool + where + I: IntoIterator<Item = KaraInfoOverride>, + { + use KaraInfoOverride::*; + macro_rules! set_if_ne { + ($what: ident, $str: expr) => { + self.$what.ne(&$str).then(|| self.$what = $str).is_some() + }; + } + overrides + .into_iter() + .map(|patch| match patch { + SongTitle(title) => set_if_ne!(song_title, title), + SongSource(source) => set_if_ne!(song_source, source), + SongType(ty) => set_if_ne!(song_type, ty), + SongOrigin(origin) => set_if_ne!(song_origin, origin), + + AddLanguage(lang) => self.languages.insert(lang), + RemoveLanguage(lang) => self.languages.remove(&lang), + + AddKaraMaker(maker) => self.kara_makers.insert(maker), + RemoveKaraMaker(maker) => self.kara_makers.remove(&maker), + }) + .count() + != 0 + } +} diff --git a/src/rust/amalib/src/db_objects.rs b/src/rust/amalib/src/db_objects.rs deleted file mode 100644 index 5ec8f058..00000000 --- a/src/rust/amalib/src/db_objects.rs +++ /dev/null @@ -1,142 +0,0 @@ -//! Collection of structures to describe objects retrieved from the lektord -//! server. - -use crate::*; - -/// Represent a global id for a kara, the pair (database, id). -#[derive(Debug, Deserialize, Serialize, Getters, CopyGetters)] -pub struct KaraId { - #[getset(get = "pub")] - repo: SmallString, - - #[getset(get_copy = "pub")] - id: i64, -} - -/// Represent what we want to override in a kara. -#[derive(Debug, Deserialize, Serialize)] -pub struct KaraOverride {} - -/// A list of informations about a kara. This is the data from lektor. When -/// queried we patch it with the overrides given by the user. -#[derive(Debug, Getters)] -#[getset(get = "pub")] -pub struct KaraInfo { - song_title: SmallString, - song_source: SmallString, - song_type: SmallString, - song_origin: SmallString, - languages: Vec<SmallString>, - kara_makers: Vec<SmallString>, - - #[getset(skip)] - tags: SimpleTagSystem, -} - -#[allow(dead_code)] -#[derive(Debug, Getters)] -#[getset(get = "pub")] -pub struct Playlist { - name: SmallString, - ctime: i64, - creator: SmallString, - content: Vec<i64>, - - #[getset(skip)] - tags: SimpleTagSystem, -} - -impl From<(&str, i64)> for KaraId { - fn from((repo, id): (&str, i64)) -> Self { - let repo = repo.into(); - Self { repo, id } - } -} - -impl From<(SmallString, i64)> for KaraId { - fn from((repo, id): (SmallString, i64)) -> Self { - Self { repo, id } - } -} - -impl<'a> TaggedObject<'a> for Playlist { - type TK = <SimpleTagSystem as TaggedObject<'a>>::TK; - type TV = <SimpleTagSystem as TaggedObject<'a>>::TV; - type TKIter = <SimpleTagSystem as TaggedObject<'a>>::TKIter; - type TVIter = <SimpleTagSystem as TaggedObject<'a>>::TVIter; - - fn add_tag(&mut self, tag: Self::TK, value: Option<Self::TV>) -> bool { - self.tags.add_tag(tag, value) - } - - fn remove_tag<S1: AsRef<str>, S2: AsRef<str>>(&mut self, tag: S1, value: S2) -> bool { - self.tags.remove_tag(tag, value) - } - - fn drop_tag<S: AsRef<str>>(&mut self, tag: S) -> bool { - self.tags.drop_tag(tag) - } - - fn empty_tag<S: AsRef<str>>(&mut self, tag: S) -> bool { - self.tags.empty_tag(tag) - } - - fn clear_tags(&mut self) -> bool { - self.tags.clear_tags() - } - - fn tags<'b>(&'b self) -> Self::TKIter - where - 'b: 'a, - { - self.tags.tags() - } - - fn iter_tag<'b, S: AsRef<str>>(&'b self, tag: S) -> Option<Self::TVIter> - where - 'b: 'a, - { - self.tags.iter_tag(tag) - } -} - -impl<'a> TaggedObject<'a> for KaraInfo { - type TK = <SimpleTagSystem as TaggedObject<'a>>::TK; - type TV = <SimpleTagSystem as TaggedObject<'a>>::TV; - type TKIter = <SimpleTagSystem as TaggedObject<'a>>::TKIter; - type TVIter = <SimpleTagSystem as TaggedObject<'a>>::TVIter; - - fn add_tag(&mut self, tag: Self::TK, value: Option<Self::TV>) -> bool { - self.tags.add_tag(tag, value) - } - - fn remove_tag<S1: AsRef<str>, S2: AsRef<str>>(&mut self, tag: S1, value: S2) -> bool { - self.tags.remove_tag(tag, value) - } - - fn drop_tag<S: AsRef<str>>(&mut self, tag: S) -> bool { - self.tags.drop_tag(tag) - } - - fn empty_tag<S: AsRef<str>>(&mut self, tag: S) -> bool { - self.tags.empty_tag(tag) - } - - fn clear_tags(&mut self) -> bool { - self.tags.clear_tags() - } - - fn tags<'b>(&'b self) -> Self::TKIter - where - 'b: 'a, - { - self.tags.tags() - } - - fn iter_tag<'b, S: AsRef<str>>(&'b self, tag: S) -> Option<Self::TVIter> - where - 'b: 'a, - { - self.tags.iter_tag(tag) - } -} diff --git a/src/rust/amalib/src/db_playlist.rs b/src/rust/amalib/src/db_playlist.rs new file mode 100644 index 00000000..c50d6fcc --- /dev/null +++ b/src/rust/amalib/src/db_playlist.rs @@ -0,0 +1,56 @@ +//! Describes playlists. + +use crate::*; + +#[derive(Debug, Getters)] +#[getset(get = "pub")] +pub struct Playlist { + name: SmallString, + ctime: i64, + creator: SmallString, + content: Vec<i64>, + + #[getset(skip)] + tags: SimpleTagSystem, +} + +impl<'a> TaggedObject<'a> for Playlist { + type TK = <SimpleTagSystem as TaggedObject<'a>>::TK; + type TV = <SimpleTagSystem as TaggedObject<'a>>::TV; + type TKIter = <SimpleTagSystem as TaggedObject<'a>>::TKIter; + type TVIter = <SimpleTagSystem as TaggedObject<'a>>::TVIter; + + fn add_tag(&mut self, tag: Self::TK, value: Option<Self::TV>) -> bool { + self.tags.add_tag(tag, value) + } + + fn remove_tag<S1: AsRef<str>, S2: AsRef<str>>(&mut self, tag: S1, value: S2) -> bool { + self.tags.remove_tag(tag, value) + } + + fn drop_tag<S: AsRef<str>>(&mut self, tag: S) -> bool { + self.tags.drop_tag(tag) + } + + fn empty_tag<S: AsRef<str>>(&mut self, tag: S) -> bool { + self.tags.empty_tag(tag) + } + + fn clear_tags(&mut self) -> bool { + self.tags.clear_tags() + } + + fn tags<'b>(&'b self) -> Self::TKIter + where + 'b: 'a, + { + self.tags.tags() + } + + fn iter_tag<'b, S: AsRef<str>>(&'b self, tag: S) -> Option<Self::TVIter> + where + 'b: 'a, + { + self.tags.iter_tag(tag) + } +} diff --git a/src/rust/amalib/src/db_tags.rs b/src/rust/amalib/src/db_tags.rs index 0433d4c9..c04e6d47 100644 --- a/src/rust/amalib/src/db_tags.rs +++ b/src/rust/amalib/src/db_tags.rs @@ -66,7 +66,7 @@ pub trait TaggedObject<'a> { /// Patch the tagged object with a list of actions to do in the passed /// order. If the object was patched, return true, otherwise return false. - fn patch<'b, I>(&'b mut self, overrides: I) -> bool + fn patch_tags<'b, I>(&'b mut self, overrides: I) -> bool where I: IntoIterator<Item = TagOverride<Self::TK, Self::TV>>, 'a: 'b, diff --git a/src/rust/amalib/src/lib.rs b/src/rust/amalib/src/lib.rs index d02b0fd3..22338b5c 100644 --- a/src/rust/amalib/src/lib.rs +++ b/src/rust/amalib/src/lib.rs @@ -7,7 +7,8 @@ mod connexion; mod constants; mod db_cache; -mod db_objects; +mod db_kara; +mod db_playlist; mod db_tags; mod query; mod response; @@ -15,7 +16,8 @@ mod uri; pub use connexion::*; pub use db_cache::*; -pub use db_objects::*; +pub use db_kara::*; +pub use db_playlist::*; pub use db_tags::*; pub use query::*; pub use response::*; -- GitLab