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

            
3
use crate::{
4
    commands::{Command, CommandRequest, RequestParserError, empty_command_response},
5
    request_tokenizer::RequestTokenizer,
6
    types::{SongPosition, Uri},
7
};
8

            
9
pub struct Add;
10

            
11
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
12
pub struct AddRequest {
13
    uri: Uri,
14
    position: Option<SongPosition>,
15
}
16

            
17
impl AddRequest {
18
    pub fn new(uri: Uri, position: Option<SongPosition>) -> Self {
19
        Self { uri, position }
20
    }
21
}
22

            
23
impl CommandRequest for AddRequest {
24
    const COMMAND: &'static str = "add";
25
    const MIN_ARGS: u32 = 1;
26
    const MAX_ARGS: Option<u32> = Some(2);
27

            
28
    fn into_request_enum(self) -> crate::Request {
29
        crate::Request::Add(self.uri, self.position)
30
    }
31

            
32
    fn from_request_enum(request: crate::Request) -> Option<Self> {
33
        match request {
34
            crate::Request::Add(uri, position) => Some(AddRequest { uri, position }),
35
            _ => None,
36
        }
37
    }
38

            
39
    fn serialize(&self) -> String {
40
        match self.position {
41
            Some(position) => format!("{} {} {}\n", Self::COMMAND, self.uri, position),
42
            None => format!("{} {}\n", Self::COMMAND, self.uri),
43
        }
44
    }
45

            
46
    fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
47
        let uri = match parts.next() {
48
            Some(s) => s,
49
            None => return Err(Self::missing_arguments_error(0)),
50
        };
51

            
52
        let position = match parts.next() {
53
            Some(s) => Some(s.parse::<SongPosition>().map_err(|_| {
54
                RequestParserError::SubtypeParserError {
55
                    argument_index: 1,
56
                    expected_type: "SongPosition",
57
                    raw_input: s.to_owned(),
58
                }
59
            })?),
60
            None => None,
61
        };
62

            
63
        Self::throw_if_too_many_arguments(parts)?;
64

            
65
        Ok(AddRequest {
66
            uri: uri.to_string(),
67
            position,
68
        })
69
    }
70
}
71

            
72
empty_command_response!(Add);
73

            
74
impl Command for Add {
75
    type Request = AddRequest;
76
    type Response = AddResponse;
77
}