cxx_qt_lib/core/
qbytearray.rs

1// SPDX-FileCopyrightText: 2022 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
2// SPDX-FileContributor: Andrew Hayzen <andrew.hayzen@kdab.com>
3//
4// SPDX-License-Identifier: MIT OR Apache-2.0
5use cxx::{type_id, ExternType};
6use std::mem::MaybeUninit;
7
8#[cxx::bridge]
9mod ffi {
10    unsafe extern "C++" {
11        include!("cxx-qt-lib/qbytearray.h");
12
13        type QByteArray = super::QByteArray;
14
15        /// Clears the contents of the byte array and makes it null.
16        fn clear(self: &mut Self);
17        /// Returns true if the byte array has size 0; otherwise returns false.
18        #[rust_name = "is_empty"]
19        fn isEmpty(self: &Self) -> bool;
20        /// Returns true if this byte array is lowercase, that is, if it's identical to its toLower() folding.
21        #[rust_name = "is_lower"]
22        fn isLower(self: &Self) -> bool;
23        /// Returns true if this byte array is null; otherwise returns false.
24        #[rust_name = "is_null"]
25        fn isNull(self: &Self) -> bool;
26        /// Returns true if this byte array is uppercase, that is, if it's identical to its toUpper() folding.
27        #[rust_name = "is_upper"]
28        fn isUpper(self: &Self) -> bool;
29        /// Releases any memory not required to store the array's data.
30        fn squeeze(self: &mut Self);
31    }
32
33    #[namespace = "rust::cxxqtlib1"]
34    unsafe extern "C++" {
35        include!("cxx-qt-lib/common.h");
36
37        #[doc(hidden)]
38        #[rust_name = "qbytearray_drop"]
39        fn drop(bytearray: &mut QByteArray);
40
41        #[doc(hidden)]
42        #[rust_name = "qbytearray_default"]
43        fn construct() -> QByteArray;
44        #[doc(hidden)]
45        #[rust_name = "qbytearray_clone"]
46        fn construct(bytearray: &QByteArray) -> QByteArray;
47
48        #[doc(hidden)]
49        #[rust_name = "qbytearray_eq"]
50        fn operatorEq(a: &QByteArray, b: &QByteArray) -> bool;
51
52        #[doc(hidden)]
53        #[rust_name = "qbytearray_from_slice_u8"]
54        fn qbytearrayFromSliceU8(slice: &[u8]) -> QByteArray;
55        #[doc(hidden)]
56        #[rust_name = "qbytearray_to_vec_u8"]
57        fn qbytearrayToVecU8(string: &QByteArray) -> Vec<u8>;
58
59        #[doc(hidden)]
60        #[rust_name = "qbytearray_from_raw_data"]
61        fn qbytearrayFromRawData(slice: &[u8]) -> QByteArray;
62        #[doc(hidden)]
63        #[rust_name = "qbytearray_as_mut_slice"]
64        fn qbytearrayAsMutSlice(bytearray: &mut QByteArray) -> &mut [u8];
65        #[doc(hidden)]
66        #[rust_name = "qbytearray_as_slice"]
67        fn qbytearrayAsSlice(bytearray: &QByteArray) -> &[u8];
68
69        #[doc(hidden)]
70        #[rust_name = "qbytearray_append"]
71        fn qbytearrayAppend(bytearray: &mut QByteArray, ch: u8);
72        #[doc(hidden)]
73        #[rust_name = "qbytearray_fill"]
74        fn qbytearrayFill(bytearray: &mut QByteArray, ch: u8, size: isize);
75        #[doc(hidden)]
76        #[rust_name = "qbytearray_insert"]
77        fn qbytearrayInsert(bytearray: &mut QByteArray, pos: isize, ch: u8);
78        #[doc(hidden)]
79        #[rust_name = "qbytearray_len"]
80        fn qbytearrayLen(bytearray: &QByteArray) -> isize;
81        #[doc(hidden)]
82        #[rust_name = "qbytearray_prepend"]
83        fn qbytearrayPrepend(bytearray: &mut QByteArray, ch: u8);
84        #[doc(hidden)]
85        #[rust_name = "qbytearray_remove"]
86        fn qbytearrayRemove(bytearray: &mut QByteArray, pos: isize, len: isize);
87        #[doc(hidden)]
88        #[rust_name = "qbytearray_reserve"]
89        fn qbytearrayReserve(bytearray: &mut QByteArray, size: isize);
90        #[doc(hidden)]
91        #[rust_name = "qbytearray_resize"]
92        fn qbytearrayResize(bytearray: &mut QByteArray, size: isize);
93        #[doc(hidden)]
94        #[rust_name = "qbytearray_simplified"]
95        fn qbytearraySimplified(bytearray: &QByteArray) -> QByteArray;
96        #[doc(hidden)]
97        #[rust_name = "qbytearray_to_lower"]
98        fn qbytearrayToLower(bytearray: &QByteArray) -> QByteArray;
99        #[doc(hidden)]
100        #[rust_name = "qbytearray_to_upper"]
101        fn qbytearrayToUpper(bytearray: &QByteArray) -> QByteArray;
102        #[doc(hidden)]
103        #[rust_name = "qbytearray_trimmed"]
104        fn qbytearrayTrimmed(bytearray: &QByteArray) -> QByteArray;
105    }
106}
107
108/// The QByteArray class provides an array of bytes.
109#[repr(C)]
110pub struct QByteArray {
111    /// The layout has changed between Qt 5 and Qt 6
112    ///
113    /// Qt5 QByteArray has one pointer as a member
114    /// Qt6 QByteArray has one member, which contains two pointers and a size_t
115    #[cfg(cxxqt_qt_version_major = "5")]
116    _space: MaybeUninit<usize>,
117    #[cfg(cxxqt_qt_version_major = "6")]
118    _space: MaybeUninit<[usize; 3]>,
119}
120
121impl AsRef<[u8]> for QByteArray {
122    /// Construct a slice of u8 from a QByteArray
123    fn as_ref(&self) -> &[u8] {
124        self.as_slice()
125    }
126}
127
128impl Clone for QByteArray {
129    /// Constructs a copy of other.
130    ///
131    /// This operation takes constant time, because QByteArray is implicitly shared similar to a [std::borrow::Cow].
132    /// This makes returning a QByteArray from a function very fast.
133    /// If a shared instance is modified, it will be copied (copy-on-write), and that takes linear time.
134    fn clone(&self) -> Self {
135        ffi::qbytearray_clone(self)
136    }
137}
138
139impl Default for QByteArray {
140    /// Constructs an empty byte array.
141    fn default() -> Self {
142        ffi::qbytearray_default()
143    }
144}
145
146impl std::cmp::PartialEq for QByteArray {
147    fn eq(&self, other: &Self) -> bool {
148        ffi::qbytearray_eq(self, other)
149    }
150}
151
152impl std::cmp::Eq for QByteArray {}
153
154impl std::fmt::Display for QByteArray {
155    /// Convert the QByteArray to a Rust string
156    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
157        if let Ok(string) = String::from_utf8(self.into()) {
158            write!(f, "{string}")
159        } else {
160            write!(f, "{:?}", self.as_slice())
161        }
162    }
163}
164
165impl std::fmt::Debug for QByteArray {
166    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
167        write!(f, "{self}")
168    }
169}
170
171impl Drop for QByteArray {
172    /// Destroys the byte array.
173    fn drop(&mut self) {
174        ffi::qbytearray_drop(self)
175    }
176}
177
178impl From<&str> for QByteArray {
179    /// Constructs a QByteArray from a Rust string slice. This makes a deep copy of the data.
180    fn from(str: &str) -> Self {
181        ffi::qbytearray_from_slice_u8(str.as_bytes())
182    }
183}
184
185impl From<&String> for QByteArray {
186    /// Constructs a QByteArray from a Rust string. This makes a deep copy of the data.
187    fn from(str: &String) -> Self {
188        ffi::qbytearray_from_slice_u8(str.as_bytes())
189    }
190}
191
192impl From<&[u8]> for QByteArray {
193    /// Constructs a QByteArray from a `&[u8]`. This makes a deep copy of the data.
194    fn from(bytes: &[u8]) -> Self {
195        ffi::qbytearray_from_slice_u8(bytes)
196    }
197}
198
199impl From<&QByteArray> for Vec<u8> {
200    /// Convert the QByteArray to a `Vec<u8>`. This makes a deep copy of the data.
201    fn from(bytearray: &QByteArray) -> Self {
202        ffi::qbytearray_to_vec_u8(bytearray)
203    }
204}
205
206#[cfg(feature = "bytes")]
207impl From<&bytes::Bytes> for QByteArray {
208    /// Convert `bytes::Bytes` to a QByteArray. This makes a deep copy of the data.
209    fn from(value: &bytes::Bytes) -> Self {
210        Self::from(value.as_ref())
211    }
212}
213
214#[cfg(feature = "bytes")]
215impl From<&QByteArray> for bytes::Bytes {
216    /// Convert QByteArray to a `bytes::Bytes`. This makes a deep copy of the data.
217    fn from(value: &QByteArray) -> Self {
218        Self::copy_from_slice(value.as_ref())
219    }
220}
221
222impl QByteArray {
223    /// Inserts value at the end of the list.
224    pub fn append(&mut self, ch: u8) {
225        ffi::qbytearray_append(self, ch);
226    }
227
228    /// Construct a mutable slice of u8 from a QByteArray
229    pub fn as_mut_slice(&mut self) -> &mut [u8] {
230        ffi::qbytearray_as_mut_slice(self)
231    }
232
233    /// Construct a slice of u8 from a QByteArray
234    pub fn as_slice(&self) -> &[u8] {
235        ffi::qbytearray_as_slice(self)
236    }
237
238    /// Sets every byte in the byte array to ch.
239    /// If size is different from -1 (the default),
240    /// the byte array is resized to size size beforehand.
241    pub fn fill(&mut self, ch: u8, size: isize) {
242        ffi::qbytearray_fill(self, ch, size)
243    }
244
245    /// Construct a QByteArray from a `bytes::Bytes` without a deep copy
246    ///
247    /// # Safety
248    ///
249    /// The caller must ensure that the original `bytes::Bytes` outlives the QByteArray
250    /// and that the QByteArray is not modified
251    #[cfg(feature = "bytes")]
252    pub unsafe fn from_raw_bytes(bytes: &bytes::Bytes) -> Self {
253        Self::from_raw_data(bytes.as_ref())
254    }
255
256    /// Construct a QByteArray from a `&[u8]` without a deep copy
257    ///
258    /// # Safety
259    ///
260    /// The caller must ensure that the original slice outlives the QByteArray
261    /// and that the QByteArray is not modified
262    pub unsafe fn from_raw_data(bytes: &[u8]) -> Self {
263        ffi::qbytearray_from_raw_data(bytes)
264    }
265
266    /// Inserts item value into the list at the given position.
267    pub fn insert(&mut self, pos: isize, ch: u8) {
268        ffi::qbytearray_insert(self, pos, ch);
269    }
270
271    /// Returns the number of items in the QByteArray.
272    pub fn len(&self) -> isize {
273        ffi::qbytearray_len(self)
274    }
275
276    /// Inserts value at the start of the list.
277    pub fn prepend(&mut self, ch: u8) {
278        ffi::qbytearray_prepend(self, ch);
279    }
280
281    /// Removes len bytes from the array, starting at index position pos.
282    pub fn remove(&mut self, pos: isize, len: isize) {
283        ffi::qbytearray_remove(self, pos, len);
284    }
285
286    /// Reserve the specified capacity to prevent repeated allocations
287    /// when the maximum size is known.
288    pub fn reserve(&mut self, size: isize) {
289        ffi::qbytearray_reserve(self, size);
290    }
291
292    /// Sets the size of the byte array to size bytes.
293    ///
294    /// If size is greater than the current size, the byte array is extended to make it size bytes with the extra bytes added to the end. The new bytes are uninitialized.
295    ///
296    /// If size is less than the current size, bytes beyond position size are excluded from the byte array.
297    pub fn resize(&mut self, size: isize) {
298        ffi::qbytearray_resize(self, size);
299    }
300
301    /// Returns a copy of this byte array that has spacing characters removed from the start and end,
302    /// and in which each sequence of internal spacing characters is replaced with a single space.
303    pub fn simplified(&self) -> Self {
304        ffi::qbytearray_simplified(self)
305    }
306
307    /// Returns a copy of the byte array in which each ASCII uppercase letter converted to lowercase.
308    pub fn to_lower(&self) -> Self {
309        ffi::qbytearray_to_lower(self)
310    }
311
312    /// Returns a copy of the byte array in which each ASCII lowercase letter converted to uppercase.
313    pub fn to_upper(&self) -> Self {
314        ffi::qbytearray_to_upper(self)
315    }
316
317    /// Returns a copy of this byte array with spacing characters removed from the start and end.
318    pub fn trimmed(&self) -> Self {
319        ffi::qbytearray_trimmed(self)
320    }
321}
322
323// Safety:
324//
325// Static checks on the C++ side to ensure the size is the same.
326unsafe impl ExternType for QByteArray {
327    type Id = type_id!("QByteArray");
328    type Kind = cxx::kind::Trivial;
329}
330
331#[cfg(test)]
332mod tests {
333    #[cfg(feature = "bytes")]
334    use super::*;
335
336    #[cfg(feature = "bytes")]
337    #[test]
338    fn test_bytes() {
339        let bytes = bytes::Bytes::from("KDAB");
340        let qbytearray = QByteArray::from(&bytes);
341        assert_eq!(bytes.as_ref(), qbytearray.as_ref());
342
343        let bytes_bytes = bytes::Bytes::from(&qbytearray);
344        assert_eq!(bytes, bytes_bytes)
345    }
346}