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

            
3
use crate::common::*;
4
use crate::request_tokenizer::RequestTokenizer;
5

            
6
use crate::commands::*;
7
use crate::filter::Filter;
8

            
9
// TODO: SingleLineString
10

            
11
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
12
pub enum Request {
13
    CommandList(Vec<Request>),
14

            
15
    // -- Query Commands -- //
16
    ClearError,
17
    CurrentSong,
18
    Idle(Option<Vec<SubSystem>>),
19
    Status,
20
    Stats,
21

            
22
    // -- Playback Commands -- //
23
    Consume(BoolOrOneshot),
24
    Crossfade(Seconds),
25
    MixRampDb(f32),
26
    MixRampDelay(Seconds),
27
    Random(bool),
28
    Repeat(bool),
29
    SetVol(VolumeValue),
30
    GetVol,
31
    Single(BoolOrOneshot),
32
    ReplayGainMode(ReplayGainModeMode),
33
    ReplayGainStatus,
34
    Volume(VolumeValue),
35

            
36
    // -- Playback Control Commands -- //
37
    Next,
38
    Pause(Option<bool>),
39
    Play(SongPosition),
40
    PlayId(SongId),
41
    Previous,
42
    Seek(SongPosition, TimeWithFractions),
43
    SeekId(SongId, TimeWithFractions),
44
    SeekCur(SeekMode, TimeWithFractions),
45
    Stop,
46

            
47
    // -- Queue Commands -- //
48
    // TODO: relative mode
49
    Add(String, Option<SongPosition>),
50
    // TODO: relative mode
51
    AddId(String, Option<SongPosition>),
52
    Clear,
53
    Delete(OneOrRange),
54
    DeleteId(SongId),
55
    // TODO: account for relative moves
56
    Move(OneOrRange, AbsouluteRelativeSongPosition),
57
    // TODO: account for relative moves
58
    MoveId(SongId, AbsouluteRelativeSongPosition),
59
    Playlist,
60
    PlaylistFind(Filter, Option<Sort>, Option<WindowRange>),
61
    PlaylistId(SongId),
62
    PlaylistInfo(Option<OneOrRange>),
63
    PlaylistSearch(Filter, Option<Sort>, Option<WindowRange>),
64
    // TODO: which type of range?
65
    PlChanges(PlaylistVersion, Option<WindowRange>),
66
    // TODO: which type of range?
67
    PlChangesPosId(PlaylistVersion, Option<WindowRange>),
68
    // TODO: which type of range?
69
    Prio(Priority, WindowRange),
70
    PrioId(Priority, Vec<SongId>),
71
    RangeId(SongId, TimeInterval),
72
    Shuffle(Option<OneOrRange>),
73
    Swap(SongPosition, SongPosition),
74
    SwapId(SongId, SongId),
75
    AddTagId(SongId, TagName, TagValue),
76
    ClearTagId(SongId, TagName),
77

            
78
    // -- Stored Playlist Commands -- //
79
    ListPlaylist(PlaylistName, Option<WindowRange>),
80
    ListPlaylistInfo(PlaylistName, Option<WindowRange>),
81
    SearchPlaylist(PlaylistName, Filter, Option<WindowRange>),
82
    ListPlaylists,
83
    Load(PlaylistName, Option<WindowRange>, Option<SongPosition>),
84
    PlaylistAdd(PlaylistName, Uri, Option<SongPosition>),
85
    PlaylistClear(PlaylistName),
86
    PlaylistDelete(PlaylistName, OneOrRange),
87
    PlaylistLength(PlaylistName),
88
    // TODO: which type of range?
89
    PlaylistMove(PlaylistName, Option<OneOrRange>, SongPosition),
90
    Rename(PlaylistName, PlaylistName),
91
    Rm(PlaylistName),
92
    Save(PlaylistName, Option<SaveMode>),
93

            
94
    // -- Music Database Commands -- //
95
    AlbumArt(Uri, Offset),
96
    Count(Filter, Option<GroupType>),
97
    GetFingerprint(Uri),
98
    Find(Filter, Option<Sort>, Option<WindowRange>),
99
    FindAdd(
100
        Filter,
101
        Option<Sort>,
102
        Option<WindowRange>,
103
        Option<SongPosition>,
104
    ),
105
    List(TagName, Option<Filter>, Vec<GroupType>, Option<WindowRange>),
106
    #[deprecated]
107
    ListAll(Option<Uri>),
108
    #[deprecated]
109
    ListAllInfo(Option<Uri>),
110
    ListFiles(Option<Uri>),
111
    LsInfo(Option<Uri>),
112
    ReadComments(Uri),
113
    ReadPicture(Uri, Offset),
114
    Search(Filter, Option<Sort>, Option<WindowRange>),
115
    SearchAdd(
116
        Filter,
117
        Option<Sort>,
118
        Option<WindowRange>,
119
        Option<SongPosition>,
120
    ),
121
    SearchAddPl(
122
        PlaylistName,
123
        Filter,
124
        Option<Sort>,
125
        Option<WindowRange>,
126
        Option<SongPosition>,
127
    ),
128
    SearchCount(Filter, Option<GroupType>),
129
    Update(Option<Uri>),
130
    Rescan(Option<Uri>),
131

            
132
    // -- Mount and Neighbor Commands -- //
133
    Mount(MountPath, Uri),
134
    Unmount(MountPath),
135
    ListMounts,
136
    ListNeighbors,
137

            
138
    // -- Sticker Commands -- //
139
    StickerGet(StickerType, Uri, String),
140
    StickerSet(StickerType, Uri, String, String),
141
    StickerInc(StickerType, Uri, String, usize),
142
    StickerDec(StickerType, Uri, String, usize),
143
    StickerDelete(StickerType, Uri, String),
144
    StickerList(StickerType, Uri),
145
    StickerFind(StickerType, Uri, String, Option<Sort>, Option<WindowRange>),
146
    StickerFindValue(
147
        StickerType,
148
        Uri,
149
        String,
150
        String,
151
        Option<Sort>,
152
        Option<WindowRange>,
153
    ),
154
    StickerNames,
155
    StickerTypes,
156
    StickerNamesTypes(Option<StickerType>),
157

            
158
    // -- Connection Commands -- //
159
    Close,
160
    Kill,
161
    Password(String),
162
    Ping,
163
    BinaryLimit(u64),
164
    TagTypes,
165
    TagTypesDisable(Vec<TagName>),
166
    TagTypesEnable(Vec<TagName>),
167
    TagTypesClear,
168
    TagTypesAll,
169
    TagTypesAvailable,
170
    TagTypesReset(Vec<TagName>),
171
    Protocol,
172
    ProtocolDisable(Vec<Feature>),
173
    ProtocolEnable(Vec<Feature>),
174
    ProtocolClear,
175
    ProtocolAll,
176
    ProtocolAvailable,
177

            
178
    // -- Partition Commands -- //
179
    Partition(PartitionName),
180
    ListPartitions,
181
    NewPartition(PartitionName),
182
    DelPartition(PartitionName),
183
    MoveOutput(String),
184

            
185
    // -- Audio Output Commands -- //
186
    DisableOutput(AudioOutputId),
187
    EnableOutput(AudioOutputId),
188
    ToggleOutput(AudioOutputId),
189
    Outputs,
190
    OutputSet(AudioOutputId, String, String),
191

            
192
    // -- Reflection Commands -- //
193
    Config,
194
    Commands,
195
    NotCommands,
196
    UrlHandlers,
197
    Decoders,
198

            
199
    // -- Client to Client Commands -- //
200
    Subscribe(ChannelName),
201
    Unsubscribe(ChannelName),
202
    Channels,
203
    ReadMessages,
204
    SendMessage(ChannelName, String),
205
}
206

            
207
// pub enum RequestParserError {
208
//     SyntaxError(u64, String),
209
//     MissingCommandListEnd(u64),
210
//     NestedCommandList(u64),
211
//     UnexpectedCommandListEnd(u64),
212
//     UnexpectedEOF,
213
//     MissingNewline,
214
// }
215

            
216
// TODO: upon encountering an error, there should be a function that lets you skip to the next OK,
217
//       and continue execution. Maybe "parse_next_or_skip(&str) -> RequestParserResponse", which
218
//       could skip stuff internally? Or do we want to report back the error with the entire command
219
//       and let the library user decide what to do?
220

            
221
impl Request {
222
    pub fn parse_next(raw: &str) -> RequestParserResult<'_> {
223
        let (line, rest) = raw
224
            .split_once('\n')
225
            .ok_or(RequestParserError::UnexpectedEOF)?;
226
        let mut parts = RequestTokenizer::new(line);
227

            
228
        match parts
229
            .next()
230
            .ok_or(RequestParserError::SyntaxError(0, line.to_string()))?
231
            .trim()
232
        {
233
            "command_list_begin" => {
234
                let mut commands = Vec::new();
235
                let mut i = 1;
236
                loop {
237
                    i += 1;
238
                    let (line, rest) = rest
239
                        .split_once('\n')
240
                        .ok_or(RequestParserError::MissingCommandListEnd(i))?;
241
                    match line.trim() {
242
                        "command_list_begin" => {
243
                            return Err(RequestParserError::NestedCommandList(i));
244
                        }
245
                        "command_list_end" => {
246
                            return Ok((Request::CommandList(commands), rest));
247
                        }
248
                        input => {
249
                            let (command, _) = Request::parse_next(input)?;
250
                            commands.push(command);
251
                        }
252
                    }
253
                }
254
            }
255
            "command_list_end" => Err(RequestParserError::UnexpectedCommandListEnd(0)),
256

            
257
            /* querying mpd status */
258
            ClearError::COMMAND => ClearError::parse_request(parts),
259
            CurrentSong::COMMAND => CurrentSong::parse_request(parts),
260
            Idle::COMMAND => Idle::parse_request(parts),
261
            Status::COMMAND => Status::parse_request(parts),
262
            Stats::COMMAND => Stats::parse_request(parts),
263

            
264
            /* playback options */
265
            Consume::COMMAND => Consume::parse_request(parts),
266
            Crossfade::COMMAND => Crossfade::parse_request(parts),
267
            MixRampDb::COMMAND => MixRampDb::parse_request(parts),
268
            MixRampDelay::COMMAND => MixRampDelay::parse_request(parts),
269
            Random::COMMAND => Random::parse_request(parts),
270
            Repeat::COMMAND => Repeat::parse_request(parts),
271
            SetVol::COMMAND => SetVol::parse_request(parts),
272
            GetVol::COMMAND => GetVol::parse_request(parts),
273
            Single::COMMAND => Single::parse_request(parts),
274
            ReplayGainMode::COMMAND => ReplayGainMode::parse_request(parts),
275
            ReplayGainStatus::COMMAND => ReplayGainStatus::parse_request(parts),
276
            Volume::COMMAND => Volume::parse_request(parts),
277

            
278
            /* playback control */
279
            Next::COMMAND => Next::parse_request(parts),
280
            Pause::COMMAND => Pause::parse_request(parts),
281
            Play::COMMAND => Play::parse_request(parts),
282
            PlayId::COMMAND => PlayId::parse_request(parts),
283
            Previous::COMMAND => Previous::parse_request(parts),
284
            Seek::COMMAND => Seek::parse_request(parts),
285
            SeekId::COMMAND => SeekId::parse_request(parts),
286
            SeekCur::COMMAND => SeekCur::parse_request(parts),
287
            Stop::COMMAND => Stop::parse_request(parts),
288

            
289
            /* queue */
290
            Add::COMMAND => Add::parse_request(parts),
291
            AddId::COMMAND => AddId::parse_request(parts),
292
            Clear::COMMAND => Clear::parse_request(parts),
293
            Delete::COMMAND => Delete::parse_request(parts),
294
            DeleteId::COMMAND => DeleteId::parse_request(parts),
295
            Move::COMMAND => Move::parse_request(parts),
296
            MoveId::COMMAND => MoveId::parse_request(parts),
297
            Playlist::COMMAND => Playlist::parse_request(parts),
298
            PlaylistFind::COMMAND => PlaylistFind::parse_request(parts),
299
            PlaylistId::COMMAND => PlaylistId::parse_request(parts),
300
            PlaylistInfo::COMMAND => PlaylistInfo::parse_request(parts),
301
            PlaylistSearch::COMMAND => PlaylistSearch::parse_request(parts),
302
            PlChanges::COMMAND => PlChanges::parse_request(parts),
303
            PlChangesPosId::COMMAND => PlChangesPosId::parse_request(parts),
304
            Prio::COMMAND => Prio::parse_request(parts),
305
            PrioId::COMMAND => PrioId::parse_request(parts),
306
            RangeId::COMMAND => RangeId::parse_request(parts),
307
            Shuffle::COMMAND => Shuffle::parse_request(parts),
308
            Swap::COMMAND => Swap::parse_request(parts),
309
            SwapId::COMMAND => SwapId::parse_request(parts),
310
            AddTagId::COMMAND => AddTagId::parse_request(parts),
311
            ClearTagId::COMMAND => ClearTagId::parse_request(parts),
312

            
313
            /* stored playlists */
314
            ListPlaylist::COMMAND => ListPlaylist::parse_request(parts),
315
            ListPlaylistInfo::COMMAND => ListPlaylistInfo::parse_request(parts),
316
            SearchPlaylist::COMMAND => SearchPlaylist::parse_request(parts),
317
            ListPlaylists::COMMAND => ListPlaylists::parse_request(parts),
318
            Load::COMMAND => Load::parse_request(parts),
319
            PlaylistAdd::COMMAND => PlaylistAdd::parse_request(parts),
320
            PlaylistClear::COMMAND => PlaylistClear::parse_request(parts),
321
            PlaylistDelete::COMMAND => PlaylistDelete::parse_request(parts),
322
            PlaylistLength::COMMAND => PlaylistLength::parse_request(parts),
323
            PlaylistMove::COMMAND => PlaylistMove::parse_request(parts),
324
            Rename::COMMAND => Rename::parse_request(parts),
325
            Rm::COMMAND => Rm::parse_request(parts),
326
            Save::COMMAND => Save::parse_request(parts),
327

            
328
            /* music database */
329
            AlbumArt::COMMAND => AlbumArt::parse_request(parts),
330
            Count::COMMAND => Count::parse_request(parts),
331
            GetFingerprint::COMMAND => GetFingerprint::parse_request(parts),
332
            Find::COMMAND => Find::parse_request(parts),
333
            FindAdd::COMMAND => FindAdd::parse_request(parts),
334
            List::COMMAND => List::parse_request(parts),
335
            ListAll::COMMAND => ListAll::parse_request(parts),
336
            ListAllInfo::COMMAND => ListAllInfo::parse_request(parts),
337
            ListFiles::COMMAND => ListFiles::parse_request(parts),
338
            LsInfo::COMMAND => LsInfo::parse_request(parts),
339
            ReadComments::COMMAND => ReadComments::parse_request(parts),
340
            ReadPicture::COMMAND => ReadPicture::parse_request(parts),
341
            Search::COMMAND => Search::parse_request(parts),
342
            SearchAdd::COMMAND => SearchAdd::parse_request(parts),
343
            SearchAddPl::COMMAND => SearchAddPl::parse_request(parts),
344
            SearchCount::COMMAND => SearchCount::parse_request(parts),
345
            Update::COMMAND => Update::parse_request(parts),
346
            Rescan::COMMAND => Rescan::parse_request(parts),
347

            
348
            /* mounts and neighbors */
349
            Mount::COMMAND => Mount::parse_request(parts),
350
            Unmount::COMMAND => Unmount::parse_request(parts),
351
            ListMounts::COMMAND => ListMounts::parse_request(parts),
352
            ListNeighbors::COMMAND => ListNeighbors::parse_request(parts),
353

            
354
            /* stickers */
355
            StickerGet::COMMAND => StickerGet::parse_request(parts),
356
            StickerSet::COMMAND => StickerSet::parse_request(parts),
357
            StickerInc::COMMAND => StickerInc::parse_request(parts),
358
            StickerDec::COMMAND => StickerDec::parse_request(parts),
359
            StickerDelete::COMMAND => StickerDelete::parse_request(parts),
360
            StickerList::COMMAND => StickerList::parse_request(parts),
361
            StickerFind::COMMAND => StickerFind::parse_request(parts),
362
            StickerNames::COMMAND => StickerNames::parse_request(parts),
363
            StickerTypes::COMMAND => StickerTypes::parse_request(parts),
364
            StickerNamesTypes::COMMAND => StickerNamesTypes::parse_request(parts),
365

            
366
            /* connection settings */
367
            Close::COMMAND => Close::parse_request(parts),
368
            Kill::COMMAND => Kill::parse_request(parts),
369
            Password::COMMAND => Password::parse_request(parts),
370
            Ping::COMMAND => Ping::parse_request(parts),
371
            BinaryLimit::COMMAND => BinaryLimit::parse_request(parts),
372
            TagTypes::COMMAND => TagTypes::parse_request(parts),
373
            TagTypesDisable::COMMAND => TagTypesDisable::parse_request(parts),
374
            TagTypesEnable::COMMAND => TagTypesEnable::parse_request(parts),
375
            TagTypesClear::COMMAND => TagTypesClear::parse_request(parts),
376
            TagTypesAll::COMMAND => TagTypesAll::parse_request(parts),
377
            TagTypesAvailable::COMMAND => TagTypesAvailable::parse_request(parts),
378
            TagTypesReset::COMMAND => TagTypesReset::parse_request(parts),
379
            Protocol::COMMAND => Protocol::parse_request(parts),
380
            ProtocolDisable::COMMAND => ProtocolDisable::parse_request(parts),
381
            ProtocolEnable::COMMAND => ProtocolEnable::parse_request(parts),
382
            ProtocolClear::COMMAND => ProtocolClear::parse_request(parts),
383
            ProtocolAll::COMMAND => ProtocolAll::parse_request(parts),
384
            ProtocolAvailable::COMMAND => ProtocolAvailable::parse_request(parts),
385

            
386
            /* partition commands */
387
            Partition::COMMAND => Partition::parse_request(parts),
388
            ListPartitions::COMMAND => ListPartitions::parse_request(parts),
389
            NewPartition::COMMAND => NewPartition::parse_request(parts),
390
            DelPartition::COMMAND => DelPartition::parse_request(parts),
391
            MoveOutput::COMMAND => MoveOutput::parse_request(parts),
392

            
393
            /* audio output devices */
394
            DisableOutput::COMMAND => DisableOutput::parse_request(parts),
395
            EnableOutput::COMMAND => EnableOutput::parse_request(parts),
396
            ToggleOutput::COMMAND => ToggleOutput::parse_request(parts),
397
            Outputs::COMMAND => Outputs::parse_request(parts),
398
            OutputSet::COMMAND => OutputSet::parse_request(parts),
399

            
400
            /* reflection */
401
            Config::COMMAND => Config::parse_request(parts),
402
            Commands::COMMAND => Commands::parse_request(parts),
403
            NotCommands::COMMAND => NotCommands::parse_request(parts),
404
            UrlHandlers::COMMAND => UrlHandlers::parse_request(parts),
405
            Decoders::COMMAND => Decoders::parse_request(parts),
406

            
407
            /* client to client */
408
            Subscribe::COMMAND => Subscribe::parse_request(parts),
409
            Unsubscribe::COMMAND => Unsubscribe::parse_request(parts),
410
            Channels::COMMAND => Channels::parse_request(parts),
411
            ReadMessages::COMMAND => ReadMessages::parse_request(parts),
412
            SendMessage::COMMAND => SendMessage::parse_request(parts),
413

            
414
            _ => unimplemented!(),
415
        }
416
    }
417
}