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

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

            
8
empty_command_request!(Decoders, "decoders");
9

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

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

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

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

            
36
impl CommandResponse for DecodersResponse {
37
    type Request = DecodersRequest;
38

            
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
    fn serialize(&self) -> Vec<u8> {
85
        unimplemented!("response serialization is not yet implemented for DecodersResponse")
86
    }
87
}
88

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

            
93
    use super::*;
94

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