Generate types.rs automatically

master
Jos van den Oever 2017-08-12 13:41:49 +02:00
parent ca8d60b277
commit d1d0fc1277
9 changed files with 249 additions and 9 deletions

View File

@ -47,6 +47,7 @@ endif()
add_custom_command(
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/common-rust/src/testinterface.rs"
"${CMAKE_CURRENT_SOURCE_DIR}/common-rust/src/types.rs"
COMMAND ${CMAKE_BINARY_DIR}/rust_qt_binding_generator/rust_qt_binding_generator "${CMAKE_CURRENT_SOURCE_DIR}/bindings.json"
DEPENDS rust_qt_binding_generator bindings.json
)

View File

@ -3,7 +3,8 @@
"rust": {
"dir": "common-rust",
"interfaceModule": "testinterface",
"implementationModule": "testimplementation"
"implementationModule": "testimplementation",
"typesModule": "types"
},
"objects": [{
"name": "Person",

View File

@ -1,3 +1,4 @@
/* generated by rust_qt_binding_generator */
use std::slice;
use libc::{c_int, c_uint, uint8_t, uint16_t};
use std::ptr::null;
@ -212,3 +213,5 @@ impl QModelIndex {
self.internal_id
}
}

View File

@ -107,6 +107,7 @@ struct Configuration {
QDir rustdir;
QString interfaceModule;
QString implementationModule;
QString typesModule;
QList<Object> objects;
bool overwriteImplementation;
};
@ -191,6 +192,7 @@ parseConfiguration(const QString& path) {
c.rustdir = QDir(base.filePath(rust.value("dir").toString()));
c.interfaceModule = rust.value("interfaceModule").toString();
c.implementationModule = rust.value("implementationModule").toString();
c.typesModule = rust.value("typesModule").toString();
return c;
}
@ -605,7 +607,7 @@ extern "C" {
void writeRustInterfaceObject(QTextStream& r, const Object& o) {
const QString lcname(snakeCase(o.name));
r << QString(R"(/* generated by rust_qt_binding_generator */
r << QString(R"(
pub struct %1QObject {}
#[derive (Clone)]
@ -804,7 +806,7 @@ QString rustFile(const QDir rustdir, const QString& module) {
void writeRustInterface(const Configuration& conf) {
DifferentFileWriter w(rustFile(conf.rustdir, conf.interfaceModule));
QTextStream r(&w.buffer);
r << QString(R"(
r << QString(R"(/* generated by rust_qt_binding_generator */
#![allow(unknown_lints)]
#![allow(mutex_atomic, needless_pass_by_value)]
use libc::{c_int, c_void};
@ -895,6 +897,229 @@ use %1::*;
}
}
void writeRustTypes(const Configuration& conf) {
DifferentFileWriter w(rustFile(conf.rustdir, conf.typesModule));
QTextStream r(&w.buffer);
r << QString(R"(/* generated by rust_qt_binding_generator */
use std::slice;
use libc::{c_int, c_uint, uint8_t, uint16_t};
use std::ptr::null;
use std::marker::PhantomData;
#[repr(C)]
pub struct QString {
data: *const uint8_t,
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 {
len: string.len() as c_int,
data: string.as_ptr(),
}
}
}
#[repr(C)]
pub struct QByteArray {
data: *const uint8_t,
len: c_int,
}
impl QByteArray {
pub fn convert(&self) -> Vec<u8> {
let data = unsafe { slice::from_raw_parts(self.data, self.len as usize) };
Vec::from(data)
}
}
impl<'a> From<&'a Vec<u8>> for QByteArray {
fn from(value: &'a Vec<u8>) -> QByteArray {
QByteArray {
len: value.len() as c_int,
data: value.as_ptr(),
}
}
}
#[derive(Clone)]
pub enum Variant {
None,
Bool(bool),
Int(c_int),
String(String),
ByteArray(Vec<u8>),
}
impl From<bool> for Variant {
fn from(value: bool) -> Variant {
Variant::Bool(value)
}
}
impl From<String> for Variant {
fn from(value: String) -> Variant {
Variant::String(value)
}
}
/* values from qvariant.h and qmetatype.h */
#[repr(u32)]
#[derive(Clone, Copy)]
enum VariantType {
Invalid = 0,
Bool = 1,
Int = 2,
String = 10,
ByteArray = 12,
}
#[repr(C)]
pub struct QVariant<'a> {
type_: VariantType,
value: c_int,
data: *const uint8_t,
phantom: PhantomData<&'a u8>,
}
impl<'a> QVariant<'a> {
pub fn type_(&self) -> u32 {
self.type_ as u32
}
pub fn convert(&self) -> Variant {
match self.type_ {
VariantType::Bool => {
Variant::Bool(self.value != 0)
},
VariantType::Int => {
Variant::Int(self.value)
},
VariantType::String => {
let data = unsafe {
let d = self.data as *const uint16_t;
slice::from_raw_parts(d, self.value as usize)
};
Variant::String(String::from_utf16_lossy(data))
}
VariantType::ByteArray => {
let data = unsafe {
slice::from_raw_parts(self.data, self.value as usize)
};
Variant::ByteArray(Vec::from(data))
}
_ => Variant::None
}
}
}
impl<'a> From<&'a Variant> for QVariant<'a> {
fn from(variant: &'a Variant) -> QVariant {
match *variant {
Variant::None => {
QVariant {
data: null(),
value: 0,
type_: VariantType::Invalid,
phantom: PhantomData,
}
}
Variant::Bool(v) => {
QVariant {
data: null(),
value: v as c_int,
type_: VariantType::Bool,
phantom: PhantomData,
}
}
Variant::Int(v) => {
QVariant {
data: null(),
value: v,
type_: VariantType::Int,
phantom: PhantomData,
}
}
Variant::String(ref v) => {
QVariant {
data: v.as_ptr(),
value: v.len() as c_int,
type_: VariantType::String,
phantom: PhantomData,
}
}
Variant::ByteArray(ref v) => {
QVariant {
data: v.as_ptr(),
value: v.len() as c_int,
type_: VariantType::ByteArray,
phantom: PhantomData,
}
}
}
}
}
#[repr(C)]
pub struct QModelIndex {
row: c_int,
column: c_int,
internal_id: usize,
}
impl QModelIndex {
pub fn invalid() -> QModelIndex {
QModelIndex {
row: -1,
column: -1,
internal_id: 0,
}
}
pub fn create(row: c_int, column: c_int, id: usize) -> QModelIndex {
QModelIndex {
row: row,
column: column,
internal_id: id,
}
}
pub fn flat(row: c_int, column: c_int) -> QModelIndex {
QModelIndex {
row: row,
column: column,
internal_id: 1,
}
}
pub fn is_valid(&self) -> bool {
self.internal_id != 0 && self.row >= 0 && self.column >= 0
}
pub fn row(&self) -> c_int {
self.row
}
pub fn column(&self) -> c_int {
self.column
}
pub fn id(&self) -> usize {
self.internal_id
}
}
)");
}
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QCoreApplication::setApplicationName(argv[0]);
@ -931,6 +1156,7 @@ int main(int argc, char *argv[]) {
writeCpp(configuration);
writeRustInterface(configuration);
writeRustImplementation(configuration);
writeRustTypes(configuration);
return 0;
}

View File

@ -9,6 +9,7 @@ function(rust_test NAME DIRECTORY)
add_custom_command(
OUTPUT "${DIR}/src/interface.rs"
"${DIR}/src/implementation.rs"
"${DIR}/src/types.rs"
"${SRC}/${NAME}_rust.h"
# if the cpp file is marked GENERATED, CMake will not check it for moc
# "${SRC}/${NAME}_rust.cpp"
@ -20,10 +21,10 @@ function(rust_test NAME DIRECTORY)
add_custom_command(
OUTPUT "${DIR}/${RUST_TARGET_DIR}/librust.a"
COMMAND cargo build ${RUST_BUILD_FLAG}
DEPENDS "${DIRECTORY}/src/lib.rs"
"${DIRECTORY}/src/implementation.rs"
"${DIRECTORY}/src/interface.rs"
"${DIRECTORY}/src/types.rs"
DEPENDS "${DIR}/src/lib.rs"
"${DIR}/src/implementation.rs"
"${DIR}/src/interface.rs"
"${DIR}/src/types.rs"
WORKING_DIRECTORY "${DIR}"
)
add_custom_target("test_${DIRECTORY}"

View File

@ -1,3 +1,4 @@
/* generated by rust_qt_binding_generator */
use std::slice;
use libc::{c_int, c_uint, uint8_t, uint16_t};
use std::ptr::null;
@ -212,3 +213,5 @@ impl QModelIndex {
self.internal_id
}
}

View File

@ -1,3 +1,4 @@
/* generated by rust_qt_binding_generator */
use std::slice;
use libc::{c_int, c_uint, uint8_t, uint16_t};
use std::ptr::null;
@ -212,3 +213,5 @@ impl QModelIndex {
self.internal_id
}
}

View File

@ -3,7 +3,8 @@
"rust": {
"dir": "rust_object",
"interfaceModule": "interface",
"implementationModule": "implementation"
"implementationModule": "implementation",
"typesModule": "types"
},
"objects": [{
"name": "Person",

View File

@ -3,7 +3,8 @@
"rust": {
"dir": "rust_object_types",
"interfaceModule": "interface",
"implementationModule": "implementation"
"implementationModule": "implementation",
"typesModule": "types"
},
"objects": [{
"name": "Object",