Skip to content
This repository has been archived by the owner on Mar 4, 2024. It is now read-only.

Commit

Permalink
WIP: Refactor Value traits
Browse files Browse the repository at this point in the history
Fixes #48
  • Loading branch information
sdroege committed Dec 13, 2020
1 parent 1ce935c commit e4cd478
Show file tree
Hide file tree
Showing 11 changed files with 1,246 additions and 649 deletions.
148 changes: 103 additions & 45 deletions glib-macros/src/gboxed_derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,48 +17,108 @@ fn gen_option_to_ptr() -> TokenStream {
}
}

fn gen_ptr_to_option(name: &Ident, nullable: bool) -> TokenStream {
if nullable {
quote! {
if ptr.is_null() {
None
} else {
Some(&*(ptr as *mut #name))
fn gen_impl_from_value(name: &Ident, crate_ident: &Ident) -> TokenStream {
quote! {
impl<'a> #crate_ident::value::FromValue<'a> for #name {
type Error = #crate_ident::value::WrongValueTypeOrNoneError;

fn check(value: &'a #crate_ident::Value) -> Result<(), Self::Error> {
#crate_ident::value::WrongValueTypeError::check::<#name>(value)?;

unsafe {
let ptr = #crate_ident::gobject_ffi::g_value_get_boxed(#crate_ident::translate::ToGlibPtr::to_glib_none(value).0);
if ptr.is_null() {
return Err(#crate_ident::value::WrongValueTypeOrNoneError::UnexpectedNone);
}
}

Ok(())
}

fn from_value(value: &'a #crate_ident::Value) -> Result<Self, Self::Error> {
Self::check(value)?;

unsafe {
let ptr = #crate_ident::gobject_ffi::g_value_dup_boxed(#crate_ident::translate::ToGlibPtr::to_glib_none(value).0);
assert!(!ptr.is_null());
Ok(Box::from_raw(ptr as *mut #name))
}
}
}
} else {
quote! {
assert!(!ptr.is_null());
Some(&*(ptr as *mut #name))

impl<'a> #crate_ident::value::FromValue<'a> for &'a #name {
type Error = #crate_ident::value::WrongValueTypeOrNoneError;

fn check(value: &'a #crate_ident::Value) -> Result<(), Self::Error> {
<Self as #crate_ident::value::FromValue>::check(value)
}

fn from_value(value: &'a #crate_ident::Value) -> Result<Self, Self::Error> {
Self::check(value)?;

unsafe {
let ptr = #crate_ident::gobject_ffi::g_value_get_boxed(#crate_ident::translate::ToGlibPtr::to_glib_none(value).0);
assert!(!ptr.is_null());
Ok(&*(ptr as *mut #name))
}
}
}
}
}

fn gen_impl_from_value(name: &Ident, crate_ident: &Ident) -> TokenStream {
fn gen_impl_from_value_optional(name: &Ident, crate_ident: &Ident) -> TokenStream {
quote! {
impl<'a> #crate_ident::value::FromValue<'a> for #name {
type Error = #crate_ident::value::WrongValueTypeError;

fn check(value: &'a #crate_ident::Value) -> Result<(), Self::Error> {
#crate_ident::value::WrongValueTypeError::check::<#name>(value)
}

fn from_value(value: &'a #crate_ident::Value) -> Result<Self, Self::Error> {
Self::check(value)?;

unsafe {
let ptr = #crate_ident::gobject_ffi::g_value_dup_boxed(#crate_ident::translate::ToGlibPtr::to_glib_none(value).0);
assert!(!ptr.is_null());
Ok(Box::from_raw(ptr as *mut #name))
}
}
}

impl<'a> #crate_ident::value::FromValue<'a> for &'a #name {
unsafe fn from_value(value: &'a #crate_ident::value::Value) -> Self {
let ptr = #crate_ident::gobject_ffi::g_value_get_boxed(
#crate_ident::translate::ToGlibPtr::to_glib_none(value).0,
);
assert!(!ptr.is_null());
&*(ptr as *mut #name)
type Error = #crate_ident::value::WrongValueTypeError;

fn check(value: &'a #crate_ident::Value) -> Result<(), Self::Error> {
<Self as #crate_ident::value::FromValue>::check(value)
}

fn from_value(value: &'a #crate_ident::Value) -> Result<Self, Self::Error> {
Self::check(value)?;

unsafe {
let ptr = #crate_ident::gobject_ffi::g_value_get_boxed(#crate_ident::translate::ToGlibPtr::to_glib_none(value).0);
assert!(!ptr.is_null());
Ok(&*(ptr as *mut #name))
}
}
}
}
}

fn gen_impl_set_value_optional(name: &Ident, crate_ident: &Ident) -> TokenStream {
fn gen_impl_to_value_optional(name: &Ident, crate_ident: &Ident) -> TokenStream {
let option_to_ptr = gen_option_to_ptr();

quote! {
impl #crate_ident::value::SetValueOptional for #name {
unsafe fn set_value_optional(value: &mut #crate_ident::value::Value, this: Option<&Self>) {
let ptr: *mut #name = #option_to_ptr;
#crate_ident::gobject_ffi::g_value_take_boxed(
#crate_ident::translate::ToGlibPtrMut::to_glib_none_mut(value).0,
ptr as *mut _,
);
impl #crate_ident::value::ToValueOptional for #name {
fn to_value_optional(s: &Option<Self>) -> #crate_ident::Value {
let mut value = #crate_ident::Value::for_value_type::<#name>();
unsafe {
let ptr: *mut #name = #option_to_ptr;
#crate_ident::gobject_ffi::g_value_take_boxed(#crate_ident::translate::ToGlibPtrMut::to_glib_none_mut(value).0, ptr as *mut _);
}

value
}
}
}
Expand All @@ -82,14 +142,13 @@ pub fn impl_gboxed(input: &syn::DeriveInput) -> TokenStream {
.unwrap();
let nullable = find_nested_meta(&meta, "nullable").is_some();

let ptr_to_option = gen_ptr_to_option(name, nullable);
let impl_from_value = if !nullable {
gen_impl_from_value(name, &crate_ident)
} else {
quote! {}
gen_impl_from_value_optional(name, &crate_ident)
};
let impl_set_value_optional = if nullable {
gen_impl_set_value_optional(name, &crate_ident)
let impl_to_value_optional = if nullable {
gen_impl_to_value_optional(name, &crate_ident)
} else {
quote! {}
};
Expand Down Expand Up @@ -119,27 +178,26 @@ pub fn impl_gboxed(input: &syn::DeriveInput) -> TokenStream {
}
}

impl #crate_ident::value::SetValue for #name {
unsafe fn set_value(value: &mut #crate_ident::value::Value, this: &Self) {
let ptr: *mut #name = Box::into_raw(Box::new(this.clone()));
#crate_ident::gobject_ffi::g_value_take_boxed(
#crate_ident::translate::ToGlibPtrMut::to_glib_none_mut(value).0,
ptr as *mut _,
);
}
impl #crate_ident::value::ValueType for #name {
type Type = #name;
}

#impl_set_value_optional
impl #crate_ident::value::ToValue for #name {
fn to_value(&self) -> #crate_ident::Value {
unsafe {
let mut value = #crate_ident::Value::from_type(<#name as #crate_ident::StaticType>::static_type());
#crate_ident::gobject_ffi::g_value_take_boxed(#crate_ident::translate::ToGlibPtrMut::to_glib_none_mut(value).0, #crate_ident::translate::ToGlibPtr::to_glib_full(self) as *mut _);
value
}
}

impl<'a> #crate_ident::value::FromValueOptional<'a> for &'a #name {
unsafe fn from_value_optional(value: &'a #crate_ident::value::Value) -> Option<Self> {
let ptr = #crate_ident::gobject_ffi::g_value_get_boxed(
#crate_ident::translate::ToGlibPtr::to_glib_none(value).0,
);
#ptr_to_option
fn to_value_type(&self) -> #crate_ident::Type {
<#name as #crate_ident::StaticType>::static_type()
}
}

#impl_to_value_optional

#impl_from_value
}
}
76 changes: 67 additions & 9 deletions glib/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,23 +253,81 @@ macro_rules! glib_boxed_wrapper {
}

#[doc(hidden)]
impl<'a> $crate::value::FromValueOptional<'a> for $name {
unsafe fn from_value_optional(value: &$crate::Value) -> Option<Self> {
$crate::translate::from_glib_full($crate::gobject_ffi::g_value_dup_boxed($crate::translate::ToGlibPtr::to_glib_none(value).0) as *mut $ffi_name)
impl $crate::value::ValueType for $name {
type Type = $name;
}

#[doc(hidden)]
impl<'a> $crate::value::FromValue<'a> for $name {
type Error = $crate::value::WrongValueTypeOrNoneError;

fn check(value: &'a $crate::Value) -> Result<(), Self::Error> {
$crate::value::WrongValueTypeError::check::<$name>(value)?;

unsafe {
let ptr = $crate::gobject_ffi::g_value_get_boxed($crate::translate::ToGlibPtr::to_glib_none(value).0);
if ptr.is_null() {
return Err($crate::value::WrongValueTypeOrNoneError::UnexpectedNone);
}
}

Ok(())
}

fn from_value(value: &'a $crate::Value) -> Result<Self, Self::Error> {
Self::check(value)?;

unsafe {
let ptr = $crate::gobject_ffi::g_value_dup_boxed($crate::translate::ToGlibPtr::to_glib_none(value).0);
assert!(!ptr.is_null());
Ok(<$name as $crate::translate::FromGlibPtrFull<*mut $ffi_name>>::from_glib_full(ptr as *mut $ffi_name))
}
}
}

#[doc(hidden)]
impl $crate::value::ToValue for $name {
fn to_value(&self) -> $crate::Value {
unsafe {
let mut value = $crate::Value::from_type(<$name as $crate::StaticType>::static_type());
$crate::gobject_ffi::g_value_take_boxed($crate::translate::ToGlibPtrMut::to_glib_none_mut(value).0, $crate::translate::ToGlibPtr::to_glib_full(self) as *mut _);
value
}
}

fn to_value_type(&self) -> $crate::Type {
<$name as $crate::StaticType>::static_type()
}
}

#[doc(hidden)]
impl $crate::value::ToValueOptional for $name {
fn to_value_optional(s: &Option<Self>) -> $crate::Value {
let mut value = $crate::Value::for_value_type::<$name>();
unsafe {
let ptr = if let Some(s) = s {
$crate::translate::ToGlibPtr::to_glib_full(s)
} else {
std::ptr::null_mut()
};
$crate::gobject_ffi::g_value_take_boxed($crate::translate::ToGlibPtrMut::to_glib_none_mut(value).0, ptr as *mut _);
}

value
}
}

#[doc(hidden)]
impl $crate::value::SetValue for $name {
unsafe fn set_value(value: &mut $crate::Value, this: &Self) {
$crate::gobject_ffi::g_value_set_boxed($crate::translate::ToGlibPtrMut::to_glib_none_mut(value).0, $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(this).0 as $crate::ffi::gpointer)
impl $crate::value::UsableAsParam for $name {
fn param_spec(name: &str, nick: &str, blurb: &str, flags: $crate::ParamFlags) -> $crate::ParamSpec {
$crate::ParamSpec::boxed(name, nick, blurb, <$name as $crate::StaticType>::static_type(), flags)
}
}

#[doc(hidden)]
impl $crate::value::SetValueOptional for $name {
unsafe fn set_value_optional(value: &mut $crate::Value, this: Option<&Self>) {
$crate::gobject_ffi::g_value_set_boxed($crate::translate::ToGlibPtrMut::to_glib_none_mut(value).0, $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(&this).0 as $crate::ffi::gpointer)
impl $crate::value::UsableAsParam for Option<$name> {
fn param_spec(name: &str, nick: &str, blurb: &str, flags: $crate::ParamFlags) -> $crate::ParamSpec {
$crate::ParamSpec::boxed(name, nick, blurb, <$name as $crate::StaticType>::static_type(), flags)
}
}
};
Expand Down
88 changes: 71 additions & 17 deletions glib/src/gstring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ use std::ptr;
use std::slice;
use std::string::String;

use crate::value::{FromValueOptional, SetValue, SetValueOptional, Value};

#[derive(Debug)]
pub struct GString(Inner);

Expand Down Expand Up @@ -493,30 +491,86 @@ impl StaticType for Vec<GString> {
}
}

impl<'a> FromValueOptional<'a> for GString {
unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
let val = value.to_glib_none().0;
if val.is_null() {
None
} else {
let ptr = gobject_ffi::g_value_dup_string(val);
Some(GString::new(ptr))
}
impl crate::value::ValueType for GString {
type Type = String;
}

impl<'a> crate::value::FromValue<'a> for GString {
type Error = crate::value::WrongValueTypeOrNoneError;

fn check(value: &'a crate::Value) -> Result<(), Self::Error> {
<&str>::check(value)
}

fn from_value(value: &'a crate::Value) -> Result<Self, Self::Error> {
<&str>::from_value(value).map(GString::from)
}
}

impl SetValue for GString {
unsafe fn set_value(value: &mut Value, this: &Self) {
gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
impl crate::value::ToValue for GString {
fn to_value(&self) -> crate::Value {
<&str>::to_value(self.as_str())
}

fn to_value_type(&self) -> Type {
String::static_type()
}
}

impl SetValueOptional for GString {
unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
impl crate::value::ToValueOptional for GString {
fn to_value_optional(s: &Option<Self>) -> crate::Value {
<&str>::to_value_optional(s.as_deref())
}
}

impl crate::value::UsableAsParam for GString {
fn param_spec(
name: &str,
nick: &str,
blurb: &str,
flags: crate::ParamFlags,
) -> crate::ParamSpec {
crate::ParamSpec::string(name, nick, blurb, flags, Some(String::new()))
}
}

impl crate::value::UsableAsParamWithDefault for GString {
fn param_spec_with_default(
name: &str,
nick: &str,
blurb: &str,
default: &String,
flags: crate::ParamFlags,
) -> crate::ParamSpec {
crate::ParamSpec::string(name, nick, blurb, flags, default)
}
}

impl crate::value::UsableAsParam for Option<GString> {
fn param_spec(
name: &str,
nick: &str,
blurb: &str,
flags: crate::ParamFlags,
) -> crate::ParamSpec {
crate::ParamSpec::string(name, nick, blurb, flags, None)
}
}

impl crate::value::UsableAsParamWithDefault for Option<GString> {
fn param_spec_with_default(
name: &str,
nick: &str,
blurb: &str,
default: &Option<String>,
flags: crate::ParamFlags,
) -> crate::ParamSpec {
crate::ParamSpec::string(name, nick, blurb, flags, default)
}
}

// TODO: Also for Vec<>, &[], []

impl_from_glib_container_as_vec_string!(GString, *const c_char);
impl_from_glib_container_as_vec_string!(GString, *mut c_char);

Expand Down
Loading

0 comments on commit e4cd478

Please sign in to comment.