diff --git a/src/commands/stored_playlists/listplaylists.rs b/src/commands/stored_playlists/listplaylists.rs index a558a6d..1f98400 100644 --- a/src/commands/stored_playlists/listplaylists.rs +++ b/src/commands/stored_playlists/listplaylists.rs @@ -1,14 +1,26 @@ +use serde::{Deserialize, Serialize}; + use crate::{ + PlaylistName, commands::{Command, RequestParserError, ResponseParserError}, request_tokenizer::RequestTokenizer, - response_tokenizer::ResponseAttributes, + response_tokenizer::{ResponseAttributes, get_next_and_parse_property, get_next_property}, }; pub struct ListPlaylists; +pub type ListPlaylistsResponse = Vec; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ListPlaylistsResponseEntry { + pub playlist: PlaylistName, + // TODO: parse this + pub last_modified: Option, +} + impl Command for ListPlaylists { type Request = (); - type Response = (); + type Response = ListPlaylistsResponse; const COMMAND: &'static str = "listplaylists"; fn serialize_request(&self, _request: Self::Request) -> String { @@ -23,6 +35,85 @@ impl Command for ListPlaylists { fn parse_response( parts: ResponseAttributes<'_>, ) -> Result> { - unimplemented!() + let mut parts = parts.into_lazy_vec().into_iter().peekable(); + // TODO: count instances of 'playlist' to preallocate + let mut result = Vec::new(); + + while parts.peek().is_some() { + let (key, playlist) = get_next_and_parse_property!(parts, Text); + debug_assert!(key == "playlist"); + let last_modified = if let Some(Ok(("Last-Modified", _))) = parts.peek() { + let (_key, last_modified) = get_next_property!(parts, Text); + Some(last_modified.to_string()) + } else { + None + }; + + result.push(ListPlaylistsResponseEntry { + playlist, + last_modified, + }); + } + + Ok(result) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use indoc::indoc; + + use pretty_assertions::assert_eq; + + #[test] + fn test_parse_response() { + let response = indoc! {" + playlist: My Playlist 1 + Last-Modified: 2024-01-01T12:00:00Z + playlist: My Playlist 2 + Last-Modified: 2024-02-01T12:00:00Z + playlist: My Playlist 3 + Last-Modified: 2024-03-01T12:00:00Z + playlist: My Playlist 4 + playlist: My Playlist 5 + playlist: My Playlist 6 + Last-Modified: 2024-06-01T12:00:00Z + OK + "}; + + let result = ListPlaylists::parse_raw_response(response); + + assert_eq!( + result, + Ok(vec![ + ListPlaylistsResponseEntry { + playlist: "My Playlist 1".into(), + last_modified: Some("2024-01-01T12:00:00Z".to_string()), + }, + ListPlaylistsResponseEntry { + playlist: "My Playlist 2".into(), + last_modified: Some("2024-02-01T12:00:00Z".to_string()), + }, + ListPlaylistsResponseEntry { + playlist: "My Playlist 3".into(), + last_modified: Some("2024-03-01T12:00:00Z".to_string()), + }, + ListPlaylistsResponseEntry { + playlist: "My Playlist 4".into(), + last_modified: None, + }, + ListPlaylistsResponseEntry { + playlist: "My Playlist 5".into(), + last_modified: None, + }, + ListPlaylistsResponseEntry { + playlist: "My Playlist 6".into(), + last_modified: Some("2024-06-01T12:00:00Z".to_string()), + }, + ]) + ); +>>>>>>> a0f4105 (commands/listplaylists: implement) } }