Generate the rust code.

master
Jos van den Oever 2017-08-08 20:07:24 +02:00
parent ff2a0a1f70
commit 91962f3f2b
7 changed files with 178 additions and 68 deletions

View File

@ -8,4 +8,3 @@ libc = "*"
[lib]
name = "rust"
crate-type = ["staticlib"]

View File

@ -46,12 +46,12 @@ impl DirEntry {
}
impl Item for DirEntry {
fn data<'a>(&self, role: c_int) -> Variant<'a> {
fn data(&self, role: c_int) -> Variant {
if role != 0 {
return Variant::None
}
let str = self.name.to_string_lossy().to_string();
return Variant::from(str);
Variant::from(str)
}
fn retrieve(&self, parents: Vec<&DirEntry>) -> Vec<DirEntry> {
let path: PathBuf = parents.into_iter().map(|e|&e.name).collect();
@ -65,7 +65,7 @@ impl Item for DirEntry {
}
}
v.sort_by(|a, b| a.name.cmp(&b.name));
return v;
v
}
}
@ -79,7 +79,7 @@ impl Default for DirEntry {
pub trait Item: Default {
fn retrieve(&self, parents: Vec<&Self>) -> Vec<Self>;
fn data<'a>(&self, role: c_int) -> Variant<'a>;
fn data(&self, role: c_int) -> Variant;
}
pub type RItemModel = RGeneralItemModel<DirEntry>;
@ -117,10 +117,9 @@ impl<T: Item> RGeneralItemModel<T> {
let mut new_entries = Vec::new();
let mut children = Vec::new();
{
let mut row = 0;
let parents = self.get_parents(id);
let entries = self.entries[id].data.retrieve(parents);
for d in entries {
for (row, d) in entries.into_iter().enumerate() {
let e = Entry {
parent: id,
row: row,
@ -128,7 +127,6 @@ impl<T: Item> RGeneralItemModel<T> {
data: d
};
children.push(self.entries.len() + row);
row += 1;
new_entries.push(e);
}
}
@ -172,11 +170,11 @@ impl<T: Item> RItemModelTrait<T> for RGeneralItemModel<T> {
if !index.is_valid() || index.id() == 1 {
return QModelIndex::invalid();
}
let ref e = self.entries[index.id()];
let e = &self.entries[index.id()];
QModelIndex::create(e.row as i32, 0, e.parent)
}
fn data<'a>(&'a mut self, index: QModelIndex, role: c_int) -> Variant<'a> {
fn data(&mut self, index: QModelIndex, role: c_int) -> Variant {
let i = self.get(&index);
return self.entries[i].data.data(role);
self.entries[i].data.data(role)
}
}

View File

@ -1,3 +1,5 @@
#![allow(unknown_lints)]
#![allow(mutex_atomic)]
use std::slice;
use libc::{c_int, uint16_t, size_t, c_void};
use types::*;
@ -36,23 +38,20 @@ pub extern fn hello_new(qobject: *const HelloQObject, changed: fn(*const HelloQO
}
#[no_mangle]
pub extern fn hello_free(ptr: *mut Hello) {
pub unsafe extern fn hello_free(ptr: *mut Hello) {
if ptr.is_null() { return }
unsafe { Box::from_raw(ptr); }
Box::from_raw(ptr);
}
#[no_mangle]
pub extern fn hello_set(ptr: *mut Hello, s: *const uint16_t, len: size_t) {
let (hello, data) = unsafe {
(&mut *ptr, slice::from_raw_parts(s, len as usize))
};
hello.set_hello(String::from_utf16_lossy(data));
pub unsafe extern fn hello_set(ptr: *mut Hello, s: *const uint16_t, len: size_t) {
let data = slice::from_raw_parts(s, len as usize);
(&mut *ptr).set_hello(String::from_utf16_lossy(data));
}
#[no_mangle]
pub extern fn hello_get(ptr: *mut Hello) -> QString {
let hello = unsafe { &mut *ptr };
QString::from(hello.get_hello())
pub unsafe extern fn hello_get(ptr: *const Hello) -> QString {
QString::from((&*ptr).get_hello())
}
@ -85,7 +84,7 @@ pub trait RItemModelTrait<T> {
fn row_count(&mut self, parent: QModelIndex) -> c_int;
fn index(&mut self, row: c_int, column: c_int, parent: QModelIndex) -> QModelIndex;
fn parent(&self, index: QModelIndex) -> QModelIndex;
fn data<'a>(&'a mut self, index: QModelIndex, role: c_int) -> Variant<'a>;
fn data(&mut self, index: QModelIndex, role: c_int) -> Variant;
}
#[no_mangle]
@ -99,38 +98,32 @@ pub extern fn ritemmodel_new(qobject: *const RItemModelQObject, new_data_ready:
}
#[no_mangle]
pub extern fn ritemmodel_free(ptr: *mut RItemModel) {
let ritemmodel = unsafe { Box::from_raw(ptr) };
ritemmodel.emit().clear();
pub unsafe extern fn ritemmodel_free(ptr: *mut RItemModel) {
Box::from_raw(ptr).emit().clear();
}
#[no_mangle]
pub extern fn ritemmodel_column_count(ptr: *mut RItemModel, parent: QModelIndex) -> i32 {
let ritemmodel = unsafe { &mut *ptr };
ritemmodel.column_count(parent)
pub unsafe extern fn ritemmodel_column_count(ptr: *mut RItemModel, parent: QModelIndex) -> i32 {
(&mut *ptr).column_count(parent)
}
#[no_mangle]
pub extern fn ritemmodel_row_count(ptr: *mut RItemModel, parent: QModelIndex) -> i32 {
let ritemmodel = unsafe { &mut *ptr };
ritemmodel.row_count(parent)
pub unsafe extern fn ritemmodel_row_count(ptr: *mut RItemModel, parent: QModelIndex) -> i32 {
(&mut*ptr).row_count(parent)
}
#[no_mangle]
pub extern fn ritemmodel_index(ptr: *mut RItemModel, row: i32, column: i32, parent: QModelIndex) -> QModelIndex {
let ritemmodel = unsafe { &mut *ptr };
ritemmodel.index(row, column, parent)
pub unsafe extern fn ritemmodel_index(ptr: *mut RItemModel, row: i32, column: i32, parent: QModelIndex) -> QModelIndex {
(&mut *ptr).index(row, column, parent)
}
#[no_mangle]
pub extern fn ritemmodel_parent(ptr: *const RItemModel, index: QModelIndex) -> QModelIndex {
let ritemmodel = unsafe { &*ptr };
ritemmodel.parent(index)
pub unsafe extern fn ritemmodel_parent(ptr: *const RItemModel, index: QModelIndex) -> QModelIndex {
(&*ptr).parent(index)
}
#[no_mangle]
pub extern fn ritemmodel_data(ptr: *mut RItemModel, index: QModelIndex, role: c_int, d: *mut c_void, set: fn (*mut c_void, &QVariant)) {
let ritemmodel = unsafe { &mut *ptr };
let data = ritemmodel.data(index, role);
pub unsafe extern fn ritemmodel_data(ptr: *mut RItemModel, index: QModelIndex, role: c_int, d: *mut c_void, set: fn (*mut c_void, &QVariant)) {
let data = (&mut *ptr).data(index, role);
set(d, &QVariant::from(&data));
}

View File

@ -0,0 +1,46 @@
use libc::{c_int};
use types::*;
use testinterface::*;
pub struct Test {
emit: TestEmitter,
username: String,
age: c_int,
active: bool,
misc: Variant
}
impl TestTrait for Test {
fn create(emit: TestEmitter) -> Test {
Test {
emit: emit,
username: String::new(),
age: 0,
active: true,
misc: Variant::None
}
}
fn emit(&self) -> &TestEmitter {
&self.emit
}
fn get_username(&self) -> String { self.username.clone() }
fn set_username(&mut self, value: String) {
self.username = value;
self.emit.username_changed();
}
fn get_age(&self) -> c_int {
self.age
}
fn get_active(&self) -> bool {
self.active
}
fn set_active(&mut self, value: bool) {
self.active = value;
self.emit.active_changed();
}
fn get_misc(&self) -> Variant { Variant::None }
fn set_misc(&mut self, value: Variant) {
self.misc = value;
self.emit.misc_changed();
}
}

View File

@ -1,4 +1,5 @@
use libc::{c_int, c_uint, uint8_t};
use std::slice;
use libc::{c_int, c_uint, uint8_t, uint16_t};
use std::ptr::null;
use std::marker::PhantomData;
@ -8,6 +9,21 @@ pub struct QString {
len: c_int
}
#[repr(C)]
pub struct QStringIn {
data: *const uint16_t,
len: c_int
}
impl QStringIn {
pub fn convert(&self) -> String {
let data = unsafe {
slice::from_raw_parts(self.data, self.len as usize)
};
String::from_utf16_lossy(data)
}
}
impl<'a> From<&'a String> for QString {
fn from(string: &'a String) -> QString {
QString {
@ -17,31 +33,25 @@ impl<'a> From<&'a String> for QString {
}
}
pub enum Variant<'a> {
pub enum Variant {
None,
Bool(bool),
String(String),
Str(&'a str)
ByteArray(Vec<u8>)
}
impl<'a> From<bool> for Variant<'a> {
fn from(value: bool) -> Variant<'a> {
impl From<bool> for Variant {
fn from(value: bool) -> Variant {
Variant::Bool(value)
}
}
impl<'a> From<String> for Variant<'a> {
fn from(value: String) -> Variant<'a> {
impl From<String> for Variant {
fn from(value: String) -> Variant {
Variant::String(value)
}
}
impl<'a> From<&'a str> for Variant<'a> {
fn from(value: &'a str) -> Variant {
Variant::Str(value)
}
}
/* values from qvariant.h and qmetatype.h */
#[repr(u32)]
#[derive(Clone, Copy)]
@ -64,33 +74,37 @@ impl<'a> QVariant<'a> {
pub fn type_(&self) -> u32 {
self.type_ as u32
}
pub fn convert(&self) -> Variant {
// TODO
Variant::None
}
}
impl<'a> From<&'a Variant<'a>> for QVariant<'a> {
fn from(variant: &'a Variant<'a>) -> QVariant {
match variant {
&Variant::None => QVariant {
impl<'a> From<&'a Variant> for QVariant<'a> {
fn from(variant: &'a Variant) -> QVariant {
match *variant {
Variant::None => QVariant {
data: null(),
len: 0,
type_: VariantType::Invalid as c_uint,
phantom: PhantomData
},
&Variant::Bool(v) => QVariant {
Variant::Bool(v) => QVariant {
data: null(),
len: v as c_int,
type_: VariantType::Bool as c_uint,
phantom: PhantomData
},
&Variant::String(ref v) => QVariant {
Variant::String(ref v) => QVariant {
data: v.as_ptr(),
len: v.len() as c_int,
type_: VariantType::String as c_uint,
phantom: PhantomData
},
&Variant::Str(ref v) => QVariant {
Variant::ByteArray(ref v) => QVariant {
data: v.as_ptr(),
len: v.len() as c_int,
type_: VariantType::String as c_uint,
type_: VariantType::ByteArray as c_uint,
phantom: PhantomData
}
}

View File

@ -0,0 +1,21 @@
# Bindings between Qt and Rust
## Glossary
### Property type
The type that is written in the JSON file. This is the type that is type that
is used in the C++ code.
### binding type
The type that is used to transer the data between the Rust and Qt.
### C++ binding type
The C++ version of the type that is transferred between Rust and Qt.
### Rust binding type
The Rust version of the type that is transferred between Rust and Qt.

View File

@ -355,11 +355,13 @@ extern "C" {
}
QString rustType(const Property& p) {
/*
if (p.type == "QVariant") {
return "Variant";
}
*/
if (p.type.startsWith("Q")) {
return "&" + p.type.mid(1);
return p.type.mid(1);
}
if (p.type == "int") {
return "c_int";
@ -407,7 +409,7 @@ pub trait %1Trait {
)").arg(o.name);
for (const Property& p: o.properties) {
const QString lc(p.name.toLower());
const bool q = p.type.startsWith("Q");
// const bool q = p.type.startsWith("Q");
r << QString(" fn get_%1(&self) -> %2;\n").arg(lc, rustType(p));
if (p.write) {
r << QString(" fn set_%1(&mut self, value: %2);\n").arg(lc, rustType(p));
@ -435,11 +437,47 @@ pub extern fn %2_new(qobject: *const %1QObject)").arg(o.name, lcname);
}
#[no_mangle]
pub extern fn %2_free(ptr: *mut %1) {
let d = unsafe { Box::from_raw(ptr) };
d.emit().clear();
pub unsafe extern fn %2_free(ptr: *mut %1) {
Box::from_raw(ptr).emit().clear();
}
)").arg(o.name, lcname);
for (const Property& p: o.properties) {
const QString base = QString("%1_%2").arg(lcname, p.name.toLower());
QString ret = ") -> " + rustType(p);
if (p.type.startsWith("Q")) {
r << QString(R"(
#[no_mangle]
pub unsafe extern fn %2_get(ptr: *const %1, p: *mut c_void, set: fn (*mut c_void, %4)) {
let data = (&*ptr).get_%3();
set(p, %4::from(&data));
}
)").arg(o.name, base, p.name.toLower(), p.type);
if (p.write) {
const QString type = p.type == "QString" ? "QStringIn" : p.type;
r << QString(R"(
#[no_mangle]
pub unsafe extern fn %2_set(ptr: *mut %1, v: %4) {
(&mut *ptr).set_%3(v.convert());
}
)").arg(o.name, base, p.name.toLower(), type);
}
} else {
r << QString(R"(
#[no_mangle]
pub unsafe extern fn %2_get(ptr: *const %1) -> %4 {
(&*ptr).get_%3()
}
)").arg(o.name, base, p.name.toLower(), rustType(p));
if (p.write) {
r << QString(R"(
#[no_mangle]
pub unsafe extern fn %2_set(ptr: *mut %1, v: %4) {
(&mut *ptr).set_%3(v);
}
)").arg(o.name, base, p.name.toLower(), rustType(p));
}
}
}
}
QString rustFile(const QDir rustdir, const QString& module) {
@ -458,8 +496,9 @@ void writeRustInterface(const Configuration& conf) {
}
QTextStream r(&file);
r << QString(R"(
use std::slice;
use libc::{c_int, uint16_t, size_t, c_void};
#![allow(unknown_lints)]
#![allow(mutex_atomic, needless_pass_by_value)]
use libc::{c_int, c_void};
use types::*;
use std::sync::{Arc, Mutex};
use std::ptr::null;