Skip to content
This repository was archived by the owner on Jun 8, 2021. It is now read-only.

Conversation

vhdirk
Copy link

@vhdirk vhdirk commented Jun 18, 2018

This PR enables wrapping a VariantTy(pe) in Value

@GuillaumeGomez
Copy link
Member

cc @sdroege @EPashkin

Copy link
Member

@sdroege sdroege left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good but incomplete. Please add both directions for both types :)


impl SetValue for VariantTy {
unsafe fn set_value(value: &mut Value, this: &Self) {
gobject_ffi::g_value_take_boxed(value.to_glib_none_mut().0, this.to_glib_none().0 as glib_ffi::gpointer)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be set_boxed? The rust part takes a reference, not ownership of the variant ty

@@ -2,6 +2,9 @@
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use libc::{c_void};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unneeded {}


impl SetValueOptional for VariantTy {
unsafe fn set_value_optional(value: &mut Value, this: Option<&Self>) {
gobject_ffi::g_value_take_boxed(value.to_glib_none_mut().0, this.to_glib_none().0 as glib_ffi::gpointer)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is NULL a valid VariantTy?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not. I guess NULL would be "*"?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to be checked in the GLib code, in the implementation of the boxed<->variantty code. Will check tomorrow if nobody else is faster :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It goes into g_variant_type_copy(), which says that it must not be NULL. So no SetValueOptional for both and you can implement FromValue for both

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So needed: StaticType, FromValueOptional, FromValue and SetValue for both types

impl<'a> FromValueOptional<'a> for &'a VariantTy {
unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
let cvty = gobject_ffi::g_value_dup_boxed(value.to_glib_none().0) as *mut glib_ffi::GVariantType;
if cvty.is_null() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert for NULL here as it's not allowed


impl<'a> FromValueOptional<'a> for &'a VariantTy {
unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
let cvty = gobject_ffi::g_value_dup_boxed(value.to_glib_none().0) as *mut glib_ffi::GVariantType;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're leaking the memory here, this has to be get_boxed()


impl<'a> FromValueOptional<'a> for VariantType {
unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
Option::<VariantType>::from_glib_full(gobject_ffi::g_value_dup_boxed(value.to_glib_none().0) as *mut glib_ffi::GVariantType)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be from_glib_none() and get_boxed().

See also this comment in the code from from_glib_full:

impl FromGlibPtrFull<*const glib_ffi::GVariantType> for VariantType {
    unsafe fn from_glib_full(ptr: *const glib_ffi::GVariantType) -> VariantType {
        // Don't assume ownership of a const pointer.
        // A transfer: full annotation on a `const GVariantType*` is likely a bug.
        VariantTy::from_ptr(ptr).to_owned()
    }
}

@vhdirk
Copy link
Author

vhdirk commented Jun 20, 2018

How come a VariantType can't be null? This test seems to tell otherwise? https://gitlab.gnome.org/GNOME/glib/blob/master/gio/tests/actions.c

@sdroege
Copy link
Member

sdroege commented Jun 20, 2018

How come a VariantType can't be null? This test seems to tell otherwise? https://gitlab.gnome.org/GNOME/glib/blob/master/gio/tests/actions.c

Inside GValue it is using g_variant_type_copy(), which will assert if NULL is passed:
https://gitlab.gnome.org/GNOME/glib/blob/b9aed426d198ccf27078263d982bb247c82ccaee/glib/gvarianttype.c#L330 and https://gitlab.gnome.org/GNOME/glib/blob/b9aed426d198ccf27078263d982bb247c82ccaee/glib/gvarianttype.c#L184-188

That might be a bug on the GLib side though. Do you need it to be NULL for anything?

Some(VariantTy::from_ptr(cvty))
}
let cvty = gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *mut glib_ffi::GVariantType;
assert!(cvty.is_null());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is missing a negation. You want to assert that it is not NULL

@vhdirk
Copy link
Author

vhdirk commented Jun 20, 2018

That might be a bug on the GLib side though. Do you need it to be NULL for anything?

Not necessarily. Only for aping SimpleAction

@sdroege
Copy link
Member

sdroege commented Jun 20, 2018

That might be a bug on the GLib side though. Do you need it to be NULL for anything?

Not necessarily. Only for aping SimpleAction

How does it work in SimpleAction (why does it not run into these assertions?), what are the NULL types used for exactly?

@vhdirk
Copy link
Author

vhdirk commented Jun 20, 2018

The docs of SimpleAction state:

The type of the parameter that must be given when activating the action.

I've never used GAction before, so I'm not sure what that means. And my rust version of SimpleAction is still panicking somewhere without a clear trace...

@vhdirk
Copy link
Author

vhdirk commented Jun 20, 2018

More from the docs

Since GLib 2.40, if no handler is connected to this signal then the default behaviour for boolean-stated actions with a NULL parameter type is to toggle them via the “change-state” signal.

@sdroege
Copy link
Member

sdroege commented Jun 20, 2018

That hints at a bug in GLib then, that clearly says that NULL types are expected behaviour... but running g_boxed_copy() on such GValues (as from the signals) would assert. Can you file a bug against GLib about that?

@vhdirk
Copy link
Author

vhdirk commented Jun 20, 2018

From what I can tell, it is not so much GValueType that is not nullable, rather the type string itself?

@sdroege
Copy link
Member

sdroege commented Jun 21, 2018

From what I can tell, it is not so much GValueType that is not nullable, rather the type string itself?

I'm not sure what you mean with this. GVariantType seems to be possible to be NULL in various contexts, just not when stored in a GValue (but GSimpleAction seems to use it as such nonetheless).

@vhdirk
Copy link
Author

vhdirk commented Jun 21, 2018

Looking at the implementation of g_variant_type_copy, I think the documentation is wrong.

GVariantType *
g_variant_type_copy (const GVariantType *type)
{
  gsize length;
  gchar *new;

  g_return_val_if_fail (g_variant_type_check (type), NULL);

  <snip>
}

There's no assertion here. It will just return another null pointer when you provide it a null pointer.

@sdroege
Copy link
Member

sdroege commented Jun 21, 2018

g_return_val_if_fail (g_variant_type_check (type), NULL);

This is an assertion (it will return FALSE for NULL)

@vhdirk
Copy link
Author

vhdirk commented Jun 21, 2018

Are you sure?

According to the docs:

#define             g_return_val_if_fail(expr,val)

It will return val if expr evaluates to FALSE.

So in this case, it will return NULL when g_variant_type_check(type) returns FALSE. Which is the case when type is NULL to begin with.

@sdroege
Copy link
Member

sdroege commented Jun 21, 2018

It's only to be used as a guard against programming mistakes. It's an assertion, but not taking down your application unless yet set G_DEBUG=fatal_criticals. It causes a g_critical() warning, which is also printed on stderr.

@vhdirk
Copy link
Author

vhdirk commented Jun 21, 2018

Ah, I though that was just a shorthand. So yeah, this is a bug in glib then.

@sdroege
Copy link
Member

sdroege commented Jun 21, 2018

Ah, I though that was just a shorthand. So yeah, this is a bug in glib then.

Lovely :) Not sure what we can do about that, need a workaround until a new GLib version arrives. But your code making it nullable is correct then, just GLib isn't correct.

@sdroege
Copy link
Member

sdroege commented Jun 21, 2018

I would suggest to file a bug there and go ahead with your implementation. It will not cause unsafety, it only causes ugly warnings on the terminal and those are GLib's problem

}
}

// impl SetValueOptional for VariantType {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can include this one now :)

@sdroege
Copy link
Member

sdroege commented Jun 21, 2018

Looks good to me, but please also link to the GLib bug report about this here for future reference

@vhdirk
Copy link
Author

vhdirk commented Jun 21, 2018

I'll create the glib bug report soon.

@vhdirk
Copy link
Author

vhdirk commented Jun 22, 2018

@sdroege
Copy link
Member

sdroege commented Jun 22, 2018

@GuillaumeGomez Let's get this in then?

@GuillaumeGomez
Copy link
Member

Yes! Thanks @vhdirk!

@GuillaumeGomez GuillaumeGomez merged commit f016524 into gtk-rs:master Jun 22, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants