1use cxx::{type_id, ExternType};
7use std::cmp::Ordering;
8use std::fmt;
9use std::mem::MaybeUninit;
10
11#[cxx::bridge]
12mod ffi {
13 #[namespace = "Qt"]
14 unsafe extern "C++" {
15 include!("cxx-qt-lib/qt.h");
16 type CaseSensitivity = crate::CaseSensitivity;
17 type SplitBehaviorFlags = crate::SplitBehaviorFlags;
18 }
19
20 unsafe extern "C++" {
21 include!("cxx-qt-lib/qbytearray.h");
22 type QByteArray = crate::QByteArray;
23 include!("cxx-qt-lib/qstring.h");
24 type QString = super::QString;
25 include!("cxx-qt-lib/qstringlist.h");
26 type QStringList = crate::QStringList;
27
28 fn append<'a>(self: &'a mut QString, str: &QString) -> &'a mut QString;
30
31 fn clear(self: &mut QString);
33
34 #[doc(hidden)]
36 #[rust_name = "compare_i32"]
37 fn compare(self: &QString, other: &QString, cs: CaseSensitivity) -> i32;
38
39 fn contains(self: &QString, str: &QString, cs: CaseSensitivity) -> bool;
41
42 #[rust_name = "ends_with"]
44 fn endsWith(self: &QString, s: &QString, cs: CaseSensitivity) -> bool;
45
46 #[rust_name = "is_empty"]
48 fn isEmpty(self: &QString) -> bool;
49
50 #[rust_name = "is_lower"]
52 fn isLower(self: &QString) -> bool;
53
54 #[rust_name = "is_null"]
56 fn isNull(self: &QString) -> bool;
57
58 #[rust_name = "is_right_to_left"]
60 fn isRightToLeft(self: &QString) -> bool;
61
62 #[rust_name = "is_upper"]
64 fn isUpper(self: &QString) -> bool;
65
66 #[rust_name = "is_valid_utf16"]
68 fn isValidUtf16(self: &QString) -> bool;
69
70 fn prepend<'a>(self: &'a mut QString, str: &QString) -> &'a mut QString;
72
73 fn remove<'a>(self: &'a mut QString, str: &QString, cs: CaseSensitivity)
75 -> &'a mut QString;
76
77 #[cfg(any(cxxqt_qt_version_at_least_7, cxxqt_qt_version_at_least_6_5))]
80 #[rust_name = "remove_first"]
81 fn removeFirst(self: &mut QString) -> &mut QString;
82
83 #[cfg(any(cxxqt_qt_version_at_least_7, cxxqt_qt_version_at_least_6_5))]
86 #[rust_name = "remove_last"]
87 fn removeLast(self: &mut QString) -> &mut QString;
88
89 fn replace<'a>(
91 self: &'a mut QString,
92 before: &QString,
93 after: &QString,
94 cs: CaseSensitivity,
95 ) -> &'a mut QString;
96
97 #[rust_name = "starts_with"]
99 fn startsWith(self: &QString, s: &QString, cs: CaseSensitivity) -> bool;
100
101 #[rust_name = "to_html_escaped"]
103 fn toHtmlEscaped(self: &QString) -> QString;
104 }
105
106 #[namespace = "rust::cxxqtlib1"]
107 unsafe extern "C++" {
108 include!("cxx-qt-lib/common.h");
109
110 #[doc(hidden)]
111 #[rust_name = "qstring_drop"]
112 fn drop(string: &mut QString);
113
114 #[doc(hidden)]
115 #[rust_name = "qstring_init_default"]
116 fn construct() -> QString;
117 #[doc(hidden)]
118 #[rust_name = "qstring_init_from_rust_string"]
119 fn qstringInitFromRustString(string: &str) -> QString;
120 #[doc(hidden)]
121 #[rust_name = "qstring_init_from_qstring"]
122 fn construct(string: &QString) -> QString;
123
124 #[doc(hidden)]
125 #[rust_name = "qstring_eq"]
126 fn operatorEq(a: &QString, b: &QString) -> bool;
127 #[doc(hidden)]
128 #[rust_name = "qstring_cmp"]
129 fn operatorCmp(a: &QString, b: &QString) -> i8;
130
131 #[doc(hidden)]
132 #[rust_name = "qstring_to_rust_string"]
133 fn qstringToRustString(string: &QString) -> String;
134
135 #[doc(hidden)]
136 #[rust_name = "qstring_arg"]
137 fn qstringArg(string: &QString, a: &QString) -> QString;
138 #[doc(hidden)]
139 #[rust_name = "qstring_index_of"]
140 fn qstringIndexOf(
141 string: &QString,
142 str: &QString,
143 from: isize,
144 cs: CaseSensitivity,
145 ) -> isize;
146 #[doc(hidden)]
147 #[rust_name = "qstring_insert"]
148 fn qstringInsert<'a>(string: &'a mut QString, pos: isize, str: &QString)
149 -> &'a mut QString;
150 #[doc(hidden)]
151 #[rust_name = "qstring_left"]
152 fn qstringLeft(string: &QString, n: isize) -> QString;
153 #[doc(hidden)]
154 #[rust_name = "qstring_len"]
155 fn qstringLen(string: &QString) -> isize;
156 #[doc(hidden)]
157 #[rust_name = "qstring_mid"]
158 fn qstringMid(string: &QString, position: isize, n: isize) -> QString;
159 #[doc(hidden)]
160 #[rust_name = "qstring_right"]
161 fn qstringRight(string: &QString, n: isize) -> QString;
162 #[doc(hidden)]
163 #[rust_name = "qstring_simplified"]
164 fn qstringSimplified(string: &QString) -> QString;
165 #[doc(hidden)]
166 #[rust_name = "qstring_split"]
167 fn qstringSplit(
168 string: &QString,
169 sep: &QString,
170 behavior: SplitBehaviorFlags,
171 cs: CaseSensitivity,
172 ) -> QStringList;
173 #[doc(hidden)]
174 #[rust_name = "qstring_to_latin1"]
175 fn qstringToLatin1(string: &QString) -> QByteArray;
176 #[doc(hidden)]
177 #[rust_name = "qstring_to_local8bit"]
178 fn qstringToLocal8Bit(string: &QString) -> QByteArray;
179 #[doc(hidden)]
180 #[rust_name = "qstring_to_lower"]
181 fn qstringToLower(string: &QString) -> QString;
182 #[doc(hidden)]
183 #[rust_name = "qstring_to_upper"]
184 fn qstringToUpper(string: &QString) -> QString;
185 #[doc(hidden)]
186 #[rust_name = "qstring_to_utf8"]
187 fn qstringToUtf8(string: &QString) -> QByteArray;
188 #[doc(hidden)]
189 #[rust_name = "qstring_trimmed"]
190 fn qstringTrimmed(string: &QString) -> QString;
191 }
192}
193
194#[cfg(feature = "serde")]
195use serde::{Deserialize, Serialize};
196
197#[repr(C)]
201#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
202#[cfg_attr(feature = "serde", serde(from = "String", into = "String"))]
203pub struct QString {
204 #[cfg(cxxqt_qt_version_major = "5")]
209 _space: MaybeUninit<usize>,
210 #[cfg(cxxqt_qt_version_major = "6")]
211 _space: MaybeUninit<[usize; 3]>,
212}
213
214impl Clone for QString {
215 fn clone(&self) -> Self {
221 ffi::qstring_init_from_qstring(self)
222 }
223}
224
225impl Default for QString {
226 fn default() -> Self {
228 ffi::qstring_init_default()
229 }
230}
231
232impl PartialEq for QString {
233 fn eq(&self, other: &Self) -> bool {
234 ffi::qstring_eq(self, other)
235 }
236}
237
238impl Eq for QString {}
239
240impl PartialOrd for QString {
241 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
242 Some(self.cmp(other))
243 }
244}
245
246impl Ord for QString {
247 fn cmp(&self, other: &Self) -> Ordering {
248 ffi::qstring_cmp(self, other).cmp(&0)
249 }
250}
251
252impl fmt::Display for QString {
253 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
257 write!(f, "{}", <&QString as Into<String>>::into(self))
258 }
259}
260
261impl fmt::Debug for QString {
262 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
263 write!(f, "{self}")
264 }
265}
266
267impl std::ops::Add for QString {
268 type Output = Self;
269 fn add(self, other: Self) -> Self {
270 let mut res = ffi::qstring_init_from_qstring(&self);
271 res.append(&other);
272 res
273 }
274}
275
276impl Drop for QString {
277 fn drop(&mut self) {
279 ffi::qstring_drop(self)
280 }
281}
282
283impl From<&str> for QString {
284 fn from(str: &str) -> Self {
288 ffi::qstring_init_from_rust_string(str)
289 }
290}
291
292impl From<&String> for QString {
293 fn from(str: &String) -> Self {
297 ffi::qstring_init_from_rust_string(str)
298 }
299}
300
301impl From<String> for QString {
302 fn from(str: String) -> Self {
306 ffi::qstring_init_from_rust_string(&str)
307 }
308}
309
310impl From<&QString> for String {
311 fn from(qstring: &QString) -> Self {
315 ffi::qstring_to_rust_string(qstring)
316 }
317}
318
319impl From<QString> for String {
320 fn from(qstring: QString) -> Self {
324 ffi::qstring_to_rust_string(&qstring)
325 }
326}
327
328impl QString {
329 pub fn arg(&self, a: &QString) -> Self {
331 ffi::qstring_arg(self, a)
332 }
333
334 pub fn compare(&self, other: &QString, cs: ffi::CaseSensitivity) -> Ordering {
337 self.compare_i32(other, cs).cmp(&0)
338 }
339
340 pub fn index_of(&self, str: &QString, from: isize, cs: ffi::CaseSensitivity) -> isize {
343 ffi::qstring_index_of(self, str, from, cs)
344 }
345
346 pub fn insert<'a>(&'a mut self, pos: isize, str: &Self) -> &'a mut Self {
348 ffi::qstring_insert(self, pos, str)
349 }
350
351 pub fn left(&self, n: isize) -> Self {
353 ffi::qstring_left(self, n)
354 }
355
356 pub fn len(self: &QString) -> isize {
358 ffi::qstring_len(self)
359 }
360
361 pub fn mid(&self, position: isize, n: isize) -> Self {
363 ffi::qstring_mid(self, position, n)
364 }
365
366 pub fn right(&self, n: isize) -> Self {
368 ffi::qstring_right(self, n)
369 }
370
371 pub fn simplified(&self) -> Self {
374 ffi::qstring_simplified(self)
375 }
376
377 pub fn split(
380 &self,
381 sep: &QString,
382 behavior: ffi::SplitBehaviorFlags,
383 cs: ffi::CaseSensitivity,
384 ) -> ffi::QStringList {
385 ffi::qstring_split(self, sep, behavior, cs)
386 }
387
388 pub fn to_latin1(&self) -> ffi::QByteArray {
390 ffi::qstring_to_latin1(self)
391 }
392
393 pub fn to_local8bit(&self) -> ffi::QByteArray {
396 ffi::qstring_to_local8bit(self)
397 }
398
399 pub fn to_lower(&self) -> Self {
401 ffi::qstring_to_lower(self)
402 }
403
404 pub fn to_upper(&self) -> Self {
406 ffi::qstring_to_upper(self)
407 }
408
409 pub fn to_utf8(&self) -> ffi::QByteArray {
411 ffi::qstring_to_utf8(self)
412 }
413
414 pub fn trimmed(&self) -> Self {
416 ffi::qstring_trimmed(self)
417 }
418}
419
420unsafe impl ExternType for QString {
424 type Id = type_id!("QString");
425 type Kind = cxx::kind::Trivial;
426}
427
428#[cfg(test)]
429mod test {
430 use super::*;
431
432 #[test]
433 fn test_ordering() {
434 let qstring_a = QString::from("a");
435 let qstring_b = QString::from("b");
436
437 assert!(qstring_a < qstring_b);
438 assert_eq!(qstring_a.cmp(&qstring_b), Ordering::Less);
439 assert_eq!(qstring_b.cmp(&qstring_a), Ordering::Greater);
440 assert_eq!(qstring_a.cmp(&qstring_a), Ordering::Equal);
441
442 assert_eq!(
443 qstring_a.compare(&qstring_b, crate::CaseSensitivity::CaseInsensitive),
444 Ordering::Less
445 );
446 assert_eq!(
447 qstring_b.compare(&qstring_a, crate::CaseSensitivity::CaseInsensitive),
448 Ordering::Greater
449 );
450 assert_eq!(
451 qstring_a.compare(&qstring_a, crate::CaseSensitivity::CaseInsensitive),
452 Ordering::Equal
453 );
454 }
455}