Skip to content

Commit

Permalink
cxx-qt-lib: use u8 vec and slice to convert to QByteArray
Browse files Browse the repository at this point in the history
  • Loading branch information
ahayzen-kdab committed Dec 20, 2022
1 parent 8e1f35c commit 854f983
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 23 deletions.
13 changes: 10 additions & 3 deletions crates/cxx-qt-lib-headers/include/qbytearray.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
#pragma once

#include <cstdint>

#include <QByteArray>

#include "rust/cxx.h"
Expand All @@ -19,9 +21,14 @@ namespace rust {
namespace cxxqtlib1 {

QByteArray
qbytearrayFromRustString(rust::Str string);
rust::String
qbytearrayToRustString(const QByteArray& string);
qbytearrayFromSliceU8(::rust::Slice<const ::std::uint8_t> slice);
::rust::Vec<::std::uint8_t>
qbytearrayToVecU8(const QByteArray& byteArray);

QByteArray
qbytearrayFromRawData(::rust::Slice<const ::std::uint8_t> slice);
::rust::Slice<const ::std::uint8_t>
qbytearrayAsSlice(const QByteArray& byteArray);

}
}
40 changes: 34 additions & 6 deletions crates/cxx-qt-lib/src/types/qbytearray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,44 @@ namespace rust {
namespace cxxqtlib1 {

QByteArray
qbytearrayFromRustString(rust::Str string)
qbytearrayFromSliceU8(::rust::Slice<const ::std::uint8_t> slice)
{
// Note that rust::Str here is borrowed
return QByteArray(string.data(), string.size());
// Note that rust::Slice here is borrowed
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
return QByteArray(reinterpret_cast<const char*>(slice.data()),
static_cast<qsizetype>(slice.size()));
#else
return QByteArray(reinterpret_cast<const char*>(slice.data()),
static_cast<int>(slice.size()));
#endif
}

::rust::Vec<::std::uint8_t>
qbytearrayToVecU8(const QByteArray& byteArray)
{
::rust::Vec<::std::uint8_t> vec;
std::copy(byteArray.cbegin(), byteArray.cend(), std::back_inserter(vec));
return vec;
}

QByteArray
qbytearrayFromRawData(::rust::Slice<const ::std::uint8_t> slice)
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
return QByteArray::fromRawData(reinterpret_cast<const char*>(slice.data()),
static_cast<qsizetype>(slice.size()));
#else
return QByteArray::fromRawData(reinterpret_cast<const char*>(slice.data()),
static_cast<int>(slice.size()));
#endif
}

rust::String
qbytearrayToRustString(const QByteArray& byteArray)
::rust::Slice<const ::std::uint8_t>
qbytearrayAsSlice(const QByteArray& byteArray)
{
return rust::String(byteArray.constData(), byteArray.size());
return ::rust::Slice<const ::std::uint8_t>(
reinterpret_cast<const std::uint8_t*>(byteArray.data()),
static_cast<::std::size_t>(byteArray.size()));
}

}
Expand Down
63 changes: 49 additions & 14 deletions crates/cxx-qt-lib/src/types/qbytearray.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,28 @@ mod ffi {

#[doc(hidden)]
#[rust_name = "qbytearray_drop"]
fn drop(string: &mut QByteArray);
fn drop(bytearray: &mut QByteArray);

#[doc(hidden)]
#[rust_name = "qbytearray_default"]
fn construct() -> QByteArray;
#[doc(hidden)]
#[rust_name = "qbytearray_from_rust_string"]
fn qbytearrayFromRustString(string: &str) -> QByteArray;
#[doc(hidden)]
#[rust_name = "qbytearray_clone"]
fn construct(string: &QByteArray) -> QByteArray;
fn construct(bytearray: &QByteArray) -> QByteArray;

#[doc(hidden)]
#[rust_name = "qbytearray_from_slice_u8"]
fn qbytearrayFromSliceU8(slice: &[u8]) -> QByteArray;
#[doc(hidden)]
#[rust_name = "qbytearray_to_vec_u8"]
fn qbytearrayToVecU8(string: &QByteArray) -> Vec<u8>;

#[doc(hidden)]
#[rust_name = "qbytearray_to_rust_string"]
fn qbytearrayToRustString(string: &QByteArray) -> String;
#[rust_name = "qbytearray_from_raw_data"]
fn qbytearrayFromRawData(slice: &[u8]) -> QByteArray;
#[doc(hidden)]
#[rust_name = "qbytearray_as_slice"]
fn qbytearrayAsSlice(bytearray: &QByteArray) -> &[u8];
}
}

