librespot_metadata/playlist/
attribute.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
use std::{
    collections::HashMap,
    fmt::Debug,
    ops::{Deref, DerefMut},
};

use crate::{
    image::PictureSizes,
    util::{impl_deref_wrapped, impl_from_repeated_copy},
};

use librespot_core::date::Date;

use librespot_protocol as protocol;
use protocol::playlist4_external::FormatListAttribute as PlaylistFormatAttributeMessage;
pub use protocol::playlist4_external::ItemAttributeKind as PlaylistItemAttributeKind;
use protocol::playlist4_external::ItemAttributes as PlaylistItemAttributesMessage;
use protocol::playlist4_external::ItemAttributesPartialState as PlaylistPartialItemAttributesMessage;
pub use protocol::playlist4_external::ListAttributeKind as PlaylistAttributeKind;
use protocol::playlist4_external::ListAttributes as PlaylistAttributesMessage;
use protocol::playlist4_external::ListAttributesPartialState as PlaylistPartialAttributesMessage;
use protocol::playlist4_external::UpdateItemAttributes as PlaylistUpdateItemAttributesMessage;
use protocol::playlist4_external::UpdateListAttributes as PlaylistUpdateAttributesMessage;

#[derive(Debug, Clone)]
pub struct PlaylistAttributes {
    pub name: String,
    pub description: String,
    pub picture: Vec<u8>,
    pub is_collaborative: bool,
    pub pl3_version: String,
    pub is_deleted_by_owner: bool,
    pub client_id: String,
    pub format: String,
    pub format_attributes: PlaylistFormatAttribute,
    pub picture_sizes: PictureSizes,
}

#[derive(Debug, Clone, Default)]
pub struct PlaylistAttributeKinds(pub Vec<PlaylistAttributeKind>);

impl_deref_wrapped!(PlaylistAttributeKinds, Vec<PlaylistAttributeKind>);

impl_from_repeated_copy!(PlaylistAttributeKind, PlaylistAttributeKinds);

#[derive(Debug, Clone, Default)]
pub struct PlaylistFormatAttribute(pub HashMap<String, String>);

impl_deref_wrapped!(PlaylistFormatAttribute, HashMap<String, String>);

#[derive(Debug, Clone)]
pub struct PlaylistItemAttributes {
    pub added_by: String,
    pub timestamp: Date,
    pub seen_at: Date,
    pub is_public: bool,
    pub format_attributes: PlaylistFormatAttribute,
    pub item_id: Vec<u8>,
}

#[derive(Debug, Clone, Default)]
pub struct PlaylistItemAttributeKinds(pub Vec<PlaylistItemAttributeKind>);

impl_deref_wrapped!(PlaylistItemAttributeKinds, Vec<PlaylistItemAttributeKind>);

impl_from_repeated_copy!(PlaylistItemAttributeKind, PlaylistItemAttributeKinds);

#[derive(Debug, Clone)]
pub struct PlaylistPartialAttributes {
    #[allow(dead_code)]
    values: PlaylistAttributes,
    #[allow(dead_code)]
    no_value: PlaylistAttributeKinds,
}

#[derive(Debug, Clone)]
pub struct PlaylistPartialItemAttributes {
    #[allow(dead_code)]
    values: PlaylistItemAttributes,
    #[allow(dead_code)]
    no_value: PlaylistItemAttributeKinds,
}

#[derive(Debug, Clone)]
pub struct PlaylistUpdateAttributes {
    pub new_attributes: PlaylistPartialAttributes,
    pub old_attributes: PlaylistPartialAttributes,
}

#[derive(Debug, Clone)]
pub struct PlaylistUpdateItemAttributes {
    pub index: i32,
    pub new_attributes: PlaylistPartialItemAttributes,
    pub old_attributes: PlaylistPartialItemAttributes,
}

impl TryFrom<&PlaylistAttributesMessage> for PlaylistAttributes {
    type Error = librespot_core::Error;
    fn try_from(attributes: &PlaylistAttributesMessage) -> Result<Self, Self::Error> {
        Ok(Self {
            name: attributes.name().to_owned(),
            description: attributes.description().to_owned(),
            picture: attributes.picture().to_owned(),
            is_collaborative: attributes.collaborative(),
            pl3_version: attributes.pl3_version().to_owned(),
            is_deleted_by_owner: attributes.deleted_by_owner(),
            client_id: attributes.client_id().to_owned(),
            format: attributes.format().to_owned(),
            format_attributes: attributes.format_attributes.as_slice().into(),
            picture_sizes: attributes.picture_size.as_slice().into(),
        })
    }
}

impl From<&[PlaylistFormatAttributeMessage]> for PlaylistFormatAttribute {
    fn from(attributes: &[PlaylistFormatAttributeMessage]) -> Self {
        let format_attributes = attributes
            .iter()
            .map(|attribute| (attribute.key().to_owned(), attribute.value().to_owned()))
            .collect();

        PlaylistFormatAttribute(format_attributes)
    }
}

impl TryFrom<&PlaylistItemAttributesMessage> for PlaylistItemAttributes {
    type Error = librespot_core::Error;
    fn try_from(attributes: &PlaylistItemAttributesMessage) -> Result<Self, Self::Error> {
        Ok(Self {
            added_by: attributes.added_by().to_owned(),
            timestamp: Date::from_timestamp_ms(attributes.timestamp())?,
            seen_at: Date::from_timestamp_ms(attributes.seen_at())?,
            is_public: attributes.public(),
            format_attributes: attributes.format_attributes.as_slice().into(),
            item_id: attributes.item_id().to_owned(),
        })
    }
}
impl TryFrom<&PlaylistPartialAttributesMessage> for PlaylistPartialAttributes {
    type Error = librespot_core::Error;
    fn try_from(attributes: &PlaylistPartialAttributesMessage) -> Result<Self, Self::Error> {
        Ok(Self {
            values: attributes.values.get_or_default().try_into()?,
            no_value: attributes
                .no_value
                .iter()
                .map(|v| v.enum_value_or_default())
                .collect::<Vec<PlaylistAttributeKind>>()
                .as_slice()
                .into(),
        })
    }
}

impl TryFrom<&PlaylistPartialItemAttributesMessage> for PlaylistPartialItemAttributes {
    type Error = librespot_core::Error;
    fn try_from(attributes: &PlaylistPartialItemAttributesMessage) -> Result<Self, Self::Error> {
        Ok(Self {
            values: attributes.values.get_or_default().try_into()?,
            no_value: attributes
                .no_value
                .iter()
                .map(|v| v.enum_value_or_default())
                .collect::<Vec<PlaylistItemAttributeKind>>()
                .as_slice()
                .into(),
        })
    }
}

impl TryFrom<&PlaylistUpdateAttributesMessage> for PlaylistUpdateAttributes {
    type Error = librespot_core::Error;
    fn try_from(update: &PlaylistUpdateAttributesMessage) -> Result<Self, Self::Error> {
        Ok(Self {
            new_attributes: update.new_attributes.get_or_default().try_into()?,
            old_attributes: update.old_attributes.get_or_default().try_into()?,
        })
    }
}

impl TryFrom<&PlaylistUpdateItemAttributesMessage> for PlaylistUpdateItemAttributes {
    type Error = librespot_core::Error;
    fn try_from(update: &PlaylistUpdateItemAttributesMessage) -> Result<Self, Self::Error> {
        Ok(Self {
            index: update.index(),
            new_attributes: update.new_attributes.get_or_default().try_into()?,
            old_attributes: update.old_attributes.get_or_default().try_into()?,
        })
    }
}