commands: implement all database selection responses
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
DbSelectionPrintResponse, DbSongInfo,
|
||||
commands::{Command, RequestParserError, ResponseParserError},
|
||||
common::types::{Sort, WindowRange},
|
||||
filter::Filter,
|
||||
@@ -18,7 +19,7 @@ pub struct FindRequest {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct FindResponse {}
|
||||
pub struct FindResponse(Vec<DbSongInfo>);
|
||||
|
||||
impl Command for Find {
|
||||
type Request = FindRequest;
|
||||
@@ -76,6 +77,18 @@ impl Command for Find {
|
||||
fn parse_response(
|
||||
parts: ResponseAttributes<'_>,
|
||||
) -> Result<Self::Response, ResponseParserError<'_>> {
|
||||
unimplemented!()
|
||||
DbSelectionPrintResponse::parse(parts)?
|
||||
.into_iter()
|
||||
.map(|i| match i {
|
||||
DbSelectionPrintResponse::Song(db_song_info) => Ok(db_song_info),
|
||||
DbSelectionPrintResponse::Directory(_db_directory_info) => {
|
||||
Err(ResponseParserError::UnexpectedProperty("directory"))
|
||||
}
|
||||
DbSelectionPrintResponse::Playlist(_db_playlist_info) => {
|
||||
Err(ResponseParserError::UnexpectedProperty("playlist"))
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<DbSongInfo>, ResponseParserError<'_>>>()
|
||||
.map(FindResponse)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::{
|
||||
DbSelectionPrintResponse,
|
||||
commands::{Command, RequestParserError, ResponseParserError},
|
||||
common::types::Uri,
|
||||
request_tokenizer::RequestTokenizer,
|
||||
@@ -8,7 +9,7 @@ use crate::{
|
||||
pub struct ListAll;
|
||||
|
||||
// TODO: This is supposed to be a tree-like structure, with directories containing files and playlists
|
||||
pub type ListAllResponse = Vec<String>;
|
||||
pub type ListAllResponse = Vec<DbSelectionPrintResponse>;
|
||||
|
||||
impl Command for ListAll {
|
||||
type Request = Option<Uri>;
|
||||
@@ -40,6 +41,133 @@ impl Command for ListAll {
|
||||
fn parse_response(
|
||||
parts: ResponseAttributes<'_>,
|
||||
) -> Result<Self::Response, ResponseParserError<'_>> {
|
||||
unimplemented!()
|
||||
|
||||
|
||||
DbSelectionPrintResponse::parse(parts)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::{DbDirectoryInfo, DbPlaylistInfo, DbSongInfo};
|
||||
|
||||
use super::*;
|
||||
|
||||
use indoc::indoc;
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn test_parse_response() {
|
||||
let response = indoc! {"
|
||||
directory: albums
|
||||
directory: albums/a
|
||||
file: albums/a/song1.mp3
|
||||
file: albums/a/song2.mp3
|
||||
file: albums/a/song3.mp3
|
||||
playlist: albums/a/album a.m3u8
|
||||
directory: albums/b
|
||||
file: albums/b/song1.mp3
|
||||
file: albums/b/song2.mp3
|
||||
file: albums/b/song3.mp3
|
||||
playlist: albums/b/album b.m3u8
|
||||
OK
|
||||
"};
|
||||
|
||||
let result = ListAll::parse_raw_response(response);
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok(vec![
|
||||
DbSelectionPrintResponse::Directory(DbDirectoryInfo {
|
||||
directory: PathBuf::from("albums"),
|
||||
last_modified: None
|
||||
}),
|
||||
DbSelectionPrintResponse::Directory(DbDirectoryInfo {
|
||||
directory: PathBuf::from("albums/a"),
|
||||
last_modified: None
|
||||
}),
|
||||
DbSelectionPrintResponse::Song(DbSongInfo {
|
||||
file: PathBuf::from("albums/a/song1.mp3"),
|
||||
range: None,
|
||||
last_modified: None,
|
||||
added: None,
|
||||
format: None,
|
||||
tags: vec![],
|
||||
time: None,
|
||||
duration: None,
|
||||
playlist: None
|
||||
}),
|
||||
DbSelectionPrintResponse::Song(DbSongInfo {
|
||||
file: PathBuf::from("albums/a/song2.mp3"),
|
||||
range: None,
|
||||
last_modified: None,
|
||||
added: None,
|
||||
format: None,
|
||||
tags: vec![],
|
||||
time: None,
|
||||
duration: None,
|
||||
playlist: None
|
||||
}),
|
||||
DbSelectionPrintResponse::Song(DbSongInfo {
|
||||
file: PathBuf::from("albums/a/song3.mp3"),
|
||||
range: None,
|
||||
last_modified: None,
|
||||
added: None,
|
||||
format: None,
|
||||
tags: vec![],
|
||||
time: None,
|
||||
duration: None,
|
||||
playlist: None
|
||||
}),
|
||||
DbSelectionPrintResponse::Playlist(DbPlaylistInfo {
|
||||
playlist: PathBuf::from("albums/a/album a.m3u8"),
|
||||
last_modified: None
|
||||
}),
|
||||
DbSelectionPrintResponse::Directory(DbDirectoryInfo {
|
||||
directory: PathBuf::from("albums/b"),
|
||||
last_modified: None
|
||||
}),
|
||||
DbSelectionPrintResponse::Song(DbSongInfo {
|
||||
file: PathBuf::from("albums/b/song1.mp3"),
|
||||
range: None,
|
||||
last_modified: None,
|
||||
added: None,
|
||||
format: None,
|
||||
tags: vec![],
|
||||
time: None,
|
||||
duration: None,
|
||||
playlist: None
|
||||
}),
|
||||
DbSelectionPrintResponse::Song(DbSongInfo {
|
||||
file: PathBuf::from("albums/b/song2.mp3"),
|
||||
range: None,
|
||||
last_modified: None,
|
||||
added: None,
|
||||
format: None,
|
||||
tags: vec![],
|
||||
time: None,
|
||||
duration: None,
|
||||
playlist: None
|
||||
}),
|
||||
DbSelectionPrintResponse::Song(DbSongInfo {
|
||||
file: PathBuf::from("albums/b/song3.mp3"),
|
||||
range: None,
|
||||
last_modified: None,
|
||||
added: None,
|
||||
format: None,
|
||||
tags: vec![],
|
||||
time: None,
|
||||
duration: None,
|
||||
playlist: None
|
||||
}),
|
||||
DbSelectionPrintResponse::Playlist(DbPlaylistInfo {
|
||||
playlist: PathBuf::from("albums/b/album b.m3u8"),
|
||||
last_modified: None
|
||||
})
|
||||
])
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::{
|
||||
DbSelectionPrintResponse,
|
||||
commands::{Command, RequestParserError, ResponseParserError},
|
||||
common::types::Uri,
|
||||
request_tokenizer::RequestTokenizer,
|
||||
@@ -7,9 +8,7 @@ use crate::{
|
||||
|
||||
pub struct ListAllInfo;
|
||||
|
||||
// TODO: This is supposed to be a tree-like structure, with directories containing files and playlists
|
||||
// in addition to the metadata of each entry
|
||||
pub type ListAllInfoResponse = Vec<String>;
|
||||
pub type ListAllInfoResponse = Vec<DbSelectionPrintResponse>;
|
||||
|
||||
impl Command for ListAllInfo {
|
||||
type Request = Option<Uri>;
|
||||
@@ -41,6 +40,90 @@ impl Command for ListAllInfo {
|
||||
fn parse_response(
|
||||
parts: ResponseAttributes<'_>,
|
||||
) -> Result<Self::Response, ResponseParserError<'_>> {
|
||||
unimplemented!()
|
||||
|
||||
|
||||
DbSelectionPrintResponse::parse(parts)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::{DbDirectoryInfo, DbPlaylistInfo, DbSongInfo, Tag};
|
||||
|
||||
use super::*;
|
||||
|
||||
use indoc::indoc;
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn test_parse_response() {
|
||||
let response = indoc! {"
|
||||
directory: albums
|
||||
Last-Modified: 2024-10-01T10:00:00Z
|
||||
directory: albums/a
|
||||
Last-Modified: 2024-10-01T10:00:00Z
|
||||
file: albums/a/song1.mp3
|
||||
Last-Modified: 2022-12-31T09:00:00Z
|
||||
Added: 2021-12-31T09:00:00Z
|
||||
Format: 44100:16:2
|
||||
Title: Song A
|
||||
Artist: Artist A
|
||||
Album: Album A
|
||||
AlbumArtist: Artist A
|
||||
Composer: Artist A
|
||||
Genre: Pop
|
||||
Track: 1
|
||||
Disc: 1
|
||||
Date: 2020-01-01
|
||||
Time: 360
|
||||
duration: 360.123
|
||||
playlist: albums/a/album a.m3u8
|
||||
Last-Modified: 2022-12-31T09:00:00Z
|
||||
OK
|
||||
"};
|
||||
|
||||
let result = ListAllInfo::parse_raw_response(response);
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok(vec![
|
||||
DbSelectionPrintResponse::Directory(DbDirectoryInfo {
|
||||
directory: PathBuf::from("albums"),
|
||||
last_modified: Some("2024-10-01T10:00:00Z".to_string()),
|
||||
}),
|
||||
DbSelectionPrintResponse::Directory(DbDirectoryInfo {
|
||||
directory: PathBuf::from("albums/a"),
|
||||
last_modified: Some("2024-10-01T10:00:00Z".to_string()),
|
||||
}),
|
||||
DbSelectionPrintResponse::Song(DbSongInfo {
|
||||
file: PathBuf::from("albums/a/song1.mp3"),
|
||||
range: None,
|
||||
last_modified: Some("2022-12-31T09:00:00Z".to_string()),
|
||||
added: Some("2021-12-31T09:00:00Z".to_string()),
|
||||
format: Some("44100:16:2".to_string()),
|
||||
tags: vec![
|
||||
Tag::Album("Album A".to_string()),
|
||||
Tag::AlbumArtist("Artist A".to_string()),
|
||||
Tag::Artist("Artist A".to_string()),
|
||||
Tag::Composer("Artist A".to_string()),
|
||||
Tag::Date("2020-01-01".to_string()),
|
||||
Tag::Disc("1".to_string()),
|
||||
Tag::Genre("Pop".to_string()),
|
||||
Tag::Title("Song A".to_string()),
|
||||
Tag::Track("1".to_string()),
|
||||
],
|
||||
time: Some(360),
|
||||
duration: Some(360.123),
|
||||
playlist: None,
|
||||
}),
|
||||
DbSelectionPrintResponse::Playlist(DbPlaylistInfo {
|
||||
playlist: PathBuf::from("albums/a/album a.m3u8"),
|
||||
last_modified: Some("2022-12-31T09:00:00Z".to_string())
|
||||
})
|
||||
]),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::{
|
||||
DbDirectoryInfo, DbSelectionPrintResponse,
|
||||
commands::{Command, RequestParserError, ResponseParserError},
|
||||
common::types::Uri,
|
||||
request_tokenizer::RequestTokenizer,
|
||||
@@ -8,7 +9,7 @@ use crate::{
|
||||
pub struct ListFiles;
|
||||
|
||||
// TODO: fix this type
|
||||
pub type ListFilesResponse = Vec<String>;
|
||||
pub type ListFilesResponse = Vec<DbDirectoryInfo>;
|
||||
|
||||
impl Command for ListFiles {
|
||||
type Request = Option<Uri>;
|
||||
@@ -40,6 +41,65 @@ impl Command for ListFiles {
|
||||
fn parse_response(
|
||||
parts: ResponseAttributes<'_>,
|
||||
) -> Result<Self::Response, ResponseParserError<'_>> {
|
||||
unimplemented!()
|
||||
|
||||
|
||||
// TODO: debug assert only toplevel dirs
|
||||
|
||||
DbSelectionPrintResponse::parse(parts)?
|
||||
.into_iter()
|
||||
.map(|i| match i {
|
||||
DbSelectionPrintResponse::Directory(db_directory_info) => Ok(db_directory_info),
|
||||
DbSelectionPrintResponse::Song(_db_song_info) => {
|
||||
Err(ResponseParserError::UnexpectedProperty("file"))
|
||||
}
|
||||
DbSelectionPrintResponse::Playlist(_db_playlist_info) => {
|
||||
Err(ResponseParserError::UnexpectedProperty("playlist"))
|
||||
}
|
||||
})
|
||||
.collect::<Result<Self::Response, ResponseParserError<'_>>>()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::*;
|
||||
|
||||
use indoc::indoc;
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn test_parse_response() {
|
||||
let response = indoc! {"
|
||||
directory: albums
|
||||
Last-Modified: 2024-10-01T10:00:00Z
|
||||
directory: playlists
|
||||
Last-Modified: 2023-10-01T10:00:00Z
|
||||
directory: Some Other Music
|
||||
Last-Modified: 2022-10-01T10:00:00Z
|
||||
OK
|
||||
"};
|
||||
|
||||
let result = ListFiles::parse_raw_response(response);
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok(vec![
|
||||
DbDirectoryInfo {
|
||||
directory: PathBuf::from("albums"),
|
||||
last_modified: Some("2024-10-01T10:00:00Z".to_string()),
|
||||
},
|
||||
DbDirectoryInfo {
|
||||
directory: PathBuf::from("playlists"),
|
||||
last_modified: Some("2023-10-01T10:00:00Z".to_string()),
|
||||
},
|
||||
DbDirectoryInfo {
|
||||
directory: PathBuf::from("Some Other Music"),
|
||||
last_modified: Some("2022-10-01T10:00:00Z".to_string()),
|
||||
}
|
||||
])
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,15 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
DbSelectionPrintResponse,
|
||||
commands::{Command, RequestParserError, ResponseParserError},
|
||||
common::types::Uri,
|
||||
request_tokenizer::RequestTokenizer,
|
||||
response_tokenizer::{ResponseAttributes, expect_property_type},
|
||||
response_tokenizer::ResponseAttributes,
|
||||
};
|
||||
|
||||
pub struct LsInfo;
|
||||
|
||||
pub type LsInfoResponse = Vec<LsInfoResponseEntry>;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct LsInfoResponseEntry {
|
||||
playlist: String,
|
||||
last_modified: Option<String>,
|
||||
}
|
||||
pub type LsInfoResponse = Vec<DbSelectionPrintResponse>;
|
||||
|
||||
impl Command for LsInfo {
|
||||
type Request = Option<Uri>;
|
||||
@@ -46,30 +40,70 @@ impl Command for LsInfo {
|
||||
fn parse_response(
|
||||
parts: ResponseAttributes<'_>,
|
||||
) -> Result<Self::Response, ResponseParserError<'_>> {
|
||||
let parts: Vec<_> = parts.into_vec()?;
|
||||
let mut playlists = Vec::new();
|
||||
|
||||
|
||||
for (key, value) in parts {
|
||||
match key {
|
||||
"playlist" => {
|
||||
playlists.push(LsInfoResponseEntry {
|
||||
playlist: expect_property_type!(Some(value), "playlist", Text).to_string(),
|
||||
last_modified: None,
|
||||
});
|
||||
}
|
||||
"Last-Modified" => {
|
||||
if let Some(last) = playlists.last_mut() {
|
||||
last.last_modified = Some(
|
||||
expect_property_type!(Some(value), "Last-Modified", Text).to_string(),
|
||||
);
|
||||
} else {
|
||||
return Err(ResponseParserError::UnexpectedProperty("Last-Modified"));
|
||||
}
|
||||
}
|
||||
_ => return Err(ResponseParserError::UnexpectedProperty(key)),
|
||||
}
|
||||
}
|
||||
// TODO: debug_assert no song variants
|
||||
// debug_assert!(
|
||||
// result.iter().
|
||||
|
||||
Ok(playlists)
|
||||
DbSelectionPrintResponse::parse(parts)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::{DbDirectoryInfo, DbPlaylistInfo};
|
||||
|
||||
use super::*;
|
||||
|
||||
use indoc::indoc;
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn test_parse_response() {
|
||||
let response = indoc! {"
|
||||
directory: albums
|
||||
Last-Modified: 2024-10-01T10:00:00Z
|
||||
directory: albums/a
|
||||
Last-Modified: 2024-10-01T10:00:00Z
|
||||
playlist: albums/a/album a.m3u8
|
||||
Last-Modified: 2022-12-31T09:00:00Z
|
||||
directory: albums/b
|
||||
Last-Modified: 2023-10-01T10:00:00Z
|
||||
playlist: albums/b/album b.m3u8
|
||||
Last-Modified: 2021-12-31T09:00:00Z
|
||||
OK
|
||||
"};
|
||||
|
||||
let result = LsInfo::parse_raw_response(response);
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok(vec![
|
||||
DbSelectionPrintResponse::Directory(DbDirectoryInfo {
|
||||
directory: PathBuf::from("albums"),
|
||||
last_modified: Some("2024-10-01T10:00:00Z".to_string())
|
||||
}),
|
||||
DbSelectionPrintResponse::Directory(DbDirectoryInfo {
|
||||
directory: PathBuf::from("albums/a"),
|
||||
last_modified: Some("2024-10-01T10:00:00Z".to_string())
|
||||
}),
|
||||
DbSelectionPrintResponse::Playlist(DbPlaylistInfo {
|
||||
playlist: PathBuf::from("albums/a/album a.m3u8"),
|
||||
last_modified: Some("2022-12-31T09:00:00Z".to_string())
|
||||
}),
|
||||
DbSelectionPrintResponse::Directory(DbDirectoryInfo {
|
||||
directory: PathBuf::from("albums/b"),
|
||||
last_modified: Some("2023-10-01T10:00:00Z".to_string())
|
||||
}),
|
||||
DbSelectionPrintResponse::Playlist(DbPlaylistInfo {
|
||||
playlist: PathBuf::from("albums/b/album b.m3u8"),
|
||||
last_modified: Some("2021-12-31T09:00:00Z".to_string())
|
||||
})
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
DbSelectionPrintResponse, DbSongInfo,
|
||||
commands::{Command, RequestParserError, ResponseParserError},
|
||||
common::types::{Sort, WindowRange},
|
||||
filter::Filter,
|
||||
@@ -18,7 +19,7 @@ pub struct SearchRequest {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct SearchResponse {}
|
||||
pub struct SearchResponse(Vec<DbSongInfo>);
|
||||
|
||||
impl Command for Search {
|
||||
type Request = SearchRequest;
|
||||
@@ -76,6 +77,18 @@ impl Command for Search {
|
||||
fn parse_response(
|
||||
parts: ResponseAttributes<'_>,
|
||||
) -> Result<Self::Response, ResponseParserError<'_>> {
|
||||
unimplemented!()
|
||||
DbSelectionPrintResponse::parse(parts)?
|
||||
.into_iter()
|
||||
.map(|i| match i {
|
||||
DbSelectionPrintResponse::Song(db_song_info) => Ok(db_song_info),
|
||||
DbSelectionPrintResponse::Directory(_db_directory_info) => {
|
||||
Err(ResponseParserError::UnexpectedProperty("directory"))
|
||||
}
|
||||
DbSelectionPrintResponse::Playlist(_db_playlist_info) => {
|
||||
Err(ResponseParserError::UnexpectedProperty("playlist"))
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<DbSongInfo>, ResponseParserError<'_>>>()
|
||||
.map(SearchResponse)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +114,5 @@ mod tests {
|
||||
},
|
||||
])
|
||||
);
|
||||
>>>>>>> a0f4105 (commands/listplaylists: implement)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user