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

            
3
use crate::{
4
    commands::{Command, CommandResponse, ResponseParserError, empty_command_request},
5
    response_tokenizer::{ResponseAttributes, expect_property_type},
6
};
7

            
8
pub struct Decoders;
9

            
10
empty_command_request!(Decoders, "decoders");
11

            
12
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
13
pub struct Decoder {
14
    pub plugin: String,
15
    pub suffixes: Vec<String>,
16
    pub mime_types: Vec<String>,
17
}
18

            
19
impl Decoder {
20
    pub fn new(plugin: String, suffixes: Vec<String>, mime_types: Vec<String>) -> Self {
21
        Decoder {
22
            plugin,
23
            suffixes,
24
            mime_types,
25
        }
26
    }
27
}
28

            
29
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
30
pub struct DecodersResponse(Vec<Decoder>);
31

            
32
impl DecodersResponse {
33
    pub fn new(items: Vec<Decoder>) -> Self {
34
        DecodersResponse(items)
35
    }
36
}
37

            
38
impl CommandResponse for DecodersResponse {
39
1
    fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
40
1
        let mut result = Vec::new();
41
1
        let mut current_decoder: Option<Decoder> = None;
42
16
        for (key, value) in parts.into_vec()?.into_iter() {
43
16
            match key {
44
16
                "plugin" => {
45
2
                    if let Some(decoder) = current_decoder.take() {
46
1
                        result.push(decoder);
47
1
                    }
48

            
49
2
                    let plugin_name = expect_property_type!(Some(value), key, Text).to_string();
50

            
51
2
                    current_decoder = Some(Decoder {
52
2
                        plugin: plugin_name,
53
2
                        suffixes: Vec::new(),
54
2
                        mime_types: Vec::new(),
55
2
                    });
56
                }
57
14
                "suffix" => {
58
4
                    current_decoder
59
4
                        .as_mut()
60
4
                        .ok_or(ResponseParserError::SyntaxError(0, key.to_string()))?
61
                        .suffixes
62
4
                        .push(expect_property_type!(Some(value), key, Text).to_string());
63
                }
64
10
                "mime_type" => {
65
10
                    current_decoder
66
10
                        .as_mut()
67
10
                        .ok_or(ResponseParserError::SyntaxError(0, key.to_string()))?
68
                        .mime_types
69
10
                        .push(expect_property_type!(Some(value), key, Text).to_string());
70
                }
71
                k => {
72
                    return Err(ResponseParserError::UnexpectedProperty(k.to_string()));
73
                }
74
            }
75
        }
76

            
77
1
        if let Some(decoder) = current_decoder.take() {
78
1
            result.push(decoder);
79
1
        }
80

            
81
1
        Ok(DecodersResponse(result))
82
1
    }
83
}
84

            
85
impl Command for Decoders {
86
    type Request = DecodersRequest;
87
    type Response = DecodersResponse;
88
}
89

            
90
#[cfg(test)]
91
mod tests {
92
    use indoc::indoc;
93

            
94
    use super::*;
95

            
96
    #[test]
97
1
    fn test_parse_response() {
98
1
        let input = indoc! {"
99
1
            plugin: audiofile
100
1
            suffix: wav
101
1
            suffix: au
102
1
            suffix: aiff
103
1
            suffix: aif
104
1
            mime_type: audio/wav
105
1
            mime_type: audio/aiff
106
1
            mime_type: audio/x-wav
107
1
            mime_type: audio/x-aiff
108
1
            plugin: pcm
109
1
            mime_type: audio/L16
110
1
            mime_type: audio/L24
111
1
            mime_type: audio/x-mpd-float
112
1
            mime_type: audio/x-mpd-cdda-pcm
113
1
            mime_type: audio/x-mpd-cdda-pcm-reverse
114
1
            mime_type: audio/x-mpd-alsa-pcm
115
1
            OK
116
1
        "};
117
1
        let result = Decoders::parse_raw_response(input.as_bytes());
118
1
        assert_eq!(
119
            result,
120
1
            Ok(DecodersResponse(vec![
121
1
                Decoder {
122
1
                    plugin: "audiofile".to_string(),
123
1
                    suffixes: vec![
124
1
                        "wav".to_string(),
125
1
                        "au".to_string(),
126
1
                        "aiff".to_string(),
127
1
                        "aif".to_string()
128
1
                    ],
129
1
                    mime_types: vec![
130
1
                        "audio/wav".to_string(),
131
1
                        "audio/aiff".to_string(),
132
1
                        "audio/x-wav".to_string(),
133
1
                        "audio/x-aiff".to_string()
134
1
                    ],
135
1
                },
136
1
                Decoder {
137
1
                    plugin: "pcm".to_string(),
138
1
                    suffixes: vec![],
139
1
                    mime_types: vec![
140
1
                        "audio/L16".to_string(),
141
1
                        "audio/L24".to_string(),
142
1
                        "audio/x-mpd-float".to_string(),
143
1
                        "audio/x-mpd-cdda-pcm".to_string(),
144
1
                        "audio/x-mpd-cdda-pcm-reverse".to_string(),
145
1
                        "audio/x-mpd-alsa-pcm".to_string(),
146
1
                    ],
147
1
                },
148
1
            ])),
149
        );
150
1
    }
151
}