1
use std::collections::HashMap;
2

            
3
use serde::{Deserialize, Serialize};
4

            
5
use crate::{
6
    commands::{CommandRequest, CommandResponse, RequestParserError, ResponseParserError},
7
    filter::Filter,
8
    request_tokenizer::RequestTokenizer,
9
    response_tokenizer::{ResponseAttributes, get_and_parse_property},
10
    types::GroupType,
11
};
12

            
13
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14
pub struct CountRequest {
15
    filter: Filter,
16
    group: Option<GroupType>,
17
}
18

            
19
impl CountRequest {
20
    pub fn new(filter: Filter, group: Option<GroupType>) -> Self {
21
        CountRequest { filter, group }
22
    }
23
}
24

            
25
impl CommandRequest for CountRequest {
26
    type Response = CountResponse;
27

            
28
    const COMMAND: &'static str = "count";
29
    const MIN_ARGS: u32 = 1;
30
    const MAX_ARGS: Option<u32> = Some(2);
31

            
32
    fn serialize(&self) -> String {
33
        let mut cmd = format!("{} {}", Self::COMMAND, self.filter);
34
        if let Some(group) = self.group.as_ref() {
35
            cmd.push_str(&format!(" group {}", group));
36
        }
37
        cmd.push('\n');
38
        cmd
39
    }
40

            
41
    fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
42
        let filter = match parts.next() {
43
            Some(f) => {
44
                Filter::parse(f).map_err(|_| RequestParserError::SyntaxError(1, f.to_owned()))?
45
            }
46
            None => return Err(Self::missing_arguments_error(0)),
47
        };
48

            
49
        let group = if let Some("group") = parts.next() {
50
            let group = parts
51
                .next()
52
                .ok_or(RequestParserError::MissingKeywordValue {
53
                    argument_index: 1,
54
                    keyword: "group",
55
                })?;
56

            
57
            Some(
58
                group
59
                    .parse()
60
                    .map_err(|_| RequestParserError::SubtypeParserError {
61
                        argument_index: 1,
62
                        expected_type: "GroupType",
63
                        raw_input: group.to_owned(),
64
                    })?,
65
            )
66
        } else {
67
            None
68
        };
69

            
70
        Self::throw_if_too_many_arguments(parts)?;
71

            
72
        Ok(CountRequest { filter, group })
73
    }
74
}
75

            
76
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
77
pub struct CountResponse {
78
    pub songs: usize,
79
    pub playtime: u64,
80
}
81

            
82
impl CountResponse {
83
    pub fn new(songs: usize, playtime: u64) -> Self {
84
        CountResponse { songs, playtime }
85
    }
86
}
87

            
88
impl CommandResponse for CountResponse {
89
    type Request = CountRequest;
90

            
91
    fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
92
        let parts: HashMap<_, _> = parts.into_map()?;
93

            
94
        let songs = get_and_parse_property!(parts, "songs", Text);
95
        let playtime = get_and_parse_property!(parts, "playtime", Text);
96

            
97
        Ok(CountResponse { songs, playtime })
98
    }
99

            
100
    fn serialize(&self) -> Vec<u8> {
101
        unimplemented!("response serialization is not yet implemented for CountResponse")
102
    }
103
}