1#![allow(clippy::upper_case_acronyms)]
4
5use std::{cell::RefCell, cmp, fmt, rc::Rc};
6
7use glib::{
8 translate::{from_glib, ToGlibPtr},
9 value::{SendValue, ToValue},
10 Date,
11};
12use serde::{
13 de,
14 de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor},
15 ser,
16 ser::{Serialize, SerializeSeq, SerializeStruct, SerializeTuple, Serializer},
17};
18
19use crate::{
20 date_time_serde,
21 tags::{GenericTagIter, TagList, TagListRef},
22 value_serde::{DATE_OTHER_TYPE_ID, DATE_TIME_OTHER_TYPE_ID, SAMPLE_OTHER_TYPE_ID},
23 DateTime, Sample, TagMergeMode, TagScope,
24};
25
26macro_rules! ser_tag (
27 ($value:ident, $seq:ident, $t:ty) => (
28 ser_some_value!($value, $t, |_, value| {
29 $seq.serialize_element(&value)
30 })
31 );
32);
33
34macro_rules! ser_opt_tag (
35 ($value:ident, $seq:ident, $t:ty) => (
36 ser_opt_value!($value, $t, |_, value| {
37 $seq.serialize_element(&value)
38 })
39 );
40);
41
42struct TagValuesSer<'a>(Rc<RefCell<GenericTagIter<'a>>>);
48impl<'a> TagValuesSer<'a> {
49 fn from(tags_ser: &TagsSer<'a>) -> Self {
50 skip_assert_initialized!();
51 TagValuesSer(Rc::clone(&tags_ser.1))
52 }
53}
54
55impl Serialize for TagValuesSer<'_> {
56 #[allow(clippy::redundant_closure_call)]
57 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
58 use std::ops::DerefMut;
59
60 let mut tag_iter = self.0.borrow_mut();
61 let mut seq = serializer.serialize_seq(tag_iter.size_hint().1)?;
62 for value in tag_iter.deref_mut() {
63 match value.type_() {
64 glib::Type::F64 => ser_tag!(value, seq, f64),
65 glib::Type::STRING => {
66 ser_some_value!(value, String, |_, value: String| {
68 seq.serialize_element(&value)
69 })
70 }
71 glib::Type::U32 => ser_tag!(value, seq, u32),
72 glib::Type::U64 => ser_tag!(value, seq, u64),
73 type_id => {
74 if *DATE_OTHER_TYPE_ID == type_id {
75 ser_some_value!(value, Date, |_, value: Date| {
77 seq.serialize_element(&date_time_serde::Date::from(value))
80 })
81 } else if *DATE_TIME_OTHER_TYPE_ID == type_id {
82 ser_opt_tag!(value, seq, DateTime)
83 } else if *SAMPLE_OTHER_TYPE_ID == type_id {
84 ser_opt_tag!(value, seq, Sample)
85 } else {
86 Err(ser::Error::custom(format!(
87 "unimplemented `Tag` serialization for type {type_id}",
88 )))
89 }
90 }
91 }?;
92 }
93 seq.end()
94 }
95}
96
97struct TagsSer<'a>(&'a str, Rc<RefCell<GenericTagIter<'a>>>);
98impl<'a> TagsSer<'a> {
99 fn new(name: &'a str, tag_iter: GenericTagIter<'a>) -> Self {
100 skip_assert_initialized!();
101 TagsSer(name, Rc::new(RefCell::new(tag_iter)))
102 }
103}
104
105impl Serialize for TagsSer<'_> {
106 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
107 let mut tup = serializer.serialize_tuple(2)?;
108 tup.serialize_element(self.0)?;
109 tup.serialize_element(&TagValuesSer::from(self))?;
110 tup.end()
111 }
112}
113
114struct TagListSer<'a>(&'a TagListRef);
115impl Serialize for TagListSer<'_> {
116 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
117 let tag_count = self.0.n_tags();
118 match tag_count.cmp(&0) {
119 cmp::Ordering::Greater => {
120 let mut seq = serializer.serialize_seq(Some(tag_count))?;
121 let tag_list_iter = self.0.iter_generic();
122 for (tag_name, tag_iter) in tag_list_iter {
123 seq.serialize_element(&TagsSer::new(tag_name, tag_iter))?;
124 }
125 seq.end()
126 }
127 cmp::Ordering::Equal => {
128 let seq = serializer.serialize_seq(None)?;
129 seq.end()
130 }
131 cmp::Ordering::Less => Err(ser::Error::custom("tag count < 0")),
132 }
133 }
134}
135
136impl Serialize for TagListRef {
137 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
138 let mut tag_list = serializer.serialize_struct("TagList", 3)?;
139 tag_list.serialize_field("scope", &self.scope())?;
140 tag_list.serialize_field("tags", &TagListSer(self))?;
141 tag_list.end()
142 }
143}
144
145impl Serialize for TagList {
146 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
147 self.as_ref().serialize(serializer)
148 }
149}
150
151macro_rules! de_tag(
152 ($tag_name:expr, $seq:expr, $t:ty) => (
153 de_some_send_value!("Tag", $tag_name, $seq, $t)
154 );
155);
156macro_rules! de_opt_tag(
157 ($tag_name:expr, $seq:expr, $t:ty) => (
158 de_opt_send_value!("Tag", $tag_name, $seq, $t)
159 );
160);
161
162struct TagValues<'a>(&'a str, &'a mut TagListRef);
163
164struct TagValuesVisitor<'a>(&'a str, &'a mut TagListRef);
165impl<'de> Visitor<'de> for TagValuesVisitor<'_> {
166 type Value = ();
167
168 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
169 formatter.write_str("a sequence of `Tag` values with the same type")
170 }
171
172 fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<(), A::Error> {
173 let tag_type: glib::Type = unsafe {
174 let tag_name = self.0.to_glib_none();
175 from_glib(crate::ffi::gst_tag_get_type(tag_name.0))
176 };
177
178 loop {
179 let tag_value = match tag_type {
180 glib::Type::F64 => de_tag!(self.0, seq, f64),
181 glib::Type::STRING => {
182 de_tag!(self.0, seq, String)
184 }
185 glib::Type::U32 => de_tag!(self.0, seq, u32),
186 glib::Type::U64 => de_tag!(self.0, seq, u64),
187 type_id => {
188 if *DATE_OTHER_TYPE_ID == type_id {
189 de_send_value!("Tag", self.0, seq, date_time_serde::Date, Date)
193 } else if *DATE_TIME_OTHER_TYPE_ID == type_id {
194 de_opt_tag!(self.0, seq, DateTime)
195 } else if *SAMPLE_OTHER_TYPE_ID == type_id {
196 de_opt_tag!(self.0, seq, Sample)
197 } else {
198 return Err(de::Error::custom(format!(
199 "unimplemented deserialization for `Tag` {} with type `{}`",
200 self.0, type_id,
201 )));
202 }
203 }
204 }?;
205
206 match tag_value {
207 Some(tag_value) => self
208 .1
209 .add_value(self.0, &tag_value, TagMergeMode::Append)
210 .map_err(|_| {
211 de::Error::custom(format!("wrong value type for `Tag` {}", self.0))
212 })?,
213 None => break,
214 }
215 }
216
217 Ok(())
218 }
219}
220
221impl<'de> DeserializeSeed<'de> for TagValues<'_> {
222 type Value = ();
223
224 fn deserialize<D: Deserializer<'de>>(self, deserializer: D) -> Result<(), D::Error> {
225 skip_assert_initialized!();
226 deserializer.deserialize_seq(TagValuesVisitor(self.0, self.1))
227 }
228}
229
230struct TagValuesTuple<'a>(&'a mut TagListRef);
231
232struct TagValuesTupleVisitor<'a>(&'a mut TagListRef);
233impl<'de> Visitor<'de> for TagValuesTupleVisitor<'_> {
234 type Value = ();
235
236 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
237 formatter
238 .write_str("a tuple (`Tag` name: `String`, seq. of `Tag` values with the same type)")
239 }
240
241 fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<(), A::Error> {
242 let name = seq
243 .next_element::<String>()
244 .map_err(|err| de::Error::custom(format!("Error reading Tag name. {err:?}")))?
245 .ok_or_else(|| de::Error::custom("Expected a name for the `Tag` name"))?;
246 seq.next_element_seed(TagValues(name.as_str(), self.0))?
247 .ok_or_else(|| de::Error::custom("Expected a seq of values for the `Tag`"))
248 }
249}
250
251impl<'de> DeserializeSeed<'de> for TagValuesTuple<'_> {
252 type Value = ();
253
254 fn deserialize<D: Deserializer<'de>>(self, deserializer: D) -> Result<(), D::Error> {
255 skip_assert_initialized!();
256 deserializer.deserialize_tuple(2, TagValuesTupleVisitor(self.0))
257 }
258}
259
260struct TagsDe(TagList);
261
262struct TagsVisitor;
263impl<'de> Visitor<'de> for TagsVisitor {
264 type Value = TagsDe;
265
266 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
267 formatter.write_str("a sequence of `Tag`s")
268 }
269
270 fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
271 let mut tag_list = TagList::new();
272 {
273 let tag_list = tag_list.get_mut().unwrap();
274 while seq.next_element_seed(TagValuesTuple(tag_list))?.is_some() {
275 }
277 }
278 Ok(TagsDe(tag_list))
279 }
280}
281
282impl<'de> Deserialize<'de> for TagsDe {
283 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
284 skip_assert_initialized!();
285 deserializer.deserialize_seq(TagsVisitor)
286 }
287}
288
289#[derive(serde::Deserialize)]
290struct TagListDe {
291 scope: TagScope,
292 tags: TagsDe,
293}
294
295impl From<TagListDe> for TagList {
296 fn from(tag_list_de: TagListDe) -> Self {
297 skip_assert_initialized!();
298 let mut tag_list = tag_list_de.tags.0;
299 tag_list.get_mut().unwrap().set_scope(tag_list_de.scope);
300
301 tag_list
302 }
303}
304
305impl<'de> Deserialize<'de> for TagList {
306 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
307 skip_assert_initialized!();
308 TagListDe::deserialize(deserializer).map(|tag_list_de| tag_list_de.into())
309 }
310}
311
312#[cfg(test)]
313mod tests {
314 use crate::{tags::*, Buffer, ClockTime, Sample, TagMergeMode, TagScope};
315
316 #[test]
317 fn test_serialize() {
318 crate::init().unwrap();
319
320 let mut tags = TagList::new();
321 assert_eq!(tags.to_string(), "taglist;");
322 {
323 let tags = tags.get_mut().unwrap();
324 tags.add::<Title>(&"a title", TagMergeMode::Append); tags.add::<Title>(&"another title", TagMergeMode::Append); tags.add::<Duration>(&(ClockTime::SECOND * 120), TagMergeMode::Append); tags.add::<Bitrate>(&96_000, TagMergeMode::Append); tags.add::<TrackGain>(&1f64, TagMergeMode::Append); tags.add::<Date>(
330 &glib::Date::from_dmy(28, glib::DateMonth::May, 2018).unwrap(),
331 TagMergeMode::Append,
332 );
333 tags.add::<DateTime>(
334 &crate::DateTime::from_ymd(2018, 5, 28).unwrap(),
335 TagMergeMode::Append,
336 );
337
338 let sample = {
339 let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]);
340 {
341 let buffer = buffer.get_mut().unwrap();
342 buffer.set_offset(0);
343 buffer.set_offset_end(0);
344 }
345 Sample::builder().buffer(&buffer).build()
346 };
347 tags.add::<Image>(&sample, TagMergeMode::Append); }
349
350 let pretty_config = ron::ser::PrettyConfig::new().new_line("".to_string());
351
352 let res = ron::ser::to_string_pretty(&tags, pretty_config);
353 assert_eq!(
354 Ok(concat!(
355 r#"("#,
356 r#" scope: Stream,"#,
357 r#" tags: ["#,
358 r#" ("title", ["#,
359 r#" "a title","#,
360 r#" "another title","#,
361 r#" ]),"#,
362 r#" ("duration", ["#,
363 r#" 120000000000,"#,
364 r#" ]),"#,
365 r#" ("bitrate", ["#,
366 r#" 96000,"#,
367 r#" ]),"#,
368 r#" ("replaygain-track-gain", ["#,
369 r#" 1.0,"#,
370 r#" ]),"#,
371 r#" ("date", ["#,
372 r#" YMD(2018, 5, 28),"#,
373 r#" ]),"#,
374 r#" ("datetime", ["#,
375 r#" Some(YMD(2018, 5, 28)),"#,
376 r#" ]),"#,
377 r#" ("image", ["#,
378 r#" Some(("#,
379 r#" buffer: Some(("#,
380 r#" pts: None,"#,
381 r#" dts: None,"#,
382 r#" duration: None,"#,
383 r#" offset: 0,"#,
384 r#" offset_end: 0,"#,
385 r#" flags: "","#,
386 r#" buffer: b"\x01\x02\x03\x04","#,
387 r#" )),"#,
388 r#" buffer_list: None,"#,
389 r#" caps: None,"#,
390 r#" segment: Some(("#,
391 r#" flags: "","#,
392 r#" rate: 1.0,"#,
393 r#" applied_rate: 1.0,"#,
394 r#" format: Time,"#,
395 r#" base: 0,"#,
396 r#" offset: 0,"#,
397 r#" start: 0,"#,
398 r#" stop: -1,"#,
399 r#" time: 0,"#,
400 r#" position: 0,"#,
401 r#" duration: -1,"#,
402 r#" )),"#,
403 r#" info: None,"#,
404 r#" )),"#,
405 r#" ]),"#,
406 r#" ],"#,
407 r#")"#,
408 )
409 .to_owned()),
410 res,
411 );
412 }
413
414 #[test]
415 fn test_deserialize() {
416 crate::init().unwrap();
417
418 let tag_list_ron = r#"
419 (
420 scope: Global,
421 tags: [
422 ("title", [
423 "a title",
424 "another title",
425 ]),
426 ("duration", [120000000000]),
427 ("bitrate", [96000]),
428 ("replaygain-track-gain", [1.0]),
429 ("date", [
430 YMD(2018, 5, 28),
431 ]),
432 ("datetime", [
433 Some(YMD(2018, 5, 28)),
434 ]),
435 ("image", [
436 Some((
437 buffer: Some((
438 pts: None,
439 dts: None,
440 duration: None,
441 offset: 0,
442 offset_end: 0,
443 flags: "",
444 buffer: b"\x01\x02\x03\x04",
445 )),
446 buffer_list: None,
447 caps: None,
448 segment: None,
449 info: None,
450 )),
451 ])
452 ],
453 )
454 "#;
455 let tags: TagList = ron::de::from_str(tag_list_ron).unwrap();
456 assert_eq!(tags.scope(), TagScope::Global);
457
458 assert_eq!(tags.index::<Title>(0).unwrap().get(), "a title");
459 assert_eq!(tags.index::<Title>(1).unwrap().get(), "another title");
460 assert_eq!(tags.index::<Title>(1).unwrap().get(), "another title");
461 assert_eq!(
462 tags.index::<Duration>(0).unwrap().get(),
463 120 * ClockTime::SECOND,
464 );
465 assert_eq!(tags.index::<Bitrate>(0).unwrap().get(), 96_000);
466 assert!((tags.index::<TrackGain>(0).unwrap().get() - 1f64).abs() < f64::EPSILON);
467 assert_eq!(
468 tags.index::<Date>(0).unwrap().get(),
469 glib::Date::from_dmy(28, glib::DateMonth::May, 2018).unwrap()
470 );
471 assert_eq!(
472 tags.index::<DateTime>(0).unwrap().get(),
473 crate::DateTime::from_ymd(2018, 5, 28).unwrap()
474 );
475 let sample = tags.index::<Image>(0).unwrap().get();
476 let buffer = sample.buffer().unwrap();
477 {
478 let data = buffer.map_readable().unwrap();
479 assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice());
480 }
481
482 let tag_json = r#"
483 {
484 "scope":"Global",
485 "tags":[
486 ["title", ["a title", "another title"]],
487 ["duration", [120000000000]],
488 ["bitrate", [96000]],
489 ["replaygain-track-gain", [1]],
490 ["date",[{"YMD":[2018,5,28]}]],
491 ["datetime",[{"YMD":[2018,5,28]}]],
492 ["image",[{"buffer":{"pts":null,"dts":null,"duration":null,"offset":0,"offset_end":0,"flags":"","buffer":[1,2,3,4]},"buffer_list":null,"caps":null,"segment":null,"info":null}]]
493 ]
494 }
495 "#;
496 let tags: TagList = serde_json::from_str(tag_json).unwrap();
497 assert_eq!(tags.scope(), TagScope::Global);
498
499 assert_eq!(tags.index::<Title>(0).unwrap().get(), "a title");
500 assert_eq!(tags.index::<Title>(1).unwrap().get(), "another title");
501 assert_eq!(tags.index::<Bitrate>(0).unwrap().get(), 96_000);
502 assert!((tags.index::<TrackGain>(0).unwrap().get() - 1f64).abs() < f64::EPSILON);
503 assert_eq!(
504 tags.index::<Date>(0).unwrap().get(),
505 glib::Date::from_dmy(28, glib::DateMonth::May, 2018).unwrap()
506 );
507 assert_eq!(
508 tags.index::<DateTime>(0).unwrap().get(),
509 crate::DateTime::from_ymd(2018, 5, 28).unwrap()
510 );
511 let sample = tags.index::<Image>(0).unwrap().get();
512 let buffer = sample.buffer().unwrap();
513 {
514 let data = buffer.map_readable().unwrap();
515 assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice());
516 }
517 }
518
519 #[test]
520 fn test_serde_roundtrip() {
521 crate::init().unwrap();
522
523 let mut tags = TagList::new();
524 assert_eq!(tags.to_string(), "taglist;");
525 {
526 let tags = tags.get_mut().unwrap();
527 tags.set_scope(TagScope::Global);
528 tags.add::<Title>(&"a title", TagMergeMode::Append); tags.add::<Title>(&"another title", TagMergeMode::Append); tags.add::<Duration>(&(ClockTime::SECOND * 120), TagMergeMode::Append); tags.add::<Bitrate>(&96_000, TagMergeMode::Append); tags.add::<TrackGain>(&1f64, TagMergeMode::Append); tags.add::<Date>(
534 &glib::Date::from_dmy(28, glib::DateMonth::May, 2018).unwrap(),
535 TagMergeMode::Append,
536 );
537 tags.add::<DateTime>(
538 &crate::DateTime::from_ymd(2018, 5, 28).unwrap(),
539 TagMergeMode::Append,
540 );
541
542 let sample = {
543 let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]);
544 {
545 let buffer = buffer.get_mut().unwrap();
546 buffer.set_offset(0);
547 buffer.set_offset_end(0);
548 }
549 Sample::builder().buffer(&buffer).build()
550 };
551 tags.add::<Image>(&sample, TagMergeMode::Append); }
553 let tags_ser = ron::ser::to_string(&tags).unwrap();
554
555 let tags_de: TagList = ron::de::from_str(tags_ser.as_str()).unwrap();
556 assert_eq!(tags_de.scope(), TagScope::Global);
557
558 assert_eq!(
559 tags_de.index::<Title>(0).unwrap().get(),
560 tags.index::<Title>(0).unwrap().get(),
561 );
562 assert_eq!(
563 tags_de.index::<Title>(1).unwrap().get(),
564 tags.index::<Title>(1).unwrap().get(),
565 );
566 assert_eq!(
567 tags_de.index::<Duration>(0).unwrap().get(),
568 tags.index::<Duration>(0).unwrap().get(),
569 );
570 assert_eq!(
571 tags_de.index::<Bitrate>(0).unwrap().get(),
572 tags.index::<Bitrate>(0).unwrap().get(),
573 );
574 assert!(
575 (tags_de.index::<TrackGain>(0).unwrap().get()
576 - tags.index::<TrackGain>(0).unwrap().get())
577 .abs()
578 < f64::EPSILON
579 );
580 assert_eq!(
581 tags_de.index::<Date>(0).unwrap().get(),
582 tags.index::<Date>(0).unwrap().get(),
583 );
584 assert_eq!(
585 tags.index::<DateTime>(0).unwrap().get(),
586 crate::DateTime::from_ymd(2018, 5, 28).unwrap()
587 );
588 let sample = tags.index::<Image>(0).unwrap().get();
589 let buffer = sample.buffer().unwrap();
590 {
591 let data = buffer.map_readable().unwrap();
592 assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice());
593 }
594 }
595}