am_api/resource/
mod.rs

1//! Apple music resources
2use am_api_proc_macro::Context;
3
4use serde::{Deserialize, Serialize};
5
6pub mod artwork;
7pub mod attributes;
8pub mod catalog;
9pub mod genre;
10pub mod history;
11pub mod library;
12pub mod personal_recommendation;
13pub mod rating;
14pub mod relationship;
15pub mod search;
16pub mod storefront;
17pub mod view;
18
19/// Apple music resource header
20#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq, Hash)]
21#[serde(rename_all = "camelCase", default)]
22pub struct ResourceHeader {
23    /// Identifier
24    pub id: String,
25    /// Relative location for the resource
26    pub href: String,
27}
28
29/// Trait for getting resource information
30pub trait ResourceInfo {
31    /// Get header
32    fn get_header(&self) -> &ResourceHeader;
33}
34
35/// Trait for getting resource data type
36pub(crate) trait ResourceType {
37    /// Get resource type
38    fn get_type(&self) -> &'static str;
39}
40
41macro_rules! resource {
42    ($($name:literal => $enum_name:ident : $data_type:path),*) => {
43        /// Apple music resource data
44        #[derive(Context, Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
45        #[serde(tag = "type")]
46        pub enum Resource {
47            $(
48                #[doc = $name]
49                #[serde(rename = $name)]
50                $enum_name {
51                    /// Data
52                    #[serde(flatten)]
53                    data: $data_type
54                }
55            ),*
56        }
57
58        impl ResourceInfo for Resource {
59            fn get_header(&self) -> &ResourceHeader {
60                match self {
61                    $(Self::$enum_name { data } => &data.header),*
62                }
63            }
64        }
65
66        impl ResourceType for Resource {
67            fn get_type(&self) -> &'static str {
68                match self {
69                    $(Self::$enum_name { .. } => $name),*
70                }
71            }
72        }
73
74        $(
75            impl From<$data_type> for Resource {
76                fn from(data: $data_type) -> Self {
77                    Self::$enum_name { data }
78                }
79            }
80        )*
81    }
82}
83
84resource! {
85    "activities" => Activity : catalog::activity::Activity,
86    "albums" => Album : catalog::album::Album,
87    "artists" => Artist : catalog::artist::Artist,
88    "apple-curators" => AppleCurator : catalog::curator::AppleCurator,
89    "curators" => Curator : catalog::curator::Curator,
90    "genres" => Genre : genre::Genre,
91    "music-videos" => MusicVideo : catalog::music_video::MusicVideo,
92    "personal-recommendation" => PersonalRecommendation : personal_recommendation::PersonalRecommendation,
93    "playlists" => Playlist : catalog::playlist::Playlist,
94    "ratings" => Rating : rating::Rating,
95    "record-labels" => RecordLabel : catalog::record_label::RecordLabel,
96    "songs" => Song : catalog::song::Song,
97    "stations" => Station : catalog::station::Station,
98    "station-genres" => StationGenre : catalog::station::StationGenre,
99    "library-albums" => LibraryAlbum : library::album::LibraryAlbum,
100    "library-artists" => LibraryArtist : library::artist::LibraryArtist,
101    "library-music-videos" => LibraryMusicVideo : library::music_video::LibraryMusicVideo,
102    "library-playlists" => LibraryPlaylist : library::playlist::LibraryPlaylist,
103    "library-playlist-folders" => LibraryPlaylistFolder : library::playlist::LibraryPlaylistFolder,
104    "library-songs" => LibrarySong : library::song::LibrarySong
105}
106
107/// Apple music response
108#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
109#[serde(rename_all = "camelCase")]
110pub struct ResourceResponse<R = Resource> {
111    /// Data
112    pub data: Vec<R>,
113}
114
115/// Apple music error response
116#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
117#[serde(rename_all = "camelCase")]
118pub struct ErrorResponse {
119    /// Error code
120    #[serde(default)]
121    pub code: Option<i32>,
122    /// Error message
123    #[serde(default)]
124    pub message: Option<String>,
125    /// Errors
126    #[serde(default)]
127    pub errors: Vec<MusicError>,
128}
129
130/// Apple music error
131#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, Hash)]
132#[serde(rename_all = "camelCase", default)]
133pub struct MusicError {
134    /// Error id
135    pub id: String,
136    /// Error title
137    pub title: String,
138    /// Error detail
139    pub detail: String,
140    /// Status
141    pub status: String,
142    /// Error code
143    pub code: String,
144}