librespot_metadata/playlist/
attribute.rs1use std::{
2 collections::HashMap,
3 fmt::Debug,
4 ops::{Deref, DerefMut},
5};
6
7use crate::{
8 image::PictureSizes,
9 util::{impl_deref_wrapped, impl_from_repeated_copy},
10};
11
12use librespot_core::date::Date;
13
14use librespot_protocol as protocol;
15use protocol::playlist4_external::FormatListAttribute as PlaylistFormatAttributeMessage;
16pub use protocol::playlist4_external::ItemAttributeKind as PlaylistItemAttributeKind;
17use protocol::playlist4_external::ItemAttributes as PlaylistItemAttributesMessage;
18use protocol::playlist4_external::ItemAttributesPartialState as PlaylistPartialItemAttributesMessage;
19pub use protocol::playlist4_external::ListAttributeKind as PlaylistAttributeKind;
20use protocol::playlist4_external::ListAttributes as PlaylistAttributesMessage;
21use protocol::playlist4_external::ListAttributesPartialState as PlaylistPartialAttributesMessage;
22use protocol::playlist4_external::UpdateItemAttributes as PlaylistUpdateItemAttributesMessage;
23use protocol::playlist4_external::UpdateListAttributes as PlaylistUpdateAttributesMessage;
24
25#[derive(Debug, Clone)]
26pub struct PlaylistAttributes {
27 pub name: String,
28 pub description: String,
29 pub picture: Vec<u8>,
30 pub is_collaborative: bool,
31 pub pl3_version: String,
32 pub is_deleted_by_owner: bool,
33 pub client_id: String,
34 pub format: String,
35 pub format_attributes: PlaylistFormatAttribute,
36 pub picture_sizes: PictureSizes,
37}
38
39#[derive(Debug, Clone, Default)]
40pub struct PlaylistAttributeKinds(pub Vec<PlaylistAttributeKind>);
41
42impl_deref_wrapped!(PlaylistAttributeKinds, Vec<PlaylistAttributeKind>);
43
44impl_from_repeated_copy!(PlaylistAttributeKind, PlaylistAttributeKinds);
45
46#[derive(Debug, Clone, Default)]
47pub struct PlaylistFormatAttribute(pub HashMap<String, String>);
48
49impl_deref_wrapped!(PlaylistFormatAttribute, HashMap<String, String>);
50
51#[derive(Debug, Clone)]
52pub struct PlaylistItemAttributes {
53 pub added_by: String,
54 pub timestamp: Date,
55 pub seen_at: Date,
56 pub is_public: bool,
57 pub format_attributes: PlaylistFormatAttribute,
58 pub item_id: Vec<u8>,
59}
60
61#[derive(Debug, Clone, Default)]
62pub struct PlaylistItemAttributeKinds(pub Vec<PlaylistItemAttributeKind>);
63
64impl_deref_wrapped!(PlaylistItemAttributeKinds, Vec<PlaylistItemAttributeKind>);
65
66impl_from_repeated_copy!(PlaylistItemAttributeKind, PlaylistItemAttributeKinds);
67
68#[derive(Debug, Clone)]
69pub struct PlaylistPartialAttributes {
70 #[allow(dead_code)]
71 values: PlaylistAttributes,
72 #[allow(dead_code)]
73 no_value: PlaylistAttributeKinds,
74}
75
76#[derive(Debug, Clone)]
77pub struct PlaylistPartialItemAttributes {
78 #[allow(dead_code)]
79 values: PlaylistItemAttributes,
80 #[allow(dead_code)]
81 no_value: PlaylistItemAttributeKinds,
82}
83
84#[derive(Debug, Clone)]
85pub struct PlaylistUpdateAttributes {
86 pub new_attributes: PlaylistPartialAttributes,
87 pub old_attributes: PlaylistPartialAttributes,
88}
89
90#[derive(Debug, Clone)]
91pub struct PlaylistUpdateItemAttributes {
92 pub index: i32,
93 pub new_attributes: PlaylistPartialItemAttributes,
94 pub old_attributes: PlaylistPartialItemAttributes,
95}
96
97impl TryFrom<&PlaylistAttributesMessage> for PlaylistAttributes {
98 type Error = librespot_core::Error;
99 fn try_from(attributes: &PlaylistAttributesMessage) -> Result<Self, Self::Error> {
100 Ok(Self {
101 name: attributes.name().to_owned(),
102 description: attributes.description().to_owned(),
103 picture: attributes.picture().to_owned(),
104 is_collaborative: attributes.collaborative(),
105 pl3_version: attributes.pl3_version().to_owned(),
106 is_deleted_by_owner: attributes.deleted_by_owner(),
107 client_id: attributes.client_id().to_owned(),
108 format: attributes.format().to_owned(),
109 format_attributes: attributes.format_attributes.as_slice().into(),
110 picture_sizes: attributes.picture_size.as_slice().into(),
111 })
112 }
113}
114
115impl From<&[PlaylistFormatAttributeMessage]> for PlaylistFormatAttribute {
116 fn from(attributes: &[PlaylistFormatAttributeMessage]) -> Self {
117 let format_attributes = attributes
118 .iter()
119 .map(|attribute| (attribute.key().to_owned(), attribute.value().to_owned()))
120 .collect();
121
122 PlaylistFormatAttribute(format_attributes)
123 }
124}
125
126impl TryFrom<&PlaylistItemAttributesMessage> for PlaylistItemAttributes {
127 type Error = librespot_core::Error;
128 fn try_from(attributes: &PlaylistItemAttributesMessage) -> Result<Self, Self::Error> {
129 Ok(Self {
130 added_by: attributes.added_by().to_owned(),
131 timestamp: Date::from_timestamp_ms(attributes.timestamp())?,
132 seen_at: Date::from_timestamp_ms(attributes.seen_at())?,
133 is_public: attributes.public(),
134 format_attributes: attributes.format_attributes.as_slice().into(),
135 item_id: attributes.item_id().to_owned(),
136 })
137 }
138}
139impl TryFrom<&PlaylistPartialAttributesMessage> for PlaylistPartialAttributes {
140 type Error = librespot_core::Error;
141 fn try_from(attributes: &PlaylistPartialAttributesMessage) -> Result<Self, Self::Error> {
142 Ok(Self {
143 values: attributes.values.get_or_default().try_into()?,
144 no_value: attributes
145 .no_value
146 .iter()
147 .map(|v| v.enum_value_or_default())
148 .collect::<Vec<PlaylistAttributeKind>>()
149 .as_slice()
150 .into(),
151 })
152 }
153}
154
155impl TryFrom<&PlaylistPartialItemAttributesMessage> for PlaylistPartialItemAttributes {
156 type Error = librespot_core::Error;
157 fn try_from(attributes: &PlaylistPartialItemAttributesMessage) -> Result<Self, Self::Error> {
158 Ok(Self {
159 values: attributes.values.get_or_default().try_into()?,
160 no_value: attributes
161 .no_value
162 .iter()
163 .map(|v| v.enum_value_or_default())
164 .collect::<Vec<PlaylistItemAttributeKind>>()
165 .as_slice()
166 .into(),
167 })
168 }
169}
170
171impl TryFrom<&PlaylistUpdateAttributesMessage> for PlaylistUpdateAttributes {
172 type Error = librespot_core::Error;
173 fn try_from(update: &PlaylistUpdateAttributesMessage) -> Result<Self, Self::Error> {
174 Ok(Self {
175 new_attributes: update.new_attributes.get_or_default().try_into()?,
176 old_attributes: update.old_attributes.get_or_default().try_into()?,
177 })
178 }
179}
180
181impl TryFrom<&PlaylistUpdateItemAttributesMessage> for PlaylistUpdateItemAttributes {
182 type Error = librespot_core::Error;
183 fn try_from(update: &PlaylistUpdateItemAttributesMessage) -> Result<Self, Self::Error> {
184 Ok(Self {
185 index: update.index(),
186 new_attributes: update.new_attributes.get_or_default().try_into()?,
187 old_attributes: update.old_attributes.get_or_default().try_into()?,
188 })
189 }
190}