1type NaiveDate = String; use serde::{de::Error, ser::Serializer, Deserialize, Serialize};
20use std::borrow::Cow;
21
22#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
24#[serde(rename = "DJ_PLAYLISTS")]
25pub struct Document {
26 #[serde(rename = "@Version")]
30 version: String,
31 #[serde(rename = "PRODUCT")]
32 product: Product,
33 #[serde(rename = "COLLECTION")]
34 collection: Collection,
35 #[serde(rename = "PLAYLISTS")]
36 playlists: Playlists,
37}
38
39#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
40struct Product {
41 #[serde(rename = "@Name")]
45 name: String,
46 #[serde(rename = "@Version")]
48 version: String,
49 #[serde(rename = "@Company")]
51 company: String,
52}
53
54#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
56struct Collection {
57 #[serde(rename = "@Entries")]
59 entries: i32,
60 #[serde(rename = "TRACK")]
61 track: Vec<Track>,
62}
63
64#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
66struct Track {
67 #[serde(rename = "@TrackID")]
69 trackid: i32,
70 #[serde(rename = "@Name")]
72 name: Option<String>,
73 #[serde(rename = "@Artist")]
75 artist: Option<String>,
76 #[serde(rename = "@Composer")]
78 composer: Option<String>,
79 #[serde(rename = "@Album")]
81 album: Option<String>,
82 #[serde(rename = "@Grouping")]
84 grouping: Option<String>,
85 #[serde(rename = "@Genre")]
87 genre: Option<String>,
88 #[serde(rename = "@Kind")]
90 kind: Option<String>,
91 #[serde(rename = "@Size")]
94 size: Option<i64>,
95 #[serde(rename = "@TotalTime")]
98 totaltime: Option<f64>,
99 #[serde(rename = "@DiscNumber")]
101 discnumber: Option<i32>,
102 #[serde(rename = "@TrackNumber")]
104 tracknumber: Option<i32>,
105 #[serde(rename = "@Year")]
107 year: Option<i32>,
108 #[serde(rename = "@AverageBpm")]
111 averagebpm: Option<f64>,
112 #[serde(rename = "@DateModified")]
115 #[serde(skip_serializing_if = "Option::is_none")]
116 datemodified: Option<NaiveDate>,
117 #[serde(rename = "@DateAdded")]
120 #[serde(skip_serializing_if = "Option::is_none")]
121 dateadded: Option<NaiveDate>,
122 #[serde(rename = "@BitRate")]
125 bitrate: Option<i32>,
126 #[serde(rename = "@SampleRate")]
129 samplerate: Option<f64>,
130 #[serde(rename = "@Comments")]
132 comments: Option<String>,
133 #[serde(rename = "@PlayCount")]
135 playcount: Option<i32>,
136 #[serde(rename = "@LastPlayed")]
139 #[serde(skip_serializing_if = "Option::is_none")]
140 lastplayed: Option<NaiveDate>,
141 #[serde(rename = "@Rating")]
144 rating: Option<i32>,
145 #[serde(rename = "@Location")]
148 location: String,
149 #[serde(rename = "@Remixer")]
151 remixer: Option<String>,
152 #[serde(rename = "@Tonality")]
154 tonality: Option<String>,
155 #[serde(rename = "@Label")]
157 label: Option<String>,
158 #[serde(rename = "@Mix")]
160 mix: Option<String>,
161 #[serde(rename = "@Colour")]
164 #[serde(skip_serializing_if = "Option::is_none")]
165 colour: Option<String>,
166 #[serde(rename = "TEMPO")]
167 #[serde(skip_serializing_if = "Vec::is_empty")]
168 #[serde(default)]
169 tempos: Vec<Tempo>,
170 #[serde(rename = "POSITION_MARK")]
171 #[serde(skip_serializing_if = "Vec::is_empty")]
172 #[serde(default)]
173 position_marks: Vec<PositionMark>,
174}
175
176#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
178enum StarRating {
179 Zero,
180 One,
181 Two,
182 Three,
183 Four,
184 Five,
185 Unknown(i32),
186}
187
188#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
190struct Tempo {
191 #[serde(rename = "@Inizio")]
194 inizio: f64,
195 #[serde(rename = "@Bpm")]
198 bpm: f64,
199 #[serde(rename = "@Metro")]
202 metro: String,
203 #[serde(rename = "@Battito")]
206 battito: i32,
207}
208
209#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
211struct PositionMark {
212 #[serde(rename = "@Name")]
214 name: String,
215 #[serde(rename = "@Type")]
218 mark_type: i32,
219 #[serde(rename = "@Start")]
222 start: f64,
223 #[serde(rename = "@End")]
226 #[serde(skip_serializing_if = "Option::is_none")]
227 end: Option<f64>,
228 #[serde(rename = "@Num")]
231 num: i32,
232}
233
234#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
235struct Playlists {
236 #[serde(rename = "NODE")]
237 node: PlaylistFolderNode,
238}
239
240#[derive(Debug, PartialEq, Clone, Serialize)]
241#[serde(tag = "@Type")]
242enum PlaylistGenericNode {
243 #[serde(rename = "0")]
244 Folder(PlaylistFolderNode),
245 #[serde(rename = "1")]
246 Playlist(PlaylistPlaylistNode),
247}
248
249impl<'de> Deserialize<'de> for PlaylistGenericNode {
250 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
251 where
252 D: serde::Deserializer<'de>,
253 {
254 struct PlaylistGenericNodeVisitor;
255
256 impl<'de> serde::de::Visitor<'de> for PlaylistGenericNodeVisitor {
257 type Value = PlaylistGenericNode;
258
259 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
260 formatter.write_str("struct PlaylistGenericNode")
261 }
262
263 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
264 where
265 A: serde::de::MapAccess<'de>,
266 {
267 let mut node_type = None;
268 let mut name = None;
269 let mut count = None;
270 let mut key_type = None;
271 let mut entries = None;
272
273 while let Some(key) = map.next_key::<Cow<'_, str>>()? {
274 match key.as_ref() {
275 "@Name" => name = map.next_value::<Cow<'_, str>>()?.into(),
276 "@Type" => node_type = map.next_value::<Cow<'_, str>>()?.into(),
277 "@Count" => count = map.next_value::<usize>()?.into(),
278 "@KeyType" => key_type = map.next_value::<Cow<'_, str>>()?.into(),
279 "@Entries" => entries = map.next_value::<usize>()?.into(),
280 unknown => {
281 return Err(A::Error::unknown_field(
282 unknown,
283 &["@Name", "@Type", "@Count", "@KeyType", "@Entries"],
284 ));
285 }
286 }
287
288 match node_type.as_deref() {
289 Some("0") => {
290 if let (Some(n), Some(_c)) = (&name, count) {
291 let nodes = {
292 #[derive(serde::Deserialize)]
294 struct Nodes {
295 #[serde(rename = "NODE")]
296 content: Vec<PlaylistGenericNode>,
297 }
298 let de = serde::de::value::MapAccessDeserializer::new(map);
299 Nodes::deserialize(de)?.content
300 };
301 return Ok(PlaylistGenericNode::Folder(PlaylistFolderNode {
303 name: n.to_string(),
304 nodes,
305 }));
306 }
307 }
308 Some("1") => {
309 if let (Some(n), Some(_c), Some(t)) = (&name, entries, &key_type) {
310 let tracks = {
311 #[derive(serde::Deserialize)]
313 struct Tracks {
314 #[serde(rename = "TRACK")]
315 content: Vec<PlaylistTrack>,
316 }
317 let de = serde::de::value::MapAccessDeserializer::new(map);
318 Tracks::deserialize(de)?.content
319 };
320 return Ok(PlaylistGenericNode::Playlist(PlaylistPlaylistNode {
322 name: n.to_string(),
323 keytype: t.to_string(),
324 tracks,
325 }));
326 }
327 }
328 Some(unknown) => {
329 return Err(A::Error::unknown_variant(unknown, &["0", "1"]))
330 }
331 None => (),
332 }
333 }
334
335 match node_type.as_deref() {
336 Some("0") => {
337 if name.is_none() {
338 Err(A::Error::missing_field("@Name"))
339 } else {
340 Err(A::Error::missing_field("@Count"))
341 }
342 }
343 Some("1") => {
344 if name.is_none() {
345 Err(A::Error::missing_field("@Name"))
346 } else if entries.is_none() {
347 Err(A::Error::missing_field("@Entries"))
348 } else {
349 Err(A::Error::missing_field("@KeyType"))
350 }
351 }
352 _ => Err(A::Error::missing_field("@Type")),
353 }
354 }
355 }
356
357 deserializer.deserialize_map(PlaylistGenericNodeVisitor)
358 }
359}
360
361#[derive(Debug, PartialEq, Clone, Deserialize)]
362struct PlaylistFolderNode {
363 #[serde(rename = "@Name")]
365 name: String,
366 #[serde(rename = "NODE")]
370 nodes: Vec<PlaylistGenericNode>,
371}
372
373impl Serialize for PlaylistFolderNode {
374 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
375 where
376 S: Serializer,
377 {
378 #[derive(Serialize)]
379 struct Value<'a> {
380 #[serde(rename = "@Name")]
382 name: &'a String,
383 #[serde(rename = "@Count")]
385 count: usize,
386 #[serde(rename = "NODE")]
388 nodes: &'a Vec<PlaylistGenericNode>,
389 }
390
391 let value = Value {
392 name: &self.name,
393 count: self.nodes.len(),
394 nodes: &self.nodes,
395 };
396
397 value.serialize(serializer)
398 }
399}
400
401#[derive(Debug, PartialEq, Clone, Deserialize)]
402struct PlaylistPlaylistNode {
403 #[serde(rename = "@Name")]
405 name: String,
406 #[serde(rename = "@KeyType")]
411 keytype: String,
412 #[serde(rename = "TRACK")]
413 tracks: Vec<PlaylistTrack>,
414}
415
416impl Serialize for PlaylistPlaylistNode {
417 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
418 where
419 S: Serializer,
420 {
421 #[derive(Serialize)]
422 struct Value<'a> {
423 #[serde(rename = "@Name")]
425 name: &'a String,
426 #[serde(rename = "@Entries")]
428 entries: usize,
429 #[serde(rename = "@KeyType")]
432 keytype: &'a String,
433 #[serde(rename = "TRACK")]
434 tracks: &'a Vec<PlaylistTrack>,
435 }
436
437 let value = Value {
438 name: &self.name,
439 entries: self.tracks.len(),
440 keytype: &self.keytype,
441 tracks: &self.tracks,
442 };
443
444 value.serialize(serializer)
445 }
446}
447
448#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
449struct PlaylistTrack {
450 #[serde(rename = "@Key")]
453 key: i32,
454}