use {Output, View};
use ffi;
use libc::c_void;
use output::handle as output_handle;
use std::any::Any;
use std::mem;
use std::ptr;
use std::rc::Rc;
use view::handle as view_handle;
pub trait Handle {
fn set_user_data<T: Any>(&self, data: T);
unsafe fn user_data<T: Any>(&self) -> Option<Rc<T>>;
unsafe fn try_take_user_data<T: Any>(&self) -> Option<T>;
fn clear_user_data(&self);
}
impl Handle for Output {
fn set_user_data<T: Any>(&self, data: T) {
self.clear_user_data();
let boxed = Box::new(Rc::new(data));
unsafe {
ffi::wlc_handle_set_user_data(output_handle(self), Box::into_raw(boxed) as *const c_void);
}
}
unsafe fn user_data<T: Any>(&self) -> Option<Rc<T>> {
let ptr = ffi::wlc_handle_get_user_data(output_handle(self));
let boxed: Box<Rc<T>> = if ptr.is_null() {
return None;
} else {
Box::from_raw(ptr as *mut Rc<T>)
};
let result = Some((*boxed).clone());
mem::forget(boxed);
result
}
unsafe fn try_take_user_data<T: Any>(&self) -> Option<T> {
match self.user_data::<T>() {
Some(rc) => {
self.clear_user_data();
match Rc::try_unwrap(rc) {
Ok(result) => Some(result),
Err(rc) => {
ffi::wlc_handle_set_user_data(output_handle(self),
Box::into_raw(Box::new(rc)) as *const c_void);
None
}
}
}
None => None,
}
}
fn clear_user_data(&self) {
let ptr = unsafe { ffi::wlc_handle_get_user_data(output_handle(self)) };
let _drop: Box<Any> = if ptr.is_null() {
return;
} else {
unsafe { Box::from_raw(ptr as *mut Any) }
};
unsafe {
ffi::wlc_handle_set_user_data(output_handle(self), ptr::null_mut());
}
}
}
impl Handle for View {
fn set_user_data<T: Any>(&self, data: T) {
self.clear_user_data();
let boxed = Box::new(Rc::new(data));
unsafe {
ffi::wlc_handle_set_user_data(view_handle(self), Box::into_raw(boxed) as *const c_void);
}
}
unsafe fn user_data<T: Any>(&self) -> Option<Rc<T>> {
let ptr = ffi::wlc_handle_get_user_data(view_handle(self));
let boxed: Box<Rc<T>> = if ptr.is_null() {
return None;
} else {
Box::from_raw(ptr as *mut Rc<T>)
};
let result = Some((*boxed).clone());
mem::forget(boxed);
result
}
unsafe fn try_take_user_data<T: Any>(&self) -> Option<T> {
match self.user_data::<T>() {
Some(rc) => {
self.clear_user_data();
match Rc::try_unwrap(rc) {
Ok(result) => Some(result),
Err(rc) => {
ffi::wlc_handle_set_user_data(view_handle(self),
Box::into_raw(Box::new(rc)) as *const c_void);
None
}
}
}
None => None,
}
}
fn clear_user_data(&self) {
let ptr = unsafe { ffi::wlc_handle_get_user_data(view_handle(self)) };
let _drop: Box<Any> = if ptr.is_null() {
return;
} else {
unsafe { Box::from_raw(ptr as *mut Any) }
};
unsafe {
ffi::wlc_handle_set_user_data(view_handle(self), ptr::null_mut());
}
}
}