1cfg_if::cfg_if! {
13 if #[cfg(feature = "v1_26")] {
14 mod bindings;
15 pub use self::bindings::IdStr;
16 } else {
17 mod compat;
18 pub use self::compat::IdStr;
19 }
20}
21
22#[cfg(feature = "serde")]
23mod serde;
24
25#[macro_export]
45macro_rules! idstr {
46 ($s:literal) => {
47 IdStr::from_static($crate::glib::gstr!($s))
48 };
49}
50
51#[cfg(test)]
52mod tests {
53 use glib::{gstr, GStr, GString};
54 use std::{ffi::CStr, sync::LazyLock};
55
56 use super::IdStr;
57
58 const STR: &str = "STR";
59 static IDSTR: LazyLock<IdStr> = LazyLock::new(|| idstr!("IDSTR"));
60 static GSTR: &GStr = gstr!("GSTR");
61 static GSTRING: LazyLock<GString> = LazyLock::new(|| GString::from("GSTRING"));
62
63 const LONG_STR: &str = "An STR longer than 15 bytes";
64 static LONG_IDSTR: LazyLock<IdStr> = LazyLock::new(|| idstr!("An IdStr longer than 15 bytes"));
65 static LONG_GSTR: &GStr = gstr!("A GSTR longer than 15 bytes");
66 static LONG_GSTRING: LazyLock<GString> =
67 LazyLock::new(|| GString::from("A GSTRING longer than 15 bytes"));
68
69 #[test]
70 fn new_set_static() {
71 assert!(!IDSTR.is_empty());
72 assert_eq!(IDSTR.len(), "IDSTR".len());
73 assert_eq!(IDSTR.as_str().len(), "IDSTR".len());
74 assert_eq!(*IDSTR, "IDSTR");
75 assert_eq!(IDSTR.to_string(), "IDSTR");
77 assert_eq!(IDSTR.as_str(), "IDSTR");
78 assert_eq!(IDSTR.as_gstr().len(), "IDSTR".len());
79 assert_eq!(IDSTR.as_gstr(), "IDSTR");
80
81 let id_str: IdStr = idstr!("id_str");
82 assert!(!id_str.is_empty());
83 assert_eq!(id_str.len(), "id_str".len());
84 assert_eq!(id_str.as_str().len(), "id_str".len());
85 assert_eq!(id_str, "id_str");
86
87 let mut s = IdStr::new();
88 assert!(s.is_empty());
89 assert_eq!(s.len(), 0);
90 assert_eq!(s.as_str(), "");
91 assert_eq!(s.as_gstr(), "");
92
93 s.set_static(gstr!("str"));
94 assert!(!s.is_empty());
95 assert_eq!(s.len(), "str".len());
96 assert_eq!(s.as_str().len(), "str".len());
97 assert_eq!(s, "str");
98 assert_eq!(s.to_string(), "str");
100 assert_eq!(s.as_str(), "str");
101 assert_eq!(s.as_gstr().len(), "str".len());
102 assert_eq!(s.as_gstr(), "str");
103
104 s.set_static(GSTR);
105 assert_eq!(s.as_str(), "GSTR");
106
107 s.set_static(&*GSTRING);
108 assert_eq!(s.as_str(), "GSTRING");
109
110 assert!(!LONG_IDSTR.is_empty());
111 assert_eq!(LONG_IDSTR.len(), "An IdStr longer than 15 bytes".len());
112 assert_eq!(*LONG_IDSTR, "An IdStr longer than 15 bytes");
113 assert_eq!(LONG_IDSTR.to_string(), "An IdStr longer than 15 bytes");
115 assert_eq!(
116 LONG_IDSTR.as_str().len(),
117 "An IdStr longer than 15 bytes".len()
118 );
119 assert_eq!(LONG_IDSTR.as_str(), "An IdStr longer than 15 bytes");
120 assert_eq!(
121 LONG_IDSTR.as_gstr().len(),
122 "An IdStr longer than 15 bytes".len()
123 );
124 assert_eq!(LONG_IDSTR.as_gstr(), "An IdStr longer than 15 bytes");
125
126 let ls = idstr!("An IdStr longer than 15 bytes");
127 assert!(!ls.is_empty());
128 assert_eq!(ls.len(), "An IdStr longer than 15 bytes".len());
129 assert_eq!(ls, "An IdStr longer than 15 bytes");
130
131 let mut ls = IdStr::new();
132
133 ls.set_static(gstr!("An str longer than 15 bytes"));
134 assert!(!ls.is_empty());
135 assert_eq!(ls.len(), "An str longer than 15 bytes".len());
136 assert_eq!(ls, "An str longer than 15 bytes");
137
138 ls.set_static(LONG_GSTR);
139 assert_eq!(ls.as_str(), "A GSTR longer than 15 bytes");
140
141 ls.set_static(&*LONG_GSTRING);
142 assert_eq!(ls.as_str(), "A GSTRING longer than 15 bytes");
143 }
144
145 #[test]
146 fn from_static() {
147 let s = IdStr::from_static(gstr!("str"));
148 assert!(!s.is_empty());
149 assert_eq!(s.len(), "str".len());
150 assert_eq!(s.as_str().len(), "str".len());
151 assert_eq!(s, "str");
152 assert_eq!(s.to_string(), "str");
154 assert_eq!(s.as_str(), "str");
155 assert_eq!(s.as_gstr().len(), "str".len());
156 assert_eq!(s.as_gstr(), "str");
157
158 let s = idstr!("str");
159 assert!(!s.is_empty());
160 assert_eq!(s.len(), "str".len());
161 assert_eq!(s.as_str().len(), "str".len());
162 assert_eq!(s, "str");
163
164 let s = IdStr::from_static(GSTR);
165 assert_eq!(s.as_str(), "GSTR");
166
167 let s = IdStr::from_static(&*GSTRING);
168 assert_eq!(s.as_str(), "GSTRING");
169
170 let ls = IdStr::from_static(gstr!("An str longer than 15 bytes"));
171 assert!(!ls.is_empty());
172 assert_eq!(ls.len(), "An str longer than 15 bytes".len());
173 assert_eq!(ls, "An str longer than 15 bytes");
174 assert_eq!(ls.to_string(), "An str longer than 15 bytes");
176 assert_eq!(ls.as_str().len(), "An str longer than 15 bytes".len());
177 assert_eq!(ls.as_str(), "An str longer than 15 bytes");
178 assert_eq!(ls.as_gstr().len(), "An str longer than 15 bytes".len());
179 assert_eq!(ls.as_gstr(), "An str longer than 15 bytes");
180
181 let ls = idstr!("An str longer than 15 bytes");
182 assert!(!ls.is_empty());
183 assert_eq!(ls.len(), "An str longer than 15 bytes".len());
184 assert_eq!(ls, "An str longer than 15 bytes");
185
186 let ls = IdStr::from_static(LONG_GSTR);
187 assert_eq!(ls.as_str(), "A GSTR longer than 15 bytes");
188
189 let ls = IdStr::from_static(&*LONG_GSTRING);
190 assert_eq!(ls.as_str(), "A GSTRING longer than 15 bytes");
191 }
192
193 #[test]
194 fn new_set() {
195 let d = IdStr::default();
196 assert!(d.is_empty());
197 assert_eq!(d.len(), 0);
198 assert_eq!(d.as_str(), "");
199 assert_eq!(d.as_gstr(), "");
200
201 let mut s = IdStr::new();
202 assert!(s.is_empty());
203 assert_eq!(s.len(), 0);
204 assert_eq!(s.as_str(), "");
205 assert_eq!(s.as_gstr(), "");
206
207 s.set("str");
208 assert!(!s.is_empty());
209 assert_eq!(s.len(), "str".len());
210 assert_eq!(s.as_str().len(), "str".len());
211 assert_eq!(s.as_str(), "str");
212 assert_eq!(AsRef::<str>::as_ref(&s), "str");
213 assert_eq!(s.to_string(), "str");
215 assert_eq!(s.as_gstr().len(), "str".len());
216 assert_eq!(s.as_gstr(), "str");
217 assert_eq!(AsRef::<GStr>::as_ref(&s), "str");
218 assert_eq!(s.as_cstr().to_bytes(), b"str");
219 assert_eq!(AsRef::<CStr>::as_ref(&s).to_bytes(), b"str");
220 assert_eq!(s.as_bytes(), b"str");
221
222 let string = String::from("String");
223 s.set(string.as_str());
224 assert_eq!(s.as_str(), "String");
225 s.set(&string);
226 assert_eq!(s.as_str(), "String");
227
228 s.set(gstr!("gstr"));
229 assert_eq!(s.as_str(), "gstr");
230
231 let gstring = GString::from("GString");
232 s.set(gstring.as_gstr());
233 assert_eq!(s.as_str(), "GString");
234 s.set(&gstring);
235 assert_eq!(s.as_str(), "GString");
236 s.set(gstring.as_str());
237 assert_eq!(s.as_str(), "GString");
238
239 let mut ls = IdStr::new();
240
241 ls.set("An str longer than 15 bytes");
242 assert!(!ls.is_empty());
243 assert_eq!(ls.len(), "An str longer than 15 bytes".len());
244 assert_eq!(ls, "An str longer than 15 bytes");
245 assert_eq!(ls.to_string(), "An str longer than 15 bytes");
247 assert_eq!(ls.as_str().len(), "An str longer than 15 bytes".len());
248 assert_eq!(ls.as_str(), "An str longer than 15 bytes");
249 assert_eq!(ls.as_gstr().len(), "An str longer than 15 bytes".len());
250 assert_eq!(ls.as_gstr(), "An str longer than 15 bytes");
251 assert_eq!(ls.as_cstr().to_bytes(), b"An str longer than 15 bytes");
252 assert_eq!(
253 AsRef::<CStr>::as_ref(&ls).to_bytes(),
254 b"An str longer than 15 bytes"
255 );
256 assert_eq!(ls.as_bytes(), b"An str longer than 15 bytes");
257
258 ls.set(gstr!("A gstr longer than 15 bytes"));
259 assert_eq!(ls.as_str(), "A gstr longer than 15 bytes");
260 }
261
262 #[test]
263 fn from() {
264 let s = IdStr::from("str");
265 assert_eq!(s.len(), "str".len());
266 assert_eq!(s.as_str().len(), "str".len());
267 assert_eq!(s.as_str(), "str");
268 assert_eq!(s.to_string(), "str");
270 assert_eq!(s.as_gstr().len(), "str".len());
271 assert_eq!(s.as_gstr(), "str");
272
273 let string = String::from("String");
274 let s = IdStr::from(string.as_str());
275 assert_eq!(s.as_str(), "String");
276 let s: IdStr = string.as_str().into();
277 assert_eq!(s.as_str(), "String");
278 let s: IdStr = (&string).into();
279 assert_eq!(s.as_str(), "String");
280 let s: IdStr = string.into();
281 assert_eq!(s.as_str(), "String");
282
283 let s = IdStr::from(gstr!("str"));
284 assert_eq!(s.as_str(), "str");
285
286 let gstring = GString::from("GString");
287 let s = IdStr::from(gstring.as_gstr());
288 assert_eq!(s.as_str(), "GString");
289 let s: IdStr = (&gstring).into();
290 assert_eq!(s.as_str(), "GString");
291 let s: IdStr = gstring.into();
292 assert_eq!(s.as_str(), "GString");
293
294 let ls = IdStr::from("An str longer than 15 bytes");
295 assert!(!ls.is_empty());
296 assert_eq!(ls.len(), "An str longer than 15 bytes".len());
297 assert_eq!(ls, "An str longer than 15 bytes");
298 assert_eq!(ls.to_string(), "An str longer than 15 bytes");
300 assert_eq!(ls.as_str().len(), "An str longer than 15 bytes".len());
301 assert_eq!(ls.as_str(), "An str longer than 15 bytes");
302 assert_eq!(ls.as_gstr().len(), "An str longer than 15 bytes".len());
303 assert_eq!(ls.as_gstr(), "An str longer than 15 bytes");
304
305 let ls = IdStr::from(gstr!("A gstr longer than 15 bytes"));
306 assert_eq!(ls.as_str(), "A gstr longer than 15 bytes");
307 assert_eq!(ls.as_gstr(), "A gstr longer than 15 bytes");
308
309 let lstring = String::from("A String longer than 15 bytes");
310 let ls = IdStr::from(lstring.as_str());
311 assert_eq!(ls.as_str(), "A String longer than 15 bytes");
312 let ls = IdStr::from(&lstring);
313 assert_eq!(ls.as_str(), "A String longer than 15 bytes");
314
315 let lgstring = String::from("A GString longer than 15 bytes");
316 let ls = IdStr::from(lgstring.as_str());
317 assert_eq!(ls.as_str(), "A GString longer than 15 bytes");
318 let ls = IdStr::from(&lgstring);
319 assert_eq!(ls.as_str(), "A GString longer than 15 bytes");
320 }
321
322 #[test]
323 #[allow(clippy::cmp_owned)]
324 fn eq_cmp() {
325 let s1 = IdStr::from(STR);
326 let s12: IdStr = STR.into();
327 assert_eq!(s1, s12);
328 let s2 = IdStr::from(String::from(STR));
329 let s22: IdStr = String::from(STR).into();
330 assert_eq!(s2, s22);
331 let s3 = IdStr::from_static(gstr!("STR"));
332 assert_eq!(s1, s2);
333 assert_eq!(s1, s3);
334 assert_eq!(s2, s3);
335
336 assert!(s1 == gstr!("STR"));
337 assert_eq!(s1, gstr!("STR"));
338 assert_eq!(s1, GString::from("STR"));
339 assert!(s1 == "STR");
340 assert_eq!(s1, "STR");
341 assert!("STR" == s1);
342 assert_eq!("STR", s1);
343 assert_eq!(s1, String::from("STR"));
344
345 assert_eq!(gstr!("STR"), s1);
346 assert_eq!(GString::from("STR"), s1);
347 assert_eq!("STR", s1);
348 assert_eq!(String::from("STR"), s1);
349
350 let ls1 = IdStr::from(LONG_STR);
351 let ls2: IdStr = String::from(LONG_STR).into();
352 let ls3 = IdStr::from_static(gstr!("An STR longer than 15 bytes"));
353 assert_eq!(ls1, ls2);
354 assert_eq!(ls1, ls3);
355 assert_eq!(ls2, ls3);
356
357 assert!(ls1 == gstr!("An STR longer than 15 bytes"));
358 assert_eq!(ls1, gstr!("An STR longer than 15 bytes"));
359 assert_eq!(ls1, GString::from(LONG_STR));
360 assert_eq!(ls1, LONG_STR);
361 assert!(ls1 == "An STR longer than 15 bytes");
362 assert_eq!(ls1, "An STR longer than 15 bytes");
363 assert_eq!(ls1, String::from(LONG_STR));
364
365 assert_eq!(gstr!("An STR longer than 15 bytes"), ls1);
366 assert_eq!(GString::from(LONG_STR), ls1);
367 assert_eq!(LONG_STR, ls1);
368 assert_eq!("An STR longer than 15 bytes", ls1);
369 assert_eq!(String::from(LONG_STR), ls1);
370
371 assert_ne!(s1, ls1);
372 assert_ne!(ls1, s1);
373
374 let s4 = IdStr::from("STR4");
375 assert_ne!(s1, s4);
376 assert!(s1 < s4);
377 assert!(s4 > s1);
378
379 assert!(s1 < gstr!("STR4"));
380 assert!(s1 < GString::from("STR4"));
381 assert!(s1 < "STR4");
382 assert!("STR4" > s1);
383 assert!(s1 < String::from("STR4"));
384
385 assert!(gstr!("STR4") > s1);
386 assert!(GString::from("STR4") > s1);
387 assert!("STR4" > s1);
388 assert!(String::from("STR4") > s1);
389
390 assert_ne!(ls1, s4);
392 assert!(ls1 < s4);
393 assert!(s4 > s1);
394 }
395
396 #[test]
397 fn as_ref_idstr() {
398 #[allow(clippy::nonminimal_bool)]
399 fn check(c: &str, v: impl AsRef<IdStr>) {
400 let v = v.as_ref();
401
402 assert_eq!(c, v);
403 assert_eq!(v, c);
404
405 assert!(!(c > v));
406 assert!(!(v > c));
407
408 let i = IdStr::from(c);
409 assert_eq!(i, v);
410 assert_eq!(i, IdStr::from(c));
411
412 assert!(!(c > i));
413 assert!(!(i > c));
414 }
415
416 let v = IdStr::from(STR);
417 check(STR, &v);
418 check(STR, v);
419
420 #[allow(clippy::nonminimal_bool)]
421 fn check_gstr(c: &GStr, v: impl AsRef<IdStr>) {
422 let v = v.as_ref();
423
424 assert_eq!(c, v);
425 assert_eq!(v, c);
426
427 assert!(!(c > v));
428 assert!(!(v > c));
429 }
430
431 let v = IdStr::from(GSTR);
432 check_gstr(GSTR, &v);
433 check_gstr(GSTR, v);
434 }
435}