Merge branch 'unclone' into 'master'

util: C-wrapped data don't need to be cloneable

See merge request Librem5/squeekboard!213
This commit is contained in:
David Boddie
2019-10-10 17:34:03 +00:00
3 changed files with 29 additions and 13 deletions

View File

@ -10,6 +10,7 @@ use ::action::Action;
use std::io::Write; use std::io::Write;
use std::iter::{ FromIterator, IntoIterator }; use std::iter::{ FromIterator, IntoIterator };
use ::util::CloneOwned;
/// Gathers stuff defined in C or called by C /// Gathers stuff defined in C or called by C
pub mod c { pub mod c {
@ -48,13 +49,13 @@ pub mod c {
pub extern "C" pub extern "C"
fn squeek_key_is_pressed(key: CKeyState) -> u32 { fn squeek_key_is_pressed(key: CKeyState) -> u32 {
//let key = unsafe { Rc::from_raw(key.0) }; //let key = unsafe { Rc::from_raw(key.0) };
return key.to_owned().pressed as u32; return key.clone_owned().pressed as u32;
} }
#[no_mangle] #[no_mangle]
pub extern "C" pub extern "C"
fn squeek_key_is_locked(key: CKeyState) -> u32 { fn squeek_key_is_locked(key: CKeyState) -> u32 {
return key.to_owned().locked as u32; return key.clone_owned().locked as u32;
} }
#[no_mangle] #[no_mangle]

View File

@ -27,6 +27,8 @@ use ::action::Action;
use ::float_ord::FloatOrd; use ::float_ord::FloatOrd;
use ::keyboard::*; use ::keyboard::*;
use ::util::CloneOwned;
/// Gathers stuff defined in C or called by C /// Gathers stuff defined in C or called by C
pub mod c { pub mod c {
use super::*; use super::*;
@ -270,7 +272,7 @@ pub mod c {
) { ) {
let layout = unsafe { &mut *layout }; let layout = unsafe { &mut *layout };
let view_name = match key.to_owned().action { let view_name = match key.clone_owned().action {
Action::SetLevel(name) => { Action::SetLevel(name) => {
Some(name.clone()) Some(name.clone())
}, },

View File

@ -4,6 +4,8 @@ use std::collections::HashMap;
use std::iter::FromIterator; use std::iter::FromIterator;
pub mod c { pub mod c {
use super::*;
use std::cell::RefCell; use std::cell::RefCell;
use std::ffi::{ CStr, CString }; use std::ffi::{ CStr, CString };
use std::os::raw::c_char; use std::os::raw::c_char;
@ -63,7 +65,7 @@ pub mod c {
/// RefCell will enforce them dynamically (only 1 writer/many readers) /// RefCell will enforce them dynamically (only 1 writer/many readers)
/// Rc is implied and will ensure timely dropping /// Rc is implied and will ensure timely dropping
#[repr(transparent)] #[repr(transparent)]
pub struct Wrapped<T: Clone>(*const RefCell<T>); pub struct Wrapped<T>(*const RefCell<T>);
// It would be nice to implement `Borrow` // It would be nice to implement `Borrow`
// directly on the raw pointer to avoid one conversion call, // directly on the raw pointer to avoid one conversion call,
@ -73,7 +75,7 @@ pub mod c {
// Unfortunately, that needs a `Ref` struct with self-referential fields, // Unfortunately, that needs a `Ref` struct with self-referential fields,
// which is a bit too complex for now. // which is a bit too complex for now.
impl<T: Clone> Wrapped<T> { impl<T> Wrapped<T> {
pub fn wrap(state: Rc<RefCell<T>>) -> Wrapped<T> { pub fn wrap(state: Rc<RefCell<T>>) -> Wrapped<T> {
Wrapped(Rc::into_raw(state)) Wrapped(Rc::into_raw(state))
} }
@ -91,20 +93,31 @@ pub mod c {
Rc::into_raw(used_rc); // prevent dropping the original reference Rc::into_raw(used_rc); // prevent dropping the original reference
rc rc
} }
}
impl<T> Clone for Wrapped<T> {
fn clone(&self) -> Wrapped<T> {
Wrapped::wrap(self.clone_ref())
}
}
/// ToOwned won't work here
/// because it's really difficult to implement Borrow on Wrapped<T>
/// with the Rc<RefCell<>> chain on the way to the data
impl<T: Clone> CloneOwned for Wrapped<T> {
type Owned = T;
/// Create a copy of the underlying data fn clone_owned(&self) -> T {
pub fn to_owned(&self) -> T {
let rc = self.clone_ref(); let rc = self.clone_ref();
let r = rc.borrow(); let r = rc.borrow();
r.to_owned() r.to_owned()
} }
} }
}
impl<T: Clone> Clone for Wrapped<T> {
fn clone(&self) -> Wrapped<T> { pub trait CloneOwned {
Wrapped::wrap(self.clone_ref()) type Owned;
} fn clone_owned(&self) -> Self::Owned;
}
} }
pub fn hash_map_map<K, V, F, K1, V1>(map: HashMap<K, V>, mut f: F) pub fn hash_map_map<K, V, F, K1, V1>(map: HashMap<K, V>, mut f: F)