Implement ValueRef and TypedValueRef for wrapping around a unowned GValue pointer without copying

Also rename new_from*() functions to from*() for consistency.
This commit is contained in:
Sebastian Dröge 2017-04-19 11:58:51 +01:00
parent 2d97baaf96
commit 1bf20bfea4
7 changed files with 266 additions and 123 deletions

View file

@ -63,14 +63,14 @@ unsafe impl MiniObject for Buffer {
self.0 = ptr self.0 = ptr
} }
unsafe fn new_from_ptr(ptr: *mut gst::GstBuffer) -> Self { unsafe fn from_ptr(ptr: *mut gst::GstBuffer) -> Self {
Buffer(ptr) Buffer(ptr)
} }
} }
impl Buffer { impl Buffer {
pub fn new() -> GstRc<Buffer> { pub fn new() -> GstRc<Buffer> {
unsafe { GstRc::new_from_owned_ptr(gst::gst_buffer_new()) } unsafe { GstRc::from_owned_ptr(gst::gst_buffer_new()) }
} }
pub fn new_with_size(size: usize) -> Option<GstRc<Buffer>> { pub fn new_with_size(size: usize) -> Option<GstRc<Buffer>> {
@ -78,7 +78,7 @@ impl Buffer {
if raw.is_null() { if raw.is_null() {
None None
} else { } else {
Some(unsafe { GstRc::new_from_owned_ptr(raw) }) Some(unsafe { GstRc::from_owned_ptr(raw) })
} }
} }
@ -87,7 +87,7 @@ impl Buffer {
drop(vec); drop(vec);
} }
pub fn new_from_vec(vec: Vec<u8>) -> Option<GstRc<Buffer>> { pub fn from_vec(vec: Vec<u8>) -> Option<GstRc<Buffer>> {
let raw = unsafe { let raw = unsafe {
let mut vec = Box::new(vec); let mut vec = Box::new(vec);
let maxsize = vec.capacity(); let maxsize = vec.capacity();
@ -106,7 +106,7 @@ impl Buffer {
if raw.is_null() { if raw.is_null() {
None None
} else { } else {
Some(unsafe { GstRc::new_from_owned_ptr(raw) }) Some(unsafe { GstRc::from_owned_ptr(raw) })
} }
} }
@ -164,10 +164,8 @@ impl Buffer {
pub fn append(buffer: GstRc<Buffer>, other: GstRc<Buffer>) -> GstRc<Buffer> { pub fn append(buffer: GstRc<Buffer>, other: GstRc<Buffer>) -> GstRc<Buffer> {
unsafe { unsafe {
GstRc::new_from_owned_ptr(gst::gst_buffer_append(buffer.into_ptr() as GstRc::from_owned_ptr(gst::gst_buffer_append(buffer.into_ptr() as *mut gst::GstBuffer,
*mut gst::GstBuffer, other.into_ptr() as *mut gst::GstBuffer))
other.into_ptr() as
*mut gst::GstBuffer))
} }
} }
@ -181,7 +179,7 @@ impl Buffer {
if raw.is_null() { if raw.is_null() {
None None
} else { } else {
Some(unsafe { GstRc::new_from_owned_ptr(raw) }) Some(unsafe { GstRc::from_owned_ptr(raw) })
} }
} }
@ -514,7 +512,7 @@ mod tests {
fn test_writability() { fn test_writability() {
init(); init();
let mut buffer = Buffer::new_from_vec(vec![1, 2, 3, 4]).unwrap(); let mut buffer = Buffer::from_vec(vec![1, 2, 3, 4]).unwrap();
{ {
let data = buffer.map_read().unwrap(); let data = buffer.map_read().unwrap();
assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice()); assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice());

View file

@ -29,18 +29,18 @@ unsafe impl MiniObject for Caps {
self.0 = ptr self.0 = ptr
} }
unsafe fn new_from_ptr(ptr: *mut gst::GstCaps) -> Self { unsafe fn from_ptr(ptr: *mut gst::GstCaps) -> Self {
Caps(ptr) Caps(ptr)
} }
} }
impl Caps { impl Caps {
pub fn new_empty() -> GstRc<Self> { pub fn new_empty() -> GstRc<Self> {
unsafe { GstRc::new_from_owned_ptr(gst::gst_caps_new_empty()) } unsafe { GstRc::from_owned_ptr(gst::gst_caps_new_empty()) }
} }
pub fn new_any() -> GstRc<Self> { pub fn new_any() -> GstRc<Self> {
unsafe { GstRc::new_from_owned_ptr(gst::gst_caps_new_any()) } unsafe { GstRc::from_owned_ptr(gst::gst_caps_new_any()) }
} }
pub fn new_simple(name: &str, values: &[(&str, &Value)]) -> GstRc<Self> { pub fn new_simple(name: &str, values: &[(&str, &Value)]) -> GstRc<Self> {
@ -67,7 +67,7 @@ impl Caps {
if caps_ptr.is_null() { if caps_ptr.is_null() {
None None
} else { } else {
Some(GstRc::new_from_owned_ptr(caps_ptr)) Some(GstRc::from_owned_ptr(caps_ptr))
} }
} }
} }

View file

@ -487,7 +487,7 @@ pub unsafe extern "C" fn demuxer_handle_buffer(ptr: *mut DemuxerWrapper,
let wrap: &mut DemuxerWrapper = &mut *ptr; let wrap: &mut DemuxerWrapper = &mut *ptr;
panic_to_error!(wrap, gst::GST_FLOW_ERROR, { panic_to_error!(wrap, gst::GST_FLOW_ERROR, {
let buffer = GstRc::new_from_owned_ptr(buffer); let buffer = GstRc::from_owned_ptr(buffer);
wrap.handle_buffer(buffer) wrap.handle_buffer(buffer)
}) })
} }

View file

@ -28,12 +28,12 @@ impl<T: MiniObject> GstRc<T> {
GstRc { obj: obj } GstRc { obj: obj }
} }
pub unsafe fn new_from_owned_ptr(ptr: *mut T::PtrType) -> Self { pub unsafe fn from_owned_ptr(ptr: *mut T::PtrType) -> Self {
Self::new(T::new_from_ptr(ptr), true) Self::new(T::from_ptr(ptr), true)
} }
pub unsafe fn new_from_unowned_ptr(ptr: *mut T::PtrType) -> Self { pub unsafe fn from_unowned_ptr(ptr: *mut T::PtrType) -> Self {
Self::new(T::new_from_ptr(ptr), false) Self::new(T::from_ptr(ptr), false)
} }
pub fn make_mut(&mut self) -> &mut T { pub fn make_mut(&mut self) -> &mut T {
@ -63,9 +63,9 @@ impl<T: MiniObject> GstRc<T> {
pub fn copy(&self) -> Self { pub fn copy(&self) -> Self {
unsafe { unsafe {
GstRc::new_from_owned_ptr(gst::gst_mini_object_copy(self.obj.as_ptr() as GstRc::from_owned_ptr(gst::gst_mini_object_copy(self.obj.as_ptr() as
*const gst::GstMiniObject) as *const gst::GstMiniObject) as
*mut T::PtrType) *mut T::PtrType)
} }
} }
@ -101,7 +101,7 @@ impl<T: MiniObject> borrow::Borrow<T> for GstRc<T> {
impl<T: MiniObject> Clone for GstRc<T> { impl<T: MiniObject> Clone for GstRc<T> {
fn clone(&self) -> GstRc<T> { fn clone(&self) -> GstRc<T> {
unsafe { GstRc::new_from_unowned_ptr(self.obj.as_ptr()) } unsafe { GstRc::from_unowned_ptr(self.obj.as_ptr()) }
} }
} }
@ -137,18 +137,18 @@ pub unsafe trait MiniObject {
ptr ptr
} }
unsafe fn new_from_ptr(ptr: *mut Self::PtrType) -> Self; unsafe fn from_ptr(ptr: *mut Self::PtrType) -> Self;
} }
impl<'a, T: MiniObject> From<&'a T> for GstRc<T> { impl<'a, T: MiniObject> From<&'a T> for GstRc<T> {
fn from(f: &'a T) -> GstRc<T> { fn from(f: &'a T) -> GstRc<T> {
unsafe { GstRc::new_from_unowned_ptr(f.as_ptr()) } unsafe { GstRc::from_unowned_ptr(f.as_ptr()) }
} }
} }
impl<'a, T: MiniObject> From<&'a mut T> for GstRc<T> { impl<'a, T: MiniObject> From<&'a mut T> for GstRc<T> {
fn from(f: &'a mut T) -> GstRc<T> { fn from(f: &'a mut T) -> GstRc<T> {
unsafe { GstRc::new_from_unowned_ptr(f.as_ptr()) } unsafe { GstRc::from_unowned_ptr(f.as_ptr()) }
} }
} }
@ -162,7 +162,7 @@ pub struct GstRef<'a, T: 'a + MiniObject> {
impl<'a, T: MiniObject> GstRef<'a, T> { impl<'a, T: MiniObject> GstRef<'a, T> {
pub unsafe fn new(ptr: *mut T::PtrType) -> GstRef<'a, T> { pub unsafe fn new(ptr: *mut T::PtrType) -> GstRef<'a, T> {
GstRef { GstRef {
obj: T::new_from_ptr(ptr), obj: T::from_ptr(ptr),
phantom: PhantomData, phantom: PhantomData,
} }
} }
@ -177,9 +177,9 @@ impl<'a, T: MiniObject> GstRef<'a, T> {
pub fn copy(&self) -> GstRc<T> { pub fn copy(&self) -> GstRc<T> {
unsafe { unsafe {
GstRc::new_from_owned_ptr(gst::gst_mini_object_copy(self.obj.as_ptr() as GstRc::from_owned_ptr(gst::gst_mini_object_copy(self.obj.as_ptr() as
*const gst::GstMiniObject) as *const gst::GstMiniObject) as
*mut T::PtrType) *mut T::PtrType)
} }
} }

View file

@ -67,7 +67,7 @@ impl Stream {
return None; return None;
} }
Some(unsafe { GstRc::new_from_owned_ptr(ptr) }) Some(unsafe { GstRc::from_owned_ptr(ptr) })
} }
pub fn get_stream_flags(&self) -> StreamFlags { pub fn get_stream_flags(&self) -> StreamFlags {
@ -90,7 +90,7 @@ impl Stream {
return None; return None;
} }
Some(unsafe { TagList::new_from_ptr(ptr) }) Some(unsafe { TagList::from_ptr(ptr) })
} }
pub fn set_caps(&self, caps: Option<GstRc<Caps>>) { pub fn set_caps(&self, caps: Option<GstRc<Caps>>) {

View file

@ -82,14 +82,14 @@ unsafe impl MiniObject for TagList {
self.0 = ptr self.0 = ptr
} }
unsafe fn new_from_ptr(ptr: *mut gst::GstTagList) -> Self { unsafe fn from_ptr(ptr: *mut gst::GstTagList) -> Self {
TagList(ptr) TagList(ptr)
} }
} }
impl TagList { impl TagList {
pub fn new() -> GstRc<Self> { pub fn new() -> GstRc<Self> {
unsafe { GstRc::new_from_owned_ptr(gst::gst_tag_list_new_empty()) } unsafe { GstRc::from_owned_ptr(gst::gst_tag_list_new_empty()) }
} }
pub fn add<'a, T: Tag<'a>>(&mut self, value: T::TagType, mode: MergeMode) pub fn add<'a, T: Tag<'a>>(&mut self, value: T::TagType, mode: MergeMode)
@ -128,6 +128,27 @@ impl TagList {
} }
} }
pub fn get_index<'a, T: Tag<'a>>(&'a self, idx: u32) -> Option<TypedValueRef<'a, T::TagType>>
where Value: From<<T as Tag<'a>>::TagType>
{
unsafe {
let tag_name = CString::new(T::tag_name()).unwrap();
let value = gst::gst_tag_list_get_value_index(self.0, tag_name.as_ptr(), idx);
if value.is_null() {
return None;
}
let res = match ValueRef::from_ptr(value) {
Some(value) => TypedValueRef::from_value_ref(value),
None => None,
};
res
}
}
pub fn to_string(&self) -> String { pub fn to_string(&self) -> String {
unsafe { unsafe {
let ptr = gst::gst_tag_list_to_string(self.0); let ptr = gst::gst_tag_list_to_string(self.0);
@ -195,5 +216,8 @@ mod tests {
assert_eq!(tags.get::<Title>().unwrap().get(), "some title"); assert_eq!(tags.get::<Title>().unwrap().get(), "some title");
assert_eq!(tags.get::<Duration>().unwrap().get(), assert_eq!(tags.get::<Duration>().unwrap().get(),
(1000u64 * 1000 * 1000 * 120)); (1000u64 * 1000 * 1000 * 120));
assert_eq!(tags.get_index::<Title>(0).unwrap().get(), "some title");
assert_eq!(tags.get_index::<Duration>(0).unwrap().get(),
(1000u64 * 1000 * 1000 * 120));
} }
} }

View file

@ -27,7 +27,7 @@ use gst;
pub struct Value(gobject::GValue); pub struct Value(gobject::GValue);
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
pub enum ValueRef<'a> { pub enum ValueView<'a> {
Bool(bool), Bool(bool),
Int(i32), Int(i32),
UInt(u32), UInt(u32),
@ -39,9 +39,9 @@ pub enum ValueRef<'a> {
Array(Cow<'a, [Value]>), Array(Cow<'a, [Value]>),
} }
impl<'a> ValueRef<'a> { impl<'a> ValueView<'a> {
pub fn try_get<T: ValueType<'a>>(&'a self) -> Option<T> { pub fn try_get<T: ValueType<'a>>(&'a self) -> Option<T> {
T::from_value_ref(&self) T::from_value_view(&self)
} }
} }
@ -50,8 +50,8 @@ pub trait ValueType<'a>
{ {
fn g_type() -> glib::GType; fn g_type() -> glib::GType;
fn from_value(v: &'a Value) -> Option<Self>; fn from_value(v: &'a gobject::GValue) -> Option<Self>;
fn from_value_ref(v: &'a ValueRef<'a>) -> Option<Self>; fn from_value_view(v: &'a ValueView<'a>) -> Option<Self>;
} }
lazy_static! { lazy_static! {
@ -77,6 +77,10 @@ impl Value {
Some(value) Some(value)
} }
pub fn from_value_ref<'a>(v: &ValueRef<'a>) -> Value {
unsafe { Value::from_ptr(v.0) }.unwrap()
}
pub unsafe fn from_raw(value: gobject::GValue) -> Option<Value> { pub unsafe fn from_raw(value: gobject::GValue) -> Option<Value> {
if !Value::is_supported_type(value.g_type) { if !Value::is_supported_type(value.g_type) {
return None; return None;
@ -107,45 +111,46 @@ impl Value {
v.into() v.into()
} }
pub fn new_from_value_ref(v: ValueRef) -> Value { pub fn from_value_view(v: ValueView) -> Value {
match v { match v {
ValueRef::Bool(v) => Value::from(v), ValueView::Bool(v) => Value::from(v),
ValueRef::Int(v) => Value::from(v), ValueView::Int(v) => Value::from(v),
ValueRef::UInt(v) => Value::from(v), ValueView::UInt(v) => Value::from(v),
ValueRef::Int64(v) => Value::from(v), ValueView::Int64(v) => Value::from(v),
ValueRef::UInt64(v) => Value::from(v), ValueView::UInt64(v) => Value::from(v),
ValueRef::Fraction(v) => Value::from(v), ValueView::Fraction(v) => Value::from(v),
ValueRef::String(v) => Value::from(v), ValueView::String(v) => Value::from(v),
ValueRef::Array(v) => Value::from(v), ValueView::Array(v) => Value::from(v),
ValueRef::Buffer(v) => Value::from(v), ValueView::Buffer(v) => Value::from(v),
} }
} }
pub fn get(&self) -> ValueRef { pub fn get(&self) -> ValueView {
match self.0.g_type { match self.0.g_type {
gobject::G_TYPE_BOOLEAN => ValueRef::Bool(bool::from_value(&self).unwrap()), gobject::G_TYPE_BOOLEAN => ValueView::Bool(bool::from_value(&self.0).unwrap()),
gobject::G_TYPE_INT => ValueRef::Int(i32::from_value(&self).unwrap()), gobject::G_TYPE_INT => ValueView::Int(i32::from_value(&self.0).unwrap()),
gobject::G_TYPE_UINT => ValueRef::UInt(u32::from_value(&self).unwrap()), gobject::G_TYPE_UINT => ValueView::UInt(u32::from_value(&self.0).unwrap()),
gobject::G_TYPE_INT64 => ValueRef::Int64(i64::from_value(&self).unwrap()), gobject::G_TYPE_INT64 => ValueView::Int64(i64::from_value(&self.0).unwrap()),
gobject::G_TYPE_UINT64 => ValueRef::UInt64(u64::from_value(&self).unwrap()), gobject::G_TYPE_UINT64 => ValueView::UInt64(u64::from_value(&self.0).unwrap()),
typ if typ == *TYPE_FRACTION => { typ if typ == *TYPE_FRACTION => {
ValueRef::Fraction(Rational32::from_value(&self).unwrap()) ValueView::Fraction(Rational32::from_value(&self.0).unwrap())
} }
gobject::G_TYPE_STRING => { gobject::G_TYPE_STRING => {
ValueRef::String(Cow::Borrowed(<&str as ValueType>::from_value(&self).unwrap())) ValueView::String(Cow::Borrowed(<&str as ValueType>::from_value(&self.0).unwrap()))
} }
typ if typ == *TYPE_GST_VALUE_ARRAY => { typ if typ == *TYPE_GST_VALUE_ARRAY => {
ValueRef::Array(Cow::Borrowed(<&[Value] as ValueType>::from_value(&self).unwrap())) ValueView::Array(Cow::Borrowed(<&[Value] as ValueType>::from_value(&self.0)
.unwrap()))
} }
typ if typ == *TYPE_BUFFER => { typ if typ == *TYPE_BUFFER => {
ValueRef::Buffer(<GstRc<Buffer> as ValueType>::from_value(&self).unwrap()) ValueView::Buffer(<GstRc<Buffer> as ValueType>::from_value(&self.0).unwrap())
} }
_ => unreachable!(), _ => unreachable!(),
} }
} }
pub fn try_get<'a, T: ValueType<'a>>(&'a self) -> Option<T> { pub fn try_get<'a, T: ValueType<'a>>(&'a self) -> Option<T> {
T::from_value(self) T::from_value(&self.0)
} }
} }
@ -184,6 +189,68 @@ impl Drop for Value {
} }
} }
#[derive(Clone)]
pub struct ValueRef<'a>(&'a gobject::GValue);
impl<'a> ValueRef<'a> {
pub unsafe fn as_ptr(&self) -> *const gobject::GValue {
self.0
}
pub fn from_value(v: &'a Value) -> ValueRef<'a> {
ValueRef(&v.0)
}
pub unsafe fn from_ptr(ptr: *const gobject::GValue) -> Option<ValueRef<'a>> {
if ptr.is_null() || !Value::is_supported_type((*ptr).g_type) {
return None;
}
Some(ValueRef(&*ptr))
}
pub fn get(&self) -> ValueView {
match self.0.g_type {
gobject::G_TYPE_BOOLEAN => ValueView::Bool(bool::from_value(self.0).unwrap()),
gobject::G_TYPE_INT => ValueView::Int(i32::from_value(self.0).unwrap()),
gobject::G_TYPE_UINT => ValueView::UInt(u32::from_value(self.0).unwrap()),
gobject::G_TYPE_INT64 => ValueView::Int64(i64::from_value(self.0).unwrap()),
gobject::G_TYPE_UINT64 => ValueView::UInt64(u64::from_value(self.0).unwrap()),
typ if typ == *TYPE_FRACTION => {
ValueView::Fraction(Rational32::from_value(&self.0).unwrap())
}
gobject::G_TYPE_STRING => {
ValueView::String(Cow::Borrowed(<&str as ValueType>::from_value(self.0).unwrap()))
}
typ if typ == *TYPE_GST_VALUE_ARRAY => {
ValueView::Array(Cow::Borrowed(<&[Value] as ValueType>::from_value(self.0)
.unwrap()))
}
typ if typ == *TYPE_BUFFER => {
ValueView::Buffer(<GstRc<Buffer> as ValueType>::from_value(self.0).unwrap())
}
_ => unreachable!(),
}
}
pub fn try_get<T: ValueType<'a>>(&self) -> Option<T> {
T::from_value(self.0)
}
}
impl<'a> PartialEq for ValueRef<'a> {
fn eq(&self, other: &ValueRef<'a>) -> bool {
self.get().eq(&other.get())
}
}
impl<'a> Eq for ValueRef<'a> {}
impl<'a> fmt::Debug for ValueRef<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.get().fmt(f)
}
}
macro_rules! impl_value_type_simple( macro_rules! impl_value_type_simple(
($typ:ty, $variant:ident, $g_type:expr, $getter:expr, $setter:expr) => { ($typ:ty, $variant:ident, $g_type:expr, $getter:expr, $setter:expr) => {
impl<'a> ValueType<'a> for $typ { impl<'a> ValueType<'a> for $typ {
@ -191,18 +258,18 @@ macro_rules! impl_value_type_simple(
$g_type $g_type
} }
fn from_value(value: &'a Value) -> Option<Self> { fn from_value(value: &'a gobject::GValue) -> Option<Self> {
if value.0.g_type != Self::g_type() { if value.g_type != Self::g_type() {
return None; return None;
} }
unsafe { unsafe {
Some($getter(value)) Some($getter(&value))
} }
} }
fn from_value_ref(value_ref: &'a ValueRef<'a>) -> Option<Self> { fn from_value_view(value_view: &'a ValueView<'a>) -> Option<Self> {
if let ValueRef::$variant(ref v) = *value_ref { if let ValueView::$variant(ref v) = *value_view {
Some(*v) Some(*v)
} else { } else {
None None
@ -216,7 +283,7 @@ macro_rules! impl_value_type_simple(
let mut value = Value(mem::zeroed()); let mut value = Value(mem::zeroed());
gobject::g_value_init(&mut value.0, <$typ as ValueType>::g_type()); gobject::g_value_init(&mut value.0, <$typ as ValueType>::g_type());
$setter(&mut value, v); $setter(&mut value.0, v);
value value
} }
@ -228,40 +295,40 @@ macro_rules! impl_value_type_simple(
impl_value_type_simple!(bool, impl_value_type_simple!(bool,
Bool, Bool,
gobject::G_TYPE_BOOLEAN, gobject::G_TYPE_BOOLEAN,
|value: &Value| !(gobject::g_value_get_boolean(&value.0) == 0), |value: &gobject::GValue| !(gobject::g_value_get_boolean(value) == 0),
|value: &mut Value, v| { |value: &mut gobject::GValue, v| {
gobject::g_value_set_boolean(&mut value.0, gobject::g_value_set_boolean(value,
if v { glib::GTRUE } else { glib::GFALSE }) if v { glib::GTRUE } else { glib::GFALSE })
}); });
impl_value_type_simple!(i32, impl_value_type_simple!(i32,
Int, Int,
gobject::G_TYPE_INT, gobject::G_TYPE_INT,
|value: &Value| gobject::g_value_get_int(&value.0), |value: &gobject::GValue| gobject::g_value_get_int(value),
|value: &mut Value, v| gobject::g_value_set_int(&mut value.0, v)); |value: &mut gobject::GValue, v| gobject::g_value_set_int(value, v));
impl_value_type_simple!(u32, impl_value_type_simple!(u32,
UInt, UInt,
gobject::G_TYPE_UINT, gobject::G_TYPE_UINT,
|value: &Value| gobject::g_value_get_uint(&value.0), |value: &gobject::GValue| gobject::g_value_get_uint(value),
|value: &mut Value, v| gobject::g_value_set_uint(&mut value.0, v)); |value: &mut gobject::GValue, v| gobject::g_value_set_uint(value, v));
impl_value_type_simple!(i64, impl_value_type_simple!(i64,
Int64, Int64,
gobject::G_TYPE_INT64, gobject::G_TYPE_INT64,
|value: &Value| gobject::g_value_get_int64(&value.0), |value: &gobject::GValue| gobject::g_value_get_int64(value),
|value: &mut Value, v| gobject::g_value_set_int64(&mut value.0, v)); |value: &mut gobject::GValue, v| gobject::g_value_set_int64(value, v));
impl_value_type_simple!(u64, impl_value_type_simple!(u64,
UInt64, UInt64,
gobject::G_TYPE_UINT64, gobject::G_TYPE_UINT64,
|value: &Value| gobject::g_value_get_uint64(&value.0), |value: &gobject::GValue| gobject::g_value_get_uint64(value),
|value: &mut Value, v| gobject::g_value_set_uint64(&mut value.0, v)); |value: &mut gobject::GValue, v| gobject::g_value_set_uint64(value, v));
impl_value_type_simple!(Rational32, impl_value_type_simple!(Rational32,
Fraction, Fraction,
*TYPE_FRACTION, *TYPE_FRACTION,
|value: &Value| { |value: &gobject::GValue| {
Rational32::new(gst::gst_value_get_fraction_numerator(&value.0), Rational32::new(gst::gst_value_get_fraction_numerator(value),
gst::gst_value_get_fraction_denominator(&value.0)) gst::gst_value_get_fraction_denominator(value))
}, },
|value: &mut Value, v: Rational32| { |value: &mut gobject::GValue, v: Rational32| {
gst::gst_value_set_fraction(&mut value.0, *v.numer(), *v.denom()) gst::gst_value_set_fraction(value, *v.numer(), *v.denom())
}); });
impl<'a> ValueType<'a> for &'a str { impl<'a> ValueType<'a> for &'a str {
@ -269,13 +336,13 @@ impl<'a> ValueType<'a> for &'a str {
gobject::G_TYPE_STRING gobject::G_TYPE_STRING
} }
fn from_value(value: &'a Value) -> Option<Self> { fn from_value(value: &'a gobject::GValue) -> Option<Self> {
if value.0.g_type != Self::g_type() { if value.g_type != Self::g_type() {
return None; return None;
} }
unsafe { unsafe {
let s = gobject::g_value_get_string(&value.0); let s = gobject::g_value_get_string(value);
if s.is_null() { if s.is_null() {
return Some(&""); return Some(&"");
} }
@ -285,8 +352,8 @@ impl<'a> ValueType<'a> for &'a str {
} }
} }
fn from_value_ref(value_ref: &'a ValueRef<'a>) -> Option<Self> { fn from_value_view(value_view: &'a ValueView<'a>) -> Option<Self> {
if let ValueRef::String(ref v) = *value_ref { if let ValueView::String(ref v) = *value_view {
Some(v.as_ref()) Some(v.as_ref())
} else { } else {
None None
@ -325,19 +392,19 @@ impl<'a> ValueType<'a> for GstRc<Buffer> {
*TYPE_BUFFER *TYPE_BUFFER
} }
fn from_value(value: &'a Value) -> Option<Self> { fn from_value(value: &'a gobject::GValue) -> Option<Self> {
if value.0.g_type != Self::g_type() { if value.g_type != Self::g_type() {
return None; return None;
} }
unsafe { unsafe {
let buffer = gobject::g_value_get_boxed(&value.0) as *mut gst::GstBuffer; let buffer = gobject::g_value_get_boxed(value) as *mut gst::GstBuffer;
Some(GstRc::new_from_unowned_ptr(buffer)) Some(GstRc::from_unowned_ptr(buffer))
} }
} }
fn from_value_ref(value_ref: &'a ValueRef<'a>) -> Option<Self> { fn from_value_view(value_view: &'a ValueView<'a>) -> Option<Self> {
if let ValueRef::Buffer(ref v) = *value_ref { if let ValueView::Buffer(ref v) = *value_view {
Some(v.clone()) Some(v.clone())
} else { } else {
None None
@ -375,13 +442,13 @@ impl<'a> ValueType<'a> for &'a [Value] {
*TYPE_GST_VALUE_ARRAY *TYPE_GST_VALUE_ARRAY
} }
fn from_value(value: &'a Value) -> Option<Self> { fn from_value(value: &'a gobject::GValue) -> Option<Self> {
if value.0.g_type != Self::g_type() { if value.g_type != Self::g_type() {
return None; return None;
} }
unsafe { unsafe {
let arr = value.0.data[0] as *const glib::GArray; let arr = value.data[0] as *const glib::GArray;
if arr.is_null() { if arr.is_null() {
Some(&[]) Some(&[])
@ -392,8 +459,8 @@ impl<'a> ValueType<'a> for &'a [Value] {
} }
} }
fn from_value_ref(value_ref: &'a ValueRef<'a>) -> Option<Self> { fn from_value_view(value_view: &'a ValueView<'a>) -> Option<Self> {
if let ValueRef::Array(ref v) = *value_ref { if let ValueView::Array(ref v) = *value_view {
Some(v.as_ref()) Some(v.as_ref())
} else { } else {
None None
@ -448,15 +515,15 @@ impl<'a> From<&'a [Value]> for Value {
} }
} }
impl<'a> From<ValueRef<'a>> for Value { impl<'a> From<ValueView<'a>> for Value {
fn from(value_ref: ValueRef<'a>) -> Value { fn from(value_view: ValueView<'a>) -> Value {
Value::new_from_value_ref(value_ref) Value::from_value_view(value_view)
} }
} }
impl<'a> From<&'a ValueRef<'a>> for Value { impl<'a> From<&'a ValueView<'a>> for Value {
fn from(value_ref: &'a ValueRef<'a>) -> Value { fn from(value_view: &'a ValueView<'a>) -> Value {
Value::new_from_value_ref(value_ref.clone()) Value::from_value_view(value_view.clone())
} }
} }
@ -490,6 +557,13 @@ impl<'a, T> TypedValue<T>
}) })
} }
pub fn from_typed_value_ref(v: &'a TypedValueRef<'a, T>) -> TypedValue<T> {
TypedValue {
value: Value::from_value_ref(&v.value),
phantom: PhantomData,
}
}
pub fn get(&'a self) -> T { pub fn get(&'a self) -> T {
self.value.try_get::<T>().unwrap() self.value.try_get::<T>().unwrap()
} }
@ -571,6 +645,53 @@ impl<'a> From<&'a Buffer> for TypedValue<GstRc<Buffer>> {
} }
} }
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct TypedValueRef<'a, T> {
value: ValueRef<'a>,
phantom: PhantomData<T>,
}
impl<'a, T> TypedValueRef<'a, T>
where T: ValueType<'a>
{
pub fn from_typed_value(v: &'a TypedValue<T>) -> TypedValueRef<'a, T> {
TypedValueRef {
value: ValueRef::from_value(&v.value),
phantom: PhantomData,
}
}
pub fn from_value_ref(value: ValueRef<'a>) -> Option<TypedValueRef<'a, T>> {
if value.0.g_type != T::g_type() {
return None;
}
Some(TypedValueRef {
value: value,
phantom: PhantomData,
})
}
pub fn get(&'a self) -> T {
self.value.try_get::<T>().unwrap()
}
pub fn into_value(self) -> ValueRef<'a> {
self.value
}
pub unsafe fn as_ptr(&self) -> *const gobject::GValue {
self.value.0
}
pub unsafe fn from_ptr(ptr: *const gobject::GValue) -> Option<TypedValueRef<'a, T>> {
if let Some(value) = ValueRef::from_ptr(ptr) {
return TypedValueRef::from_value_ref(value);
}
None
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -583,7 +704,7 @@ mod tests {
unsafe { gst::gst_init(ptr::null_mut(), ptr::null_mut()) }; unsafe { gst::gst_init(ptr::null_mut(), ptr::null_mut()) };
let value = Value::new($value); let value = Value::new($value);
if let ValueRef::$variant(v) = value.get() { if let ValueView::$variant(v) = value.get() {
assert_eq!(v, $value); assert_eq!(v, $value);
} else { } else {
unreachable!(); unreachable!();
@ -596,13 +717,13 @@ mod tests {
} }
let value2 = value.clone(); let value2 = value.clone();
if let ValueRef::$variant(v) = value2.get() { if let ValueView::$variant(v) = value2.get() {
assert_eq!(v, $value); assert_eq!(v, $value);
} else { } else {
unreachable!(); unreachable!();
} }
let value2 = Value::new_from_value_ref(value.get()); let value2 = Value::from_value_view(value.get());
assert_eq!(value2, value); assert_eq!(value2, value);
let value3 = TypedValue::new($value); let value3 = TypedValue::new($value);
@ -631,7 +752,7 @@ mod tests {
let orig_v = String::from("foo"); let orig_v = String::from("foo");
let value = Value::new(orig_v.clone()); let value = Value::new(orig_v.clone());
if let ValueRef::String(v) = value.get() { if let ValueView::String(v) = value.get() {
assert_eq!(v, orig_v); assert_eq!(v, orig_v);
} else { } else {
unreachable!(); unreachable!();
@ -644,17 +765,17 @@ mod tests {
} }
let value2 = value.clone(); let value2 = value.clone();
if let ValueRef::String(v) = value2.get() { if let ValueView::String(v) = value2.get() {
assert_eq!(v, orig_v); assert_eq!(v, orig_v);
} else { } else {
unreachable!(); unreachable!();
} }
let value2 = Value::new_from_value_ref(value.get()); let value2 = Value::from_value_view(value.get());
assert_eq!(value2, value); assert_eq!(value2, value);
let value2 = Value::new_from_value_ref(value.get()); let value2 = Value::from_value_view(value.get());
assert_eq!(value2, value); assert_eq!(value2, value);
let value3 = TypedValue::new(orig_v.clone()); let value3 = TypedValue::new(orig_v.clone());
@ -674,7 +795,7 @@ mod tests {
let orig_v = "foo"; let orig_v = "foo";
let value = Value::new(orig_v); let value = Value::new(orig_v);
if let ValueRef::String(v) = value.get() { if let ValueView::String(v) = value.get() {
assert_eq!(v, orig_v); assert_eq!(v, orig_v);
} else { } else {
unreachable!(); unreachable!();
@ -687,13 +808,13 @@ mod tests {
} }
let value2 = value.clone(); let value2 = value.clone();
if let ValueRef::String(v) = value2.get() { if let ValueView::String(v) = value2.get() {
assert_eq!(v, orig_v); assert_eq!(v, orig_v);
} else { } else {
unreachable!(); unreachable!();
} }
let value2 = Value::new_from_value_ref(value.get()); let value2 = Value::from_value_view(value.get());
assert_eq!(value2, value); assert_eq!(value2, value);
let value3 = TypedValue::new(orig_v); let value3 = TypedValue::new(orig_v);
@ -713,7 +834,7 @@ mod tests {
let orig_v = vec![Value::new("a"), Value::new("b")]; let orig_v = vec![Value::new("a"), Value::new("b")];
let value = Value::new(orig_v.clone()); let value = Value::new(orig_v.clone());
if let ValueRef::Array(arr) = value.get() { if let ValueView::Array(arr) = value.get() {
assert_eq!(arr, orig_v.as_slice()); assert_eq!(arr, orig_v.as_slice());
} else { } else {
unreachable!(); unreachable!();
@ -725,10 +846,10 @@ mod tests {
unreachable!(); unreachable!();
} }
let value2 = Value::new_from_value_ref(value.get()); let value2 = Value::from_value_view(value.get());
assert_eq!(value2, value); assert_eq!(value2, value);
let value2 = Value::new_from_value_ref(value.get()); let value2 = Value::from_value_view(value.get());
assert_eq!(value2, value); assert_eq!(value2, value);
let value3 = TypedValue::new(orig_v.clone()); let value3 = TypedValue::new(orig_v.clone());
@ -748,7 +869,7 @@ mod tests {
let orig_v = vec![Value::new("a"), Value::new("b")]; let orig_v = vec![Value::new("a"), Value::new("b")];
let value = Value::new(&orig_v); let value = Value::new(&orig_v);
if let ValueRef::Array(arr) = value.get() { if let ValueView::Array(arr) = value.get() {
assert_eq!(arr, orig_v.as_slice()); assert_eq!(arr, orig_v.as_slice());
} else { } else {
unreachable!(); unreachable!();
@ -760,7 +881,7 @@ mod tests {
unreachable!(); unreachable!();
} }
let value2 = Value::new_from_value_ref(value.get()); let value2 = Value::from_value_view(value.get());
assert_eq!(value2, value); assert_eq!(value2, value);
let value3 = TypedValue::new(orig_v.as_slice()); let value3 = TypedValue::new(orig_v.as_slice());
@ -777,10 +898,10 @@ mod tests {
fn buffer() { fn buffer() {
unsafe { gst::gst_init(ptr::null_mut(), ptr::null_mut()) }; unsafe { gst::gst_init(ptr::null_mut(), ptr::null_mut()) };
let orig_v = Buffer::new_from_vec(vec![1, 2, 3, 4]).unwrap(); let orig_v = Buffer::from_vec(vec![1, 2, 3, 4]).unwrap();
let value = Value::new(orig_v.clone()); let value = Value::new(orig_v.clone());
if let ValueRef::Buffer(buf) = value.get() { if let ValueView::Buffer(buf) = value.get() {
assert_eq!(buf, orig_v); assert_eq!(buf, orig_v);
} else { } else {
unreachable!(); unreachable!();
@ -792,7 +913,7 @@ mod tests {
unreachable!(); unreachable!();
} }
let value2 = Value::new_from_value_ref(value.get()); let value2 = Value::from_value_view(value.get());
assert_eq!(value2, value); assert_eq!(value2, value);
let value3 = TypedValue::new(&orig_v); let value3 = TypedValue::new(&orig_v);