From b6367525ffb189aef91a01d043c4c3e17de523c6 Mon Sep 17 00:00:00 2001 From: meh Date: Sat, 20 Mar 2021 23:12:06 +0100 Subject: [PATCH] feat(dictionary): add serde support --- src/format/chapter/chapter_mut.rs | 4 +- src/util/dictionary/owned.rs | 84 ++++++++++++++++++++++++++----- 2 files changed, 74 insertions(+), 14 deletions(-) diff --git a/src/format/chapter/chapter_mut.rs b/src/format/chapter/chapter_mut.rs index c71296c..a055baa 100644 --- a/src/format/chapter/chapter_mut.rs +++ b/src/format/chapter/chapter_mut.rs @@ -56,8 +56,8 @@ impl<'a> ChapterMut<'a> { // dictionary.set() allocates the AVDictionary the first time a key/value is // inserted so we want to update the metadata dictionary afterwards unsafe { - let dictionary = Dictionary::own(self.metadata().as_mut_ptr()); - dictionary.as_mut().set(key.as_ref(), value.as_ref()); + let mut dictionary = Dictionary::own(self.metadata().as_mut_ptr()); + dictionary.set(key.as_ref(), value.as_ref()); (*self.as_mut_ptr()).metadata = dictionary.disown(); } } diff --git a/src/util/dictionary/owned.rs b/src/util/dictionary/owned.rs index f2aed24..33fc3a8 100644 --- a/src/util/dictionary/owned.rs +++ b/src/util/dictionary/owned.rs @@ -1,6 +1,6 @@ use std::{fmt, iter::FromIterator, ptr}; -use super::{immutable, mutable}; +use super::{immutable, mutable, Iter}; use crate::ffi::*; pub struct Owned { @@ -44,8 +44,8 @@ impl Owned { unsafe { immutable::Ref::wrap(self.ptr) } } - pub fn as_mut(&self) -> mutable::Ref { - unsafe { mutable::Ref::wrap(self.ptr) } + pub fn len(&self) -> usize { + self.as_ref().len() } pub fn iter(&self) -> Iter<'_> { @@ -53,17 +53,22 @@ impl Owned { } pub fn set(&mut self, key: &str, value: &str) -> &mut Self { - self.as_mut().set(key, value); + unsafe { + let mut mutable = mutable::Ref::wrap(self.ptr); + mutable.set(key, value); + self.ptr = mutable.as_mut_ptr(); + } + self } } impl<'a> FromIterator<(&'a str, &'a str)> for Owned { fn from_iter>(iterator: T) -> Self { - let result = Owned::new(); + let mut result = Owned::new(); for (key, value) in iterator { - result.as_mut().set(key, value); + result.set(key, value); } result @@ -72,10 +77,10 @@ impl<'a> FromIterator<(&'a str, &'a str)> for Owned { impl<'a> FromIterator<&'a (&'a str, &'a str)> for Owned { fn from_iter>(iterator: T) -> Self { - let result = Owned::new(); + let mut result = Owned::new(); for &(key, value) in iterator { - result.as_mut().set(key, value); + result.set(key, value); } result @@ -84,10 +89,10 @@ impl<'a> FromIterator<&'a (&'a str, &'a str)> for Owned { impl FromIterator<(String, String)> for Owned { fn from_iter>(iterator: T) -> Self { - let result = Owned::new(); + let mut result = Owned::new(); for (key, value) in iterator { - result.as_mut().set(&key, &value); + result.set(&key, &value); } result @@ -96,10 +101,10 @@ impl FromIterator<(String, String)> for Owned { impl<'a> FromIterator<&'a (String, String)> for Owned { fn from_iter>(iterator: T) -> Self { - let result = Owned::new(); + let mut result = Owned::new(); for &(ref key, ref value) in iterator { - result.as_mut().set(key, value); + result.set(key, value); } result @@ -136,3 +141,58 @@ impl fmt::Debug for Owned { unsafe { mutable::Ref::wrap(self.ptr) }.fmt(fmt) } } + +#[cfg(feature = "serde")] +mod serde { + use std::fmt; + + use serde::{ + de::{Deserialize, Deserializer, MapAccess, Visitor}, + ser::{Serialize, SerializeMap, Serializer}, + }; + + impl Serialize for super::Owned { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut map = serializer.serialize_map(Some(self.len()))?; + for (k, v) in self.iter() { + map.serialize_entry(k, v)?; + } + map.end() + } + } + + struct DictionaryVisitor; + + impl<'de> Visitor<'de> for DictionaryVisitor { + type Value = super::Owned; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("an ffmpeg dictionary") + } + + fn visit_map(self, mut access: M) -> Result + where + M: MapAccess<'de>, + { + let mut map = super::Owned::new(); + + while let Some((key, value)) = access.next_entry()? { + map.set(key, value); + } + + Ok(map) + } + } + + impl<'de> Deserialize<'de> for super::Owned { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_map(DictionaryVisitor) + } + } +}