util/dictionary: refactor and make more sound
This commit is contained in:
parent
620958d684
commit
f2fb08e491
@ -55,7 +55,12 @@ impl Decoder {
|
||||
pub fn open_as_with(mut self, codec: &Codec, options: Dictionary) -> Result<Opened, Error> {
|
||||
unsafe {
|
||||
if codec.is_decoder() {
|
||||
match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut options.take()) {
|
||||
let mut opts = options.disown();
|
||||
let res = avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut opts);
|
||||
|
||||
Dictionary::own(opts);
|
||||
|
||||
match res {
|
||||
0 => Ok(Opened(self)),
|
||||
e => Err(Error::from(e))
|
||||
}
|
||||
|
@ -38,7 +38,12 @@ impl Audio {
|
||||
pub fn open_as_with(mut self, codec: &Codec, options: Dictionary) -> Result<Encoder, Error> {
|
||||
unsafe {
|
||||
if codec.is_encoder() {
|
||||
match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut options.take()) {
|
||||
let mut opts = options.disown();
|
||||
let res = avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut opts);
|
||||
|
||||
Dictionary::own(opts);
|
||||
|
||||
match res {
|
||||
0 => Ok(Encoder(self)),
|
||||
e => Err(Error::from(e))
|
||||
}
|
||||
|
@ -36,7 +36,12 @@ impl Subtitle {
|
||||
pub fn open_as_with(mut self, codec: &Codec, options: Dictionary) -> Result<Encoder, Error> {
|
||||
unsafe {
|
||||
if codec.is_encoder() {
|
||||
match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut options.take()) {
|
||||
let mut opts = options.disown();
|
||||
let res = avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut opts);
|
||||
|
||||
Dictionary::own(opts);
|
||||
|
||||
match res {
|
||||
0 => Ok(Encoder(self)),
|
||||
e => Err(Error::from(e))
|
||||
}
|
||||
|
@ -39,7 +39,12 @@ impl Video {
|
||||
pub fn open_as_with(mut self, codec: &Codec, options: Dictionary) -> Result<Encoder, Error> {
|
||||
unsafe {
|
||||
if codec.is_encoder() {
|
||||
match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut options.take()) {
|
||||
let mut opts = options.disown();
|
||||
let res = avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut opts);
|
||||
|
||||
Dictionary::own(opts);
|
||||
|
||||
match res {
|
||||
0 => Ok(Encoder(self)),
|
||||
e => Err(Error::from(e))
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use std::ptr;
|
||||
|
||||
use ffi::*;
|
||||
use libc::{c_int, c_uint};
|
||||
use ::{media, Stream, StreamMut, Dictionary};
|
||||
use ::{media, Stream, StreamMut, DictionaryRef};
|
||||
|
||||
pub struct Context {
|
||||
ptr: *mut AVFormatContext,
|
||||
@ -60,9 +60,9 @@ impl Context {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> Dictionary {
|
||||
pub fn metadata(&self) -> DictionaryRef {
|
||||
unsafe {
|
||||
Dictionary::wrap((*self.as_ptr()).metadata)
|
||||
DictionaryRef::wrap((*self.as_ptr()).metadata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,12 +39,12 @@ impl Output {
|
||||
|
||||
pub fn write_header_with(&mut self, options: Dictionary) -> Result<(), Error> {
|
||||
unsafe {
|
||||
let mut opts = options.take();
|
||||
let status = avformat_write_header(self.as_mut_ptr(), &mut opts);
|
||||
let mut opts = options.disown();
|
||||
let res = avformat_write_header(self.as_mut_ptr(), &mut opts);
|
||||
|
||||
Dictionary::own(opts);
|
||||
|
||||
match status {
|
||||
match res {
|
||||
0 => Ok(()),
|
||||
e => Err(Error::from(e)),
|
||||
}
|
||||
|
@ -100,14 +100,16 @@ pub fn open_with<P: AsRef<Path>>(path: &P, format: &Format, options: Dictionary)
|
||||
unsafe {
|
||||
let mut ps = ptr::null_mut();
|
||||
let path = from_path(path);
|
||||
let mut opts = options.take();
|
||||
let mut opts = options.disown();
|
||||
|
||||
match format {
|
||||
&Format::Input(ref format) => {
|
||||
match avformat_open_input(&mut ps, path.as_ptr(), format.as_ptr(), &mut opts) {
|
||||
0 => {
|
||||
Dictionary::own(opts);
|
||||
let res = avformat_open_input(&mut ps, path.as_ptr(), format.as_ptr(), &mut opts);
|
||||
|
||||
Dictionary::own(opts);
|
||||
|
||||
match res {
|
||||
0 => {
|
||||
match avformat_find_stream_info(ps, ptr::null_mut()) {
|
||||
0 => Ok(Context::Input(context::Input::wrap(ps))),
|
||||
e => Err(Error::from(e)),
|
||||
@ -156,12 +158,13 @@ pub fn input_with<P: AsRef<Path>>(path: &P, options: Dictionary) -> Result<conte
|
||||
unsafe {
|
||||
let mut ps = ptr::null_mut();
|
||||
let path = from_path(path);
|
||||
let mut opts = options.take();
|
||||
let mut opts = options.disown();
|
||||
let res = avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), &mut opts);
|
||||
|
||||
match avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), &mut opts) {
|
||||
Dictionary::own(opts);
|
||||
|
||||
match res {
|
||||
0 => {
|
||||
Dictionary::own(opts);
|
||||
|
||||
match avformat_find_stream_info(ps, ptr::null_mut()) {
|
||||
0 => Ok(context::Input::wrap(ps)),
|
||||
e => Err(Error::from(e))
|
||||
|
@ -9,7 +9,10 @@ pub use sys as ffi;
|
||||
|
||||
pub mod util;
|
||||
pub use util::error::Error;
|
||||
pub use util::dictionary::Dictionary;
|
||||
pub use util::dictionary;
|
||||
pub use util::dictionary::Owned as Dictionary;
|
||||
pub use util::dictionary::Ref as DictionaryRef;
|
||||
pub use util::dictionary::Mut as DictionaryMut;
|
||||
pub use util::rational::{self, Rational};
|
||||
pub use util::media;
|
||||
pub use util::picture;
|
||||
|
@ -1,153 +0,0 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::str::from_utf8_unchecked;
|
||||
|
||||
use ffi::*;
|
||||
|
||||
pub struct Dictionary<'a> {
|
||||
ptr: *mut AVDictionary,
|
||||
|
||||
_own: bool,
|
||||
_marker: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
impl<'a> Dictionary<'a> {
|
||||
pub unsafe fn wrap(ptr: *mut AVDictionary) -> Self {
|
||||
Dictionary { ptr: ptr, _own: false, _marker: PhantomData }
|
||||
}
|
||||
|
||||
pub unsafe fn own(ptr: *mut AVDictionary) -> Self {
|
||||
Dictionary { ptr: ptr, _own: true, _marker: PhantomData }
|
||||
}
|
||||
|
||||
pub unsafe fn as_ptr(&self) -> *const AVDictionary {
|
||||
self.ptr as *const _
|
||||
}
|
||||
|
||||
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVDictionary {
|
||||
self.ptr
|
||||
}
|
||||
|
||||
pub unsafe fn take(mut self) -> *mut AVDictionary {
|
||||
self._own = false;
|
||||
self.ptr
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Dictionary<'a> {
|
||||
pub fn new() -> Self {
|
||||
Dictionary { ptr: ptr::null_mut(), _own: true, _marker: PhantomData }
|
||||
}
|
||||
|
||||
pub fn set(&mut self, key: &str, value: &str) {
|
||||
unsafe {
|
||||
let key = CString::new(key).unwrap();
|
||||
let value = CString::new(value).unwrap();
|
||||
let mut ptr = self.as_mut_ptr();
|
||||
|
||||
if av_dict_set(&mut ptr, key.as_ptr(), value.as_ptr(), 0) < 0 {
|
||||
panic!("out of memory");
|
||||
}
|
||||
|
||||
self.ptr = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&'a self, key: &str) -> Option<&'a str> {
|
||||
unsafe {
|
||||
let key = CString::new(key).unwrap();
|
||||
let entry = av_dict_get(self.as_ptr(), key.as_ptr(), ptr::null_mut(), 0);
|
||||
|
||||
if entry.is_null() {
|
||||
None
|
||||
}
|
||||
else {
|
||||
Some(from_utf8_unchecked(CStr::from_ptr((*entry).value).to_bytes()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> DictionaryIter {
|
||||
unsafe {
|
||||
DictionaryIter::new(self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Clone for Dictionary<'a> {
|
||||
fn clone(&self) -> Self {
|
||||
let mut dictionary = Dictionary::new();
|
||||
dictionary.clone_from(self);
|
||||
|
||||
dictionary
|
||||
}
|
||||
|
||||
fn clone_from(&mut self, source: &Self) {
|
||||
unsafe {
|
||||
let mut ptr = self.as_mut_ptr();
|
||||
av_dict_copy(&mut ptr, source.as_ptr(), 0);
|
||||
self.ptr = ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for Dictionary<'a> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
if self._own && self.as_ptr() != ptr::null() {
|
||||
av_dict_free(&mut self.as_mut_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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<<Self as Iterator>::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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
58
src/util/dictionary/immutable.rs
Normal file
58
src/util/dictionary/immutable.rs
Normal file
@ -0,0 +1,58 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::str::from_utf8_unchecked;
|
||||
|
||||
use ffi::*;
|
||||
use super::{Iter, Owned};
|
||||
|
||||
pub struct Ref<'a> {
|
||||
ptr: *const AVDictionary,
|
||||
|
||||
_marker: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
impl<'a> Ref<'a> {
|
||||
pub unsafe fn wrap(ptr: *const AVDictionary) -> Self {
|
||||
Ref { ptr: ptr, _marker: PhantomData }
|
||||
}
|
||||
|
||||
pub unsafe fn as_ptr(&self) -> *const AVDictionary {
|
||||
self.ptr
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Ref<'a> {
|
||||
pub fn get(&'a self, key: &str) -> Option<&'a str> {
|
||||
unsafe {
|
||||
let key = CString::new(key).unwrap();
|
||||
let entry = av_dict_get(self.as_ptr(), key.as_ptr(), ptr::null_mut(), 0);
|
||||
|
||||
if entry.is_null() {
|
||||
None
|
||||
}
|
||||
else {
|
||||
Some(from_utf8_unchecked(CStr::from_ptr((*entry).value).to_bytes()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> Iter {
|
||||
unsafe {
|
||||
Iter::new(self.as_ptr())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_owned(&self) -> Owned {
|
||||
self.iter().collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a Ref<'a> {
|
||||
type Item = (&'a str, &'a str);
|
||||
type IntoIter = Iter<'a>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter()
|
||||
}
|
||||
}
|
47
src/util/dictionary/iter.rs
Normal file
47
src/util/dictionary/iter.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::str::from_utf8_unchecked;
|
||||
|
||||
use ffi::*;
|
||||
|
||||
pub struct Iter<'a> {
|
||||
ptr: *const AVDictionary,
|
||||
cur: *mut AVDictionaryEntry,
|
||||
|
||||
_marker: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
impl<'a> Iter<'a> {
|
||||
pub fn new(dictionary: *const AVDictionary) -> Self {
|
||||
Iter {
|
||||
ptr: dictionary,
|
||||
cur: ptr::null_mut(),
|
||||
|
||||
_marker: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Iter<'a> {
|
||||
type Item = (&'a str, &'a str);
|
||||
|
||||
fn next(&mut self) -> Option<<Self as Iterator>::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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
src/util/dictionary/mod.rs
Normal file
11
src/util/dictionary/mod.rs
Normal file
@ -0,0 +1,11 @@
|
||||
mod immutable;
|
||||
pub use self::immutable::Ref;
|
||||
|
||||
mod mutable;
|
||||
pub use self::mutable::Ref as Mut;
|
||||
|
||||
mod owned;
|
||||
pub use self::owned::Owned;
|
||||
|
||||
mod iter;
|
||||
pub use self::iter::Iter;
|
47
src/util/dictionary/mutable.rs
Normal file
47
src/util/dictionary/mutable.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use std::ops::Deref;
|
||||
use std::marker::PhantomData;
|
||||
use std::ffi::CString;
|
||||
|
||||
use ffi::*;
|
||||
use super::immutable;
|
||||
|
||||
pub struct Ref<'a> {
|
||||
ptr: *mut AVDictionary,
|
||||
imm: immutable::Ref<'a>,
|
||||
|
||||
_marker: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
impl<'a> Ref<'a> {
|
||||
pub unsafe fn wrap(ptr: *mut AVDictionary) -> Self {
|
||||
Ref { ptr: ptr, imm: immutable::Ref::wrap(ptr), _marker: PhantomData }
|
||||
}
|
||||
|
||||
pub unsafe fn as_mut_ptr(&self) -> *mut AVDictionary {
|
||||
self.ptr
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Ref<'a> {
|
||||
pub fn set(&mut self, key: &str, value: &str) {
|
||||
unsafe {
|
||||
let key = CString::new(key).unwrap();
|
||||
let value = CString::new(value).unwrap();
|
||||
let mut ptr = self.as_mut_ptr();
|
||||
|
||||
if av_dict_set(&mut ptr, key.as_ptr(), value.as_ptr(), 0) < 0 {
|
||||
panic!("out of memory");
|
||||
}
|
||||
|
||||
self.ptr = ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deref for Ref<'a> {
|
||||
type Target = immutable::Ref<'a>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.imm
|
||||
}
|
||||
}
|
82
src/util/dictionary/owned.rs
Normal file
82
src/util/dictionary/owned.rs
Normal file
@ -0,0 +1,82 @@
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::iter::FromIterator;
|
||||
use std::ptr;
|
||||
|
||||
use ffi::*;
|
||||
use super::mutable;
|
||||
|
||||
pub struct Owned<'a> {
|
||||
inner: mutable::Ref<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Owned<'a> {
|
||||
pub unsafe fn own(ptr: *mut AVDictionary) -> Self {
|
||||
Owned { inner: mutable::Ref::wrap(ptr) }
|
||||
}
|
||||
|
||||
pub unsafe fn disown(mut self) -> *mut AVDictionary {
|
||||
let result = self.inner.as_mut_ptr();
|
||||
self.inner = mutable::Ref::wrap(ptr::null_mut());
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Owned<'a> {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
Owned { inner: mutable::Ref::wrap(ptr::null_mut()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> FromIterator<(&'b str, &'b str)> for Owned<'a> {
|
||||
fn from_iter<T: IntoIterator<Item=(&'b str, &'b str)>>(iterator: T) -> Self {
|
||||
let mut result = Owned::new();
|
||||
|
||||
for (key, value) in iterator {
|
||||
result.set(key, value);
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deref for Owned<'a> {
|
||||
type Target = mutable::Ref<'a>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> DerefMut for Owned<'a> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Clone for Owned<'a> {
|
||||
fn clone(&self) -> Self {
|
||||
let mut dictionary = Owned::new();
|
||||
dictionary.clone_from(self);
|
||||
|
||||
dictionary
|
||||
}
|
||||
|
||||
fn clone_from(&mut self, source: &Self) {
|
||||
unsafe {
|
||||
let mut ptr = self.as_mut_ptr();
|
||||
av_dict_copy(&mut ptr, source.as_ptr(), 0);
|
||||
self.inner = mutable::Ref::wrap(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for Owned<'a> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
av_dict_free(&mut self.inner.as_mut_ptr());
|
||||
}
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ pub use self::flag::Flags;
|
||||
|
||||
use libc::c_int;
|
||||
use ffi::*;
|
||||
use ::Dictionary;
|
||||
use ::{Dictionary, DictionaryRef};
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct Packet {
|
||||
@ -106,15 +106,15 @@ impl Frame {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> Dictionary {
|
||||
pub fn metadata(&self) -> DictionaryRef {
|
||||
unsafe {
|
||||
Dictionary::wrap(av_frame_get_metadata(self.as_ptr()))
|
||||
DictionaryRef::wrap(av_frame_get_metadata(self.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_metadata(&mut self, value: Dictionary) {
|
||||
unsafe {
|
||||
av_frame_set_metadata(self.as_mut_ptr(), value.take());
|
||||
av_frame_set_metadata(self.as_mut_ptr(), value.disown());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ use std::str::from_utf8_unchecked;
|
||||
|
||||
use ffi::*;
|
||||
use super::Frame;
|
||||
use ::Dictionary;
|
||||
use ::DictionaryRef;
|
||||
|
||||
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
|
||||
pub enum Type {
|
||||
@ -108,9 +108,9 @@ impl<'a> SideData<'a> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn metadata(&self) -> Dictionary {
|
||||
pub fn metadata(&self) -> DictionaryRef {
|
||||
unsafe {
|
||||
Dictionary::wrap((*self.as_ptr()).metadata)
|
||||
DictionaryRef::wrap((*self.as_ptr()).metadata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user