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, expect_property_type},
8
    types::{GroupType, TagName, WindowRange},
9
};
10

            
11
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
12
pub struct ListRequest {
13
    tagname: TagName,
14
    filter: Option<Filter>,
15
    groups: Vec<GroupType>,
16
    window: Option<WindowRange>,
17
}
18

            
19
impl ListRequest {
20
    pub fn new(
21
        tagname: TagName,
22
        filter: Option<Filter>,
23
        groups: Vec<GroupType>,
24
        window: Option<WindowRange>,
25
    ) -> Self {
26
        Self {
27
            tagname,
28
            filter,
29
            groups,
30
            window,
31
        }
32
    }
33
}
34

            
35
impl CommandRequest for ListRequest {
36
    type Response = ListResponse;
37

            
38
    const COMMAND: &'static str = "list";
39
    const MIN_ARGS: u32 = 1;
40
    const MAX_ARGS: Option<u32> = None;
41

            
42
    fn serialize(&self) -> String {
43
        let mut cmd = match &self.filter {
44
            Some(f) => format!("{} {} {}", Self::COMMAND, self.tagname, f),
45
            None => format!("{} {}", Self::COMMAND, self.tagname),
46
        };
47
        for group in &self.groups {
48
            cmd.push_str(&format!(" group {}", group));
49
        }
50
        if let Some(window) = &self.window {
51
            cmd.push_str(&format!(" window {}", window));
52
        }
53
        cmd.push('\n');
54
        cmd
55
    }
56

            
57
    fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
58
        let tagname = parts.next().ok_or(Self::missing_arguments_error(0))?;
59
        let tagname = tagname
60
            .parse()
61
            .map_err(|_| RequestParserError::SubtypeParserError {
62
                argument_index: 0,
63
                expected_type: "TagName",
64
                raw_input: tagname.to_owned(),
65
            })?;
66

            
67
        let mut filter = None;
68
        let mut groups = Vec::new();
69
        let mut window = None;
70

            
71
        let mut next = parts.next();
72

            
73
        let mut argument_index_counter = 0;
74
        if let Some(f) = next
75
            && f != "group"
76
            && f != "window"
77
        {
78
            argument_index_counter += 1;
79
            let parsed_filter =
80
                Filter::parse(f).map_err(|_| RequestParserError::SyntaxError(1, f.to_owned()))?;
81
            filter = Some(parsed_filter);
82
            next = parts.next();
83
        }
84

            
85
        while let Some(g) = next
86
            && g == "group"
87
        {
88
            argument_index_counter += 1;
89
            let group = parts
90
                .next()
91
                .ok_or(RequestParserError::MissingKeywordValue {
92
                    keyword: "group",
93
                    argument_index: argument_index_counter,
94
                })?;
95
            let parsed_group =
96
                group
97
                    .parse()
98
                    .map_err(|_| RequestParserError::SubtypeParserError {
99
                        argument_index: 2,
100
                        expected_type: "GroupType",
101
                        raw_input: group.to_owned(),
102
                    })?;
103
            groups.push(parsed_group);
104
            next = parts.next();
105
        }
106

            
107
        if let Some(w) = next
108
            && w == "window"
109
        {
110
            let window_str = parts
111
                .next()
112
                .ok_or(RequestParserError::MissingKeywordValue {
113
                    keyword: "window",
114
                    argument_index: argument_index_counter,
115
                })?;
116
            let parsed_window =
117
                window_str
118
                    .parse()
119
                    .map_err(|_| RequestParserError::SubtypeParserError {
120
                        argument_index: 3,
121
                        expected_type: "WindowRange",
122
                        raw_input: window_str.to_owned(),
123
                    })?;
124
            window = Some(parsed_window);
125
        }
126

            
127
        Self::throw_if_too_many_arguments(parts)?;
128

            
129
        Ok(ListRequest {
130
            tagname,
131
            filter,
132
            groups,
133
            window,
134
        })
135
    }
136
}
137

            
138
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
139
pub struct ListResponse(Vec<String>);
140

            
141
impl ListResponse {
142
    pub fn new(items: Vec<String>) -> Self {
143
        ListResponse(items)
144
    }
145
}
146

            
147
impl CommandResponse for ListResponse {
148
    type Request = ListRequest;
149

            
150
    fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
151
        let parts_: Vec<_> = parts.into_vec()?;
152
        debug_assert!({
153
            let key = parts_.first().map(|(k, _)| k);
154
            parts_.iter().all(|(k, _)| k == key.unwrap())
155
        });
156

            
157
        let list = parts_
158
            .into_iter()
159
            .map(|(k, v)| Ok(expect_property_type!(Some(v), k, Text).to_string()))
160
            .collect::<Result<Vec<_>, ResponseParserError>>()?;
161

            
162
        Ok(ListResponse(list))
163
    }
164

            
165
    fn serialize(&self) -> Vec<u8> {
166
        unimplemented!("response serialization is not yet implemented for ListResponse")
167
    }
168
}