1
use serde::{Deserialize, Serialize};
2

            
3
use crate::{
4
    commands::{CommandRequest, CommandResponse, RequestParserError, ResponseParserError},
5
    filter::Filter,
6
    request_tokenizer::RequestTokenizer,
7
    response_tokenizer::ResponseAttributes,
8
    types::{DbSelectionPrintResponse, DbSongInfo, Sort, WindowRange},
9
};
10

            
11
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
12
pub struct FindRequest {
13
    filter: Filter,
14
    sort: Option<Sort>,
15
    window: Option<WindowRange>,
16
}
17

            
18
impl FindRequest {
19
    pub fn new(filter: Filter, sort: Option<Sort>, window: Option<WindowRange>) -> Self {
20
        Self {
21
            filter,
22
            sort,
23
            window,
24
        }
25
    }
26
}
27

            
28
impl CommandRequest for FindRequest {
29
    type Response = FindResponse;
30

            
31
    const COMMAND: &'static str = "find";
32
    const MIN_ARGS: u32 = 1;
33
    const MAX_ARGS: Option<u32> = Some(3);
34

            
35
    fn serialize(&self) -> String {
36
        let mut cmd = format!("{} {}", Self::COMMAND, self.filter);
37
        if let Some(sort) = &self.sort {
38
            cmd.push_str(&format!(" sort {}", sort));
39
        }
40
        if let Some(window) = &self.window {
41
            cmd.push_str(&format!(" window {}", window));
42
        }
43
        cmd.push('\n');
44
        cmd
45
    }
46

            
47
    fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
48
        let filter = match parts.next() {
49
            Some(f) => {
50
                Filter::parse(f).map_err(|_| RequestParserError::SyntaxError(1, f.to_owned()))?
51
            }
52
            None => return Err(Self::missing_arguments_error(0)),
53
        };
54

            
55
        let mut argument_index_counter = 0;
56
        let mut sort_or_window = parts.next();
57
        let mut sort = None;
58
        if let Some("sort") = sort_or_window {
59
            argument_index_counter += 1;
60
            let s = parts
61
                .next()
62
                .ok_or(RequestParserError::MissingKeywordValue {
63
                    keyword: "sort",
64
                    argument_index: argument_index_counter,
65
                })?;
66
            sort = Some(
67
                s.parse()
68
                    .map_err(|_| RequestParserError::SubtypeParserError {
69
                        argument_index: argument_index_counter,
70
                        expected_type: "Sort",
71
                        raw_input: s.to_string(),
72
                    })?,
73
            );
74
            sort_or_window = parts.next();
75
        }
76

            
77
        let mut window = None;
78
        if let Some("window") = sort_or_window {
79
            argument_index_counter += 1;
80
            let w = parts
81
                .next()
82
                .ok_or(RequestParserError::MissingKeywordValue {
83
                    keyword: "window",
84
                    argument_index: argument_index_counter,
85
                })?;
86
            window = Some(
87
                w.parse()
88
                    .map_err(|_| RequestParserError::SubtypeParserError {
89
                        argument_index: argument_index_counter,
90
                        expected_type: "WindowRange",
91
                        raw_input: w.to_string(),
92
                    })?,
93
            );
94
        }
95

            
96
        Self::throw_if_too_many_arguments(parts)?;
97

            
98
        Ok(FindRequest {
99
            filter,
100
            sort,
101
            window,
102
        })
103
    }
104
}
105

            
106
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
107
pub struct FindResponse(Vec<DbSongInfo>);
108

            
109
impl FindResponse {
110
    pub fn new(items: Vec<DbSongInfo>) -> Self {
111
        FindResponse(items)
112
    }
113
}
114

            
115
impl CommandResponse for FindResponse {
116
    type Request = FindRequest;
117

            
118
    fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
119
        DbSelectionPrintResponse::parse(parts)?
120
            .into_iter()
121
            .map(|i| match i {
122
                DbSelectionPrintResponse::Song(db_song_info) => Ok(db_song_info),
123
                DbSelectionPrintResponse::Directory(_db_directory_info) => Err(
124
                    ResponseParserError::UnexpectedProperty("directory".to_string()),
125
                ),
126
                DbSelectionPrintResponse::Playlist(_db_playlist_info) => Err(
127
                    ResponseParserError::UnexpectedProperty("playlist".to_string()),
128
                ),
129
            })
130
            .collect::<Result<Vec<DbSongInfo>, ResponseParserError>>()
131
            .map(FindResponse)
132
    }
133

            
134
    fn serialize(&self) -> Vec<u8> {
135
        unimplemented!("response serialization is not yet implemented for FindResponse")
136
    }
137
}