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