From 3c9c4f926faa8e7911278cb039b6d3263b187527 Mon Sep 17 00:00:00 2001 From: lummax Date: Wed, 19 Aug 2015 13:21:23 +0200 Subject: [PATCH] util/dictionary: implement Iterator and IntoIterator --- src/util/dictionary.rs | 58 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/util/dictionary.rs b/src/util/dictionary.rs index 912328f..c8fb868 100644 --- a/src/util/dictionary.rs +++ b/src/util/dictionary.rs @@ -1,5 +1,7 @@ use std::marker::PhantomData; use std::ptr; +use std::ffi::{CStr, CString}; +use std::str::from_utf8_unchecked; use ffi::*; @@ -37,6 +39,12 @@ impl<'a> Dictionary<'a> { pub fn new() -> Self { Dictionary { ptr: ptr::null_mut(), _own: true, _marker: PhantomData } } + + pub fn iter(&self) -> DictionaryIter { + unsafe { + DictionaryIter::new(self.as_ptr()) + } + } } impl<'a> Drop for Dictionary<'a> { @@ -48,3 +56,53 @@ impl<'a> Drop for Dictionary<'a> { } } } + +pub struct DictionaryIter<'a> { + ptr: *const AVDictionary, + cur: *mut AVDictionaryEntry, + + _marker: PhantomData<&'a Dictionary<'a>>, +} + +impl<'a> DictionaryIter<'a> { + pub fn new(dictionary: *const AVDictionary) -> Self { + DictionaryIter { + ptr: dictionary, + cur: ptr::null_mut(), + + _marker: PhantomData + } + } +} + +impl<'a> Iterator for DictionaryIter<'a> { + type Item = (&'a str, &'a str); + + fn next(&mut self) -> Option<::Item> { + unsafe { + let empty = CString::new("").unwrap(); + let entry = av_dict_get(self.ptr, empty.as_ptr(), self.cur, AV_DICT_IGNORE_SUFFIX); + + if !entry.is_null() { + let key = from_utf8_unchecked(CStr::from_ptr((*entry).key).to_bytes()); + let val = from_utf8_unchecked(CStr::from_ptr((*entry).value).to_bytes()); + + self.cur = entry; + + Some((key, val)) + } + else { + None + } + } + } +} + +impl<'a> IntoIterator for &'a Dictionary<'a> { + type Item = (&'a str, &'a str); + type IntoIter = DictionaryIter<'a>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +}