Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function to cast event types without copying #38

Closed
wolfiestyle opened this issue Mar 15, 2016 · 7 comments
Closed

Function to cast event types without copying #38

wolfiestyle opened this issue Mar 15, 2016 · 7 comments

Comments

@wolfiestyle
Copy link
Contributor

I use this in my code, and I think it would be a great addition to the library:

fn cast_event<T: From<xlib::XEvent>>(ev: &xlib::XEvent) -> &T
{
    unsafe { mem::transmute(ev) }
}

it should be safe because the size of XEvent is >= the size of T (tested elsewhere). Using From<XEvent> does an unnecessary copy and this provides an alternative.

@ghost
Copy link

ghost commented Mar 16, 2016

This could be unsafe if another crate implements From<XEvent> for a type not defined in x11-rs. Another way to accomplish the same thing could be to add a function for each type such as:

impl XEvent {
    pub fn as_x_client_message_event (&self) -> &XClientMessageEvent {
        unsafe { mem::transmute(self) }
    }
}

And vice versa:

impl XClientMessageEvent {
    pub fn as_x_event (&self) -> &XEvent {
        unsafe { mem::transmute(self) }
    }
}

A local macro can be used to make these much less verbose.

I recall reading somewhere that it is generally preferred to pass structs by value if they are copyable, but I wonder if the Xlib structures are big enough (I believe XEvent is 128 bytes) for the impact to be significant. Either way, it doesn't hurt to have this option available.

@ghost
Copy link

ghost commented Mar 20, 2016

On second thought, this would only work when converting from XEvent to the other types. The reason is that these structs each have different sizes, which would cause undefined behavior after converting the reference to a larger struct and trying to access an element near the end. We could implement AsRef to get a reference to a concrete event type from XEvent, but not the other way around.

@wolfiestyle
Copy link
Contributor Author

On C this is handled by using an union. What about converting it into a Rust enum?

@ghost
Copy link

ghost commented Mar 23, 2016

With the changes in 4a0c484, you should be able to use XEvent like this:

let mut xevent: XEvent = mem::zeroed();

{
    let mut xclient: &mut XClientMessageEvent = xevent.as_mut();
    xclient.type_ = xlib::ClientMessage;
    xclient.message_type = wm_protocols;
    xclient.format = 32;
    xclient.data.set_long(0, wm_delete_window);
}

xlib::XSendEvent(display, window, xlib::False, 0, &mut xevent);

@wolfiestyle
Copy link
Contributor Author

A pretty nice solution. But XGenericEventCookie was left out.

@ghost
Copy link

ghost commented Apr 23, 2016

22dff4d and the changes are published :D

@wolfiestyle
Copy link
Contributor Author

Thanks!

BTW I think the union RFC was approved some time ago, so we won't need this type of stuff in the future.

@ghost ghost closed this as completed Apr 27, 2016
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant