use serde_json;
use ApiError;
#[derive(Debug, Deserialize)]
pub struct Response {
#[serde(rename = "subsonic-response")]
inner: InnerResponse,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct InnerResponse {
status: String,
version: String,
error: Option<ApiError>,
license: Option<serde_json::Value>,
music_folders: Option<serde_json::Value>,
indexes: Option<serde_json::Value>,
directory: Option<serde_json::Value>,
genres: Option<serde_json::Value>,
artists: Option<serde_json::Value>,
artist: Option<serde_json::Value>,
albums: Option<serde_json::Value>,
album: Option<serde_json::Value>,
song: Option<serde_json::Value>,
videos: Option<serde_json::Value>,
video_info: Option<serde_json::Value>,
artist_info: Option<serde_json::Value>,
artist_info2: Option<serde_json::Value>,
album_info: Option<serde_json::Value>,
similar_songs: Option<serde_json::Value>,
similar_songs2: Option<serde_json::Value>,
top_songs: Option<serde_json::Value>,
album_list: Option<serde_json::Value>,
album_list2: Option<serde_json::Value>,
random_songs: Option<serde_json::Value>,
songs_by_genre: Option<serde_json::Value>,
now_playing: Option<serde_json::Value>,
starred: Option<serde_json::Value>,
starred2: Option<serde_json::Value>,
search_result: Option<serde_json::Value>,
search_result2: Option<serde_json::Value>,
search_result3: Option<serde_json::Value>,
playlists: Option<serde_json::Value>,
playlist: Option<serde_json::Value>,
lyrics: Option<serde_json::Value>,
shares: Option<serde_json::Value>,
podcasts: Option<serde_json::Value>,
newest_podcasts: Option<serde_json::Value>,
jukebox_status: Option<serde_json::Value>,
jukebox_playlist: Option<serde_json::Value>,
internet_radio_stations: Option<serde_json::Value>,
chat_messages: Option<serde_json::Value>,
user: Option<serde_json::Value>,
users: Option<serde_json::Value>,
bookmarks: Option<serde_json::Value>,
play_queue: Option<serde_json::Value>,
scan_status: Option<serde_json::Value>,
}
impl Response {
pub fn into_value(self) -> Option<serde_json::Value> {
macro_rules! choose {
( $($f:ident),* ) => ({ $(
if let Some(v) = self.inner.$f {
return Some(v)
}
)* })
}
if self.inner.error.is_some() {
return None;
}
choose!(
album,
album_info,
album_list,
album_list2,
albums,
artist,
artist_info,
artist_info2,
artists,
bookmarks,
chat_messages,
directory,
genres,
indexes,
internet_radio_stations,
jukebox_playlist,
jukebox_status,
license,
lyrics,
music_folders,
music_folders,
newest_podcasts,
now_playing,
play_queue,
playlist,
playlists,
podcasts,
random_songs,
scan_status,
search_result,
search_result2,
search_result3,
shares,
similar_songs,
similar_songs2,
song,
songs_by_genre,
starred,
starred2,
top_songs,
user,
users,
video_info,
videos
);
None
}
pub fn into_error(self) -> Option<ApiError> {
self.inner.error
}
pub fn is_ok(&self) -> bool {
self.inner.error.is_none()
}
pub fn is_err(&self) -> bool {
!self.is_ok()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn into_err_result() {
let fail = r#"{"subsonic-response": {
"status": "failed",
"version": "1.14.0",
"error": {
"code": 70,
"message": "Requested resource not found"
}
}}"#;
let fail = serde_json::from_str::<Response>(fail).unwrap();
assert!(fail.into_error().is_some());
let success = r#"{"subsonic-response": {
"status": "ok",
"version": "1.14.0"
}}"#;
let success = serde_json::from_str::<Response>(success).unwrap();
assert!(success.into_error().is_none());
}
}