Expand Down Expand Up @@ -70,7 +77,11 @@ impl Default for QByteArray {
impl std::fmt::Display for QByteArray {
/// Convert the QByteArray to a Rust string
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", <&QByteArray as Into<String>>::into(self))
if let Ok(string) = String::from_utf8(self.into()) {
write!(f, "{}", string)
} else {
write!(f, "{:?}", ffi::qbytearray_to_vec_u8(self))
}
}
}

Expand All @@ -84,21 +95,45 @@ impl Drop for QByteArray {
impl From<&str> for QByteArray {
/// Constructs a QByteArray from a Rust string
fn from(str: &str) -> Self {
ffi::qbytearray_from_rust_string(str)
ffi::qbytearray_from_slice_u8(str.as_bytes())
}
}

impl From<&String> for QByteArray {
/// Constructs a QByteArray from a Rust string
fn from(str: &String) -> Self {
ffi::qbytearray_from_rust_string(str)
ffi::qbytearray_from_slice_u8(str.as_bytes())
}
}

impl From<&QByteArray> for String {
/// Convert the QByteArray to a Rust string
fn from(qbytearray: &QByteArray) -> Self {
ffi::qbytearray_to_rust_string(qbytearray)
impl From<&[u8]> for QByteArray {
/// Constructs a QByteArray from a vector of u8
fn from(bytes: &[u8]) -> Self {
ffi::qbytearray_from_slice_u8(bytes)
}
}

impl From<&QByteArray> for Vec<u8> {
/// Convert the QByteArray to a vector of u8
fn from(bytearray: &QByteArray) -> Self {
ffi::qbytearray_to_vec_u8(bytearray)
}
}

impl QByteArray {
/// Construct a slice of u8 from a QByteArray
pub fn as_slice(&self) -> &[u8] {
ffi::qbytearray_as_slice(self)
}

/// Construct a QByteArray from a vector of u8
///
/// # Safety
///
/// The bytes are not copied, so you must ensure that the
/// original slice outlives the QByteArray
pub unsafe fn from_raw_data(bytes: &[u8]) -> QByteArray {
ffi::qbytearray_from_raw_data(bytes)
}
}

Expand Down
2 changes: 2 additions & 0 deletions tests/qt_types_standalone/cpp/qbytearray.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,6 @@ private Q_SLOTS:
modify_qbytearray(s);
QCOMPARE(s, QByteArrayLiteral("Updated string value"));
}

void can_use_as_slice_cpp() { QVERIFY(can_use_as_slice()); }
};
8 changes: 8 additions & 0 deletions tests/qt_types_standalone/rust/src/qbytearray.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mod qbytearray_cxx {
fn modify_qbytearray(s: Pin<&mut QByteArray>);
fn can_handle_qbytearray_change() -> bool;
fn clone_qbytearray(s: &QByteArray) -> QByteArray;
fn can_use_as_slice() -> bool;
}
}

Expand Down Expand Up @@ -57,3 +58,10 @@ fn can_handle_qbytearray_change() -> bool {
fn clone_qbytearray(s: &QByteArray) -> QByteArray {
s.clone()
}

fn can_use_as_slice() -> bool {
let string = "String slice";
let slice = unsafe { QByteArray::from_raw_data(string.as_bytes()) };

slice.as_slice() == string.as_bytes()
}

0 comments on commit 854f983

Please sign in to comment.