lastfm_client/types/
artists.rs1use std::cmp::Ordering;
2use std::fmt;
3
4use crate::types::{BaseResponse, RankAttr, TrackImage};
5use serde::{Deserialize, Serialize};
6
7use crate::types::utils::{bool_from_str, u32_from_str};
8
9#[derive(Serialize, Deserialize, Debug, Clone)]
13#[non_exhaustive]
14pub struct TopArtist {
15 pub name: String,
17 pub mbid: String,
19 pub url: String,
21 #[serde(deserialize_with = "u32_from_str")]
23 pub playcount: u32,
24 #[serde(deserialize_with = "bool_from_str")]
26 pub streamable: bool,
27 pub image: Vec<TrackImage>,
29 #[serde(rename = "@attr")]
31 pub attr: RankAttr,
32}
33
34impl fmt::Display for TopArtist {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 write!(
37 f,
38 "#{} - {} ({} plays)",
39 self.attr.rank, self.name, self.playcount
40 )
41 }
42}
43
44impl PartialEq for TopArtist {
45 fn eq(&self, other: &Self) -> bool {
46 self.playcount == other.playcount
47 }
48}
49
50impl Eq for TopArtist {}
51
52impl PartialOrd for TopArtist {
53 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
54 Some(self.cmp(other))
55 }
56}
57
58impl Ord for TopArtist {
59 fn cmp(&self, other: &Self) -> Ordering {
60 self.playcount.cmp(&other.playcount)
61 }
62}
63
64#[cfg(feature = "sqlite")]
67impl crate::sqlite::SqliteExportable for TopArtist {
68 fn table_name() -> &'static str {
69 "top_artists"
70 }
71
72 fn create_table_sql() -> &'static str {
73 "CREATE TABLE IF NOT EXISTS top_artists (
74 id INTEGER PRIMARY KEY AUTOINCREMENT,
75 name TEXT NOT NULL,
76 mbid TEXT NOT NULL,
77 url TEXT NOT NULL,
78 playcount INTEGER NOT NULL,
79 rank INTEGER NOT NULL
80 )"
81 }
82
83 fn insert_sql() -> &'static str {
84 "INSERT INTO top_artists (name, mbid, url, playcount, rank)
85 VALUES (?1, ?2, ?3, ?4, ?5)"
86 }
87
88 fn bind_and_execute(&self, stmt: &mut rusqlite::Statement<'_>) -> rusqlite::Result<usize> {
89 let rank: u32 = self.attr.rank.parse().unwrap_or_default();
90 stmt.execute(rusqlite::params![
91 self.name,
92 self.mbid,
93 self.url,
94 self.playcount,
95 rank,
96 ])
97 }
98}
99
100#[cfg(feature = "sqlite")]
103impl crate::sqlite::SqliteLoadable for TopArtist {
104 fn select_sql() -> &'static str {
105 "SELECT name, mbid, url, playcount, rank
107 FROM top_artists
108 ORDER BY rank ASC"
109 }
110
111 fn from_row(row: &rusqlite::Row<'_>) -> rusqlite::Result<Self> {
112 Ok(Self {
113 name: row.get(0)?,
114 mbid: row.get(1)?,
115 url: row.get(2)?,
116 playcount: row.get(3)?,
117 attr: crate::types::RankAttr {
118 rank: row.get::<_, u32>(4)?.to_string(),
119 },
120 streamable: false,
122 image: vec![],
123 })
124 }
125}
126
127#[derive(Serialize, Deserialize, Debug, Clone)]
129#[non_exhaustive]
130pub struct TopArtists {
131 pub artist: Vec<TopArtist>,
133 #[serde(rename = "@attr")]
135 pub attr: BaseResponse,
136}
137
138#[derive(Serialize, Deserialize, Debug, Clone)]
140#[non_exhaustive]
141pub struct UserTopArtists {
142 pub topartists: TopArtists,
144}