librespot_metadata/playlist/
operation.rs

1use std::{
2    fmt::Debug,
3    ops::{Deref, DerefMut},
4};
5
6use crate::{
7    playlist::{
8        attribute::{PlaylistUpdateAttributes, PlaylistUpdateItemAttributes},
9        item::PlaylistItems,
10    },
11    util::{impl_deref_wrapped, impl_try_from_repeated},
12};
13
14use librespot_protocol as protocol;
15use protocol::playlist4_external::Add as PlaylistAddMessage;
16use protocol::playlist4_external::Mov as PlaylistMoveMessage;
17use protocol::playlist4_external::Op as PlaylistOperationMessage;
18use protocol::playlist4_external::Rem as PlaylistRemoveMessage;
19pub use protocol::playlist4_external::op::Kind as PlaylistOperationKind;
20
21#[derive(Debug, Clone)]
22pub struct PlaylistOperation {
23    pub kind: PlaylistOperationKind,
24    pub add: PlaylistOperationAdd,
25    pub rem: PlaylistOperationRemove,
26    pub mov: PlaylistOperationMove,
27    pub update_item_attributes: PlaylistUpdateItemAttributes,
28    pub update_list_attributes: PlaylistUpdateAttributes,
29}
30
31#[derive(Debug, Clone, Default)]
32pub struct PlaylistOperations(pub Vec<PlaylistOperation>);
33
34impl_deref_wrapped!(PlaylistOperations, Vec<PlaylistOperation>);
35
36#[derive(Debug, Clone)]
37pub struct PlaylistOperationAdd {
38    pub from_index: i32,
39    pub items: PlaylistItems,
40    pub add_last: bool,
41    pub add_first: bool,
42}
43
44#[derive(Debug, Clone)]
45pub struct PlaylistOperationMove {
46    pub from_index: i32,
47    pub length: i32,
48    pub to_index: i32,
49}
50
51#[derive(Debug, Clone)]
52pub struct PlaylistOperationRemove {
53    pub from_index: i32,
54    pub length: i32,
55    pub items: PlaylistItems,
56    pub has_items_as_key: bool,
57}
58
59impl TryFrom<&PlaylistOperationMessage> for PlaylistOperation {
60    type Error = librespot_core::Error;
61    fn try_from(operation: &PlaylistOperationMessage) -> Result<Self, Self::Error> {
62        Ok(Self {
63            kind: operation.kind(),
64            add: operation.add.get_or_default().try_into()?,
65            rem: operation.rem.get_or_default().try_into()?,
66            mov: operation.mov.get_or_default().into(),
67            update_item_attributes: operation
68                .update_item_attributes
69                .get_or_default()
70                .try_into()?,
71            update_list_attributes: operation
72                .update_list_attributes
73                .get_or_default()
74                .try_into()?,
75        })
76    }
77}
78
79impl_try_from_repeated!(PlaylistOperationMessage, PlaylistOperations);
80
81impl TryFrom<&PlaylistAddMessage> for PlaylistOperationAdd {
82    type Error = librespot_core::Error;
83    fn try_from(add: &PlaylistAddMessage) -> Result<Self, Self::Error> {
84        Ok(Self {
85            from_index: add.from_index(),
86            items: add.items.as_slice().try_into()?,
87            add_last: add.add_last(),
88            add_first: add.add_first(),
89        })
90    }
91}
92
93impl From<&PlaylistMoveMessage> for PlaylistOperationMove {
94    fn from(mov: &PlaylistMoveMessage) -> Self {
95        Self {
96            from_index: mov.from_index(),
97            length: mov.length(),
98            to_index: mov.to_index(),
99        }
100    }
101}
102
103impl TryFrom<&PlaylistRemoveMessage> for PlaylistOperationRemove {
104    type Error = librespot_core::Error;
105    fn try_from(remove: &PlaylistRemoveMessage) -> Result<Self, Self::Error> {
106        Ok(Self {
107            from_index: remove.from_index(),
108            length: remove.length(),
109            items: remove.items.as_slice().try_into()?,
110            has_items_as_key: remove.items_as_key(),
111        })
112    }
113}