Skip to main content

gstreamer/id_str/
bindings.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3// rustdoc-stripper-ignore-next
4//! The `IdStr` bindings of the C type `GstIdStr`.
5//!
6//! See the higher level module documentation for details.
7
8use crate::ffi;
9use glib::{GStr, GString, translate::*};
10use std::{
11    cmp,
12    ffi::{CStr, c_char},
13    fmt,
14    hash::{Hash, Hasher},
15    mem,
16    ops::Deref,
17    ptr::NonNull,
18};
19
20glib::wrapper! {
21    // rustdoc-stripper-ignore-next
22    /// An UTF-8 immutable string type with optimizations for short values (len < 16).
23    // rustdoc-stripper-ignore-next-stop
24    /// s);
25    /// ```text
26    ///
27    #[derive(Debug)]
28    #[doc(alias = "GstIdStr")]
29    pub struct IdStr(BoxedInline<ffi::GstIdStr>);
30
31    match fn {
32        copy => |ptr| ffi::gst_id_str_copy(ptr),
33        free => |ptr| ffi::gst_id_str_free(ptr),
34        init => |ptr| ffi::gst_id_str_init(ptr),
35        copy_into => |dest, src| ffi::gst_id_str_copy_into(dest, src),
36        clear => |ptr| ffi::gst_id_str_clear(ptr),
37    }
38}
39
40impl IdStr {
41    #[doc(alias = "gst_id_str_new")]
42    #[inline]
43    pub const fn new() -> IdStr {
44        skip_assert_initialized!();
45        unsafe {
46            // Safety: empty inlined string consists in the type being all zeroed
47            IdStr {
48                inner: mem::zeroed(),
49            }
50        }
51    }
52
53    // rustdoc-stripper-ignore-next
54    /// Builds an `IdStr` from the given static `GStr`.
55    ///
56    /// This constructor performs optimizations which other constructors can't rely on.
57    ///
58    /// To build an `IdStr` from a string literal, use the [`idstr`](crate::idstr) macro.
59    #[inline]
60    pub fn from_static<T: AsRef<GStr> + ?Sized>(value: &'static T) -> IdStr {
61        skip_assert_initialized!();
62        let mut ret = IdStr::new();
63        ret.set_static(value);
64
65        ret
66    }
67
68    #[doc(alias = "gst_id_str_new")]
69    #[inline]
70    pub fn from<T: AsRef<str>>(value: T) -> IdStr {
71        skip_assert_initialized!();
72        let mut id = IdStr::new();
73        id.set(value);
74
75        id
76    }
77
78    /// Returns the length of `self`, exluding the NUL-terminator. This is equivalent to
79    /// calling ``strcmp()`` but potentially faster.
80    #[doc(alias = "gst_id_str_get_len")]
81    #[inline]
82    pub fn len(&self) -> usize {
83        unsafe { ffi::gst_id_str_get_len(self.to_glib_none().0) }
84    }
85
86    #[inline]
87    pub fn is_empty(&self) -> bool {
88        self.len() == 0
89    }
90
91    // rustdoc-stripper-ignore-next
92    /// Returns the pointer to the nul terminated string `value` represented by this `IdStr`.
93    #[inline]
94    fn as_char_ptr(&self) -> NonNull<c_char> {
95        unsafe {
96            let ptr = ffi::gst_id_str_as_str(self.to_glib_none().0);
97            debug_assert!(!ptr.is_null());
98            let nn = NonNull::<c_char>::new_unchecked(ptr as *mut _);
99
100            debug_assert_eq!(*nn.as_ptr().add(self.len()), 0, "expecting nul terminator");
101
102            nn
103        }
104    }
105
106    #[inline]
107    pub fn as_bytes(&self) -> &[u8] {
108        unsafe {
109            // Safety: `as_char_ptr()` returns a non-null pointer to a nul terminated string.
110            std::slice::from_raw_parts(self.as_char_ptr().as_ptr() as *const _, self.len())
111        }
112    }
113
114    #[inline]
115    fn as_bytes_with_nul(&self) -> &[u8] {
116        unsafe {
117            // Safety: `as_char_ptr()` returns a non-null pointer to a nul terminated string.
118            std::slice::from_raw_parts(self.as_char_ptr().as_ptr() as *const _, self.len() + 1)
119        }
120    }
121
122    ///
123    /// # Returns
124    ///
125    /// the NUL-terminated string representation of `self`.
126    #[inline]
127    pub fn as_str(&self) -> &str {
128        cfg_if::cfg_if! {
129            if #[cfg(debug_assertions)] {
130                std::str::from_utf8(self.as_bytes()).unwrap()
131            } else {
132                unsafe {
133                    std::str::from_utf8_unchecked(self.as_bytes())
134                }
135            }
136        }
137    }
138
139    #[doc(alias = "gst_id_str_as_str")]
140    #[inline]
141    pub fn as_gstr(&self) -> &GStr {
142        cfg_if::cfg_if! {
143            if #[cfg(debug_assertions)] {
144                GStr::from_utf8_with_nul(self.as_bytes_with_nul()).unwrap()
145            } else {
146                unsafe {
147                    GStr::from_utf8_with_nul_unchecked(self.as_bytes_with_nul())
148                }
149            }
150        }
151    }
152
153    #[inline]
154    pub fn as_cstr(&self) -> &CStr {
155        cfg_if::cfg_if! {
156            if #[cfg(debug_assertions)] {
157                CStr::from_bytes_with_nul(self.as_bytes_with_nul()).unwrap()
158            } else {
159                unsafe {
160                    CStr::from_bytes_with_nul_unchecked(self.as_bytes_with_nul())
161                }
162            }
163        }
164    }
165
166    #[doc(alias = "gst_id_str_is_equal")]
167    #[inline]
168    fn is_equal(&self, s2: &IdStr) -> bool {
169        unsafe {
170            from_glib(ffi::gst_id_str_is_equal(
171                self.to_glib_none().0,
172                s2.to_glib_none().0,
173            ))
174        }
175    }
176
177    /// Compares `self` and `s2` for equality.
178    /// ## `s2`
179    /// A string
180    ///
181    /// # Returns
182    ///
183    /// [`true`] if `self` and `s2` are equal.
184    #[doc(alias = "gst_id_str_is_equal_to_str_with_len")]
185    #[inline]
186    fn is_equal_to_str(&self, s2: impl AsRef<str>) -> bool {
187        unsafe {
188            let s2 = s2.as_ref();
189            from_glib(ffi::gst_id_str_is_equal_to_str_with_len(
190                self.to_glib_none().0,
191                s2.as_ptr() as *const c_char,
192                s2.len(),
193            ))
194        }
195    }
196
197    // rustdoc-stripper-ignore-next
198    /// Sets `self` to the static string `value`.
199    ///
200    /// This function performs optimizations which [IdStr::set] can't rely on.
201    ///
202    /// To build an `IdStr` from a string literal, use the [`idstr`](crate::idstr) macro.
203    #[doc(alias = "gst_id_str_set_static_str")]
204    #[doc(alias = "gst_id_str_set_static_str_with_len")]
205    #[inline]
206    pub fn set_static<T: AsRef<GStr> + ?Sized>(&mut self, value: &'static T) {
207        unsafe {
208            let v = value.as_ref();
209            ffi::gst_id_str_set_static_str_with_len(
210                self.to_glib_none_mut().0,
211                v.to_glib_none().0,
212                v.len(),
213            );
214        }
215    }
216
217    // rustdoc-stripper-ignore-next
218    /// Sets `self` to the string `value`.
219    ///
220    /// For a static value, use [IdStr::set_static] which can perform optimizations.
221    ///
222    /// To build an `IdStr` from a string literal, use the [`idstr`](crate::idstr) macro.
223    // rustdoc-stripper-ignore-next-stop
224    /// Sets `self` to the string `value`.
225    /// ## `value`
226    /// A NUL-terminated string
227    #[doc(alias = "gst_id_str_set")]
228    #[doc(alias = "gst_id_str_set_with_len")]
229    #[inline]
230    pub fn set(&mut self, value: impl AsRef<str>) {
231        unsafe {
232            let v = value.as_ref();
233            ffi::gst_id_str_set_with_len(
234                self.to_glib_none_mut().0,
235                v.as_ptr() as *const c_char,
236                v.len(),
237            );
238        }
239    }
240}
241
242impl Default for IdStr {
243    fn default() -> Self {
244        Self::new()
245    }
246}
247
248impl Deref for IdStr {
249    type Target = GStr;
250
251    fn deref(&self) -> &Self::Target {
252        self.as_gstr()
253    }
254}
255
256impl AsRef<str> for IdStr {
257    #[inline]
258    fn as_ref(&self) -> &str {
259        self.as_str()
260    }
261}
262
263impl AsRef<IdStr> for IdStr {
264    #[inline]
265    fn as_ref(&self) -> &IdStr {
266        self
267    }
268}
269
270impl AsRef<GStr> for IdStr {
271    #[inline]
272    fn as_ref(&self) -> &GStr {
273        self.as_gstr()
274    }
275}
276
277impl AsRef<CStr> for IdStr {
278    #[inline]
279    fn as_ref(&self) -> &CStr {
280        self.as_cstr()
281    }
282}
283
284impl From<&str> for IdStr {
285    #[inline]
286    fn from(value: &str) -> IdStr {
287        skip_assert_initialized!();
288        let mut ret = IdStr::new();
289        ret.set(value);
290
291        ret
292    }
293}
294
295impl From<&String> for IdStr {
296    #[inline]
297    fn from(value: &String) -> IdStr {
298        skip_assert_initialized!();
299        let mut ret = IdStr::new();
300        ret.set(value);
301
302        ret
303    }
304}
305
306impl From<String> for IdStr {
307    #[inline]
308    fn from(value: String) -> IdStr {
309        skip_assert_initialized!();
310        let mut ret = IdStr::new();
311        ret.set(&value);
312
313        ret
314    }
315}
316
317impl From<&GStr> for IdStr {
318    #[inline]
319    fn from(value: &GStr) -> IdStr {
320        // assert checked in new()
321        skip_assert_initialized!();
322        let mut ret = IdStr::new();
323        ret.set(value);
324
325        ret
326    }
327}
328
329impl From<&GString> for IdStr {
330    #[inline]
331    fn from(value: &GString) -> IdStr {
332        skip_assert_initialized!();
333        let mut ret = IdStr::new();
334        ret.set(value);
335
336        ret
337    }
338}
339
340impl From<GString> for IdStr {
341    #[inline]
342    fn from(value: GString) -> IdStr {
343        skip_assert_initialized!();
344        let mut ret = IdStr::new();
345        ret.set(&value);
346
347        ret
348    }
349}
350
351impl fmt::Display for IdStr {
352    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353        f.write_str(self.as_gstr())
354    }
355}
356
357impl PartialOrd for IdStr {
358    #[inline]
359    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
360        Some(self.cmp(other))
361    }
362}
363
364impl PartialEq for IdStr {
365    #[inline]
366    fn eq(&self, other: &Self) -> bool {
367        self.is_equal(other)
368    }
369}
370
371impl PartialOrd<&IdStr> for IdStr {
372    #[inline]
373    fn partial_cmp(&self, other: &&IdStr) -> Option<cmp::Ordering> {
374        Some(self.cmp(*other))
375    }
376}
377
378impl PartialEq<&IdStr> for IdStr {
379    #[inline]
380    fn eq(&self, other: &&IdStr) -> bool {
381        self.is_equal(other)
382    }
383}
384
385impl Ord for IdStr {
386    #[inline]
387    fn cmp(&self, other: &Self) -> cmp::Ordering {
388        self.as_cstr().cmp(other.as_cstr())
389    }
390}
391
392impl Eq for IdStr {}
393
394impl PartialOrd<&GStr> for IdStr {
395    #[inline]
396    fn partial_cmp(&self, other: &&GStr) -> Option<cmp::Ordering> {
397        self.as_str().partial_cmp(*other)
398    }
399}
400
401impl PartialEq<&GStr> for IdStr {
402    #[inline]
403    fn eq(&self, other: &&GStr) -> bool {
404        self.is_equal_to_str(other)
405    }
406}
407
408impl PartialOrd<GStr> for IdStr {
409    #[inline]
410    fn partial_cmp(&self, other: &GStr) -> Option<cmp::Ordering> {
411        self.as_str().partial_cmp(other)
412    }
413}
414
415impl PartialEq<GStr> for IdStr {
416    #[inline]
417    fn eq(&self, other: &GStr) -> bool {
418        self.is_equal_to_str(other)
419    }
420}
421
422impl PartialOrd<IdStr> for &GStr {
423    #[inline]
424    fn partial_cmp(&self, other: &IdStr) -> Option<cmp::Ordering> {
425        (*self).partial_cmp(other.as_gstr())
426    }
427}
428
429impl PartialEq<IdStr> for &GStr {
430    #[inline]
431    fn eq(&self, other: &IdStr) -> bool {
432        other.is_equal_to_str(self)
433    }
434}
435
436impl PartialOrd<IdStr> for GStr {
437    #[inline]
438    fn partial_cmp(&self, other: &IdStr) -> Option<cmp::Ordering> {
439        self.partial_cmp(other.as_gstr())
440    }
441}
442
443impl PartialEq<IdStr> for GStr {
444    #[inline]
445    fn eq(&self, other: &IdStr) -> bool {
446        other.is_equal_to_str(self)
447    }
448}
449
450impl PartialOrd<&str> for IdStr {
451    #[inline]
452    fn partial_cmp(&self, other: &&str) -> Option<cmp::Ordering> {
453        self.as_gstr().partial_cmp(*other)
454    }
455}
456
457impl PartialEq<&str> for IdStr {
458    #[inline]
459    fn eq(&self, other: &&str) -> bool {
460        self.is_equal_to_str(*other)
461    }
462}
463
464impl PartialOrd<str> for IdStr {
465    #[inline]
466    fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
467        self.as_gstr().partial_cmp(other)
468    }
469}
470
471impl PartialEq<str> for IdStr {
472    #[inline]
473    fn eq(&self, other: &str) -> bool {
474        self.is_equal_to_str(other)
475    }
476}
477
478impl PartialOrd<IdStr> for &str {
479    #[inline]
480    fn partial_cmp(&self, other: &IdStr) -> Option<cmp::Ordering> {
481        (*self).partial_cmp(other.as_gstr())
482    }
483}
484
485impl PartialEq<IdStr> for &str {
486    #[inline]
487    fn eq(&self, other: &IdStr) -> bool {
488        other.is_equal_to_str(self)
489    }
490}
491
492impl PartialOrd<IdStr> for str {
493    #[inline]
494    fn partial_cmp(&self, other: &IdStr) -> Option<cmp::Ordering> {
495        self.partial_cmp(other.as_gstr())
496    }
497}
498
499impl PartialEq<IdStr> for str {
500    #[inline]
501    fn eq(&self, other: &IdStr) -> bool {
502        other.is_equal_to_str(self)
503    }
504}
505
506impl PartialOrd<GString> for IdStr {
507    #[inline]
508    fn partial_cmp(&self, other: &GString) -> Option<cmp::Ordering> {
509        self.as_gstr().partial_cmp(other)
510    }
511}
512
513impl PartialEq<GString> for IdStr {
514    #[inline]
515    fn eq(&self, other: &GString) -> bool {
516        self.is_equal_to_str(other)
517    }
518}
519
520impl PartialOrd<IdStr> for GString {
521    #[inline]
522    fn partial_cmp(&self, other: &IdStr) -> Option<cmp::Ordering> {
523        self.partial_cmp(other.as_gstr())
524    }
525}
526
527impl PartialEq<IdStr> for GString {
528    #[inline]
529    fn eq(&self, other: &IdStr) -> bool {
530        other.is_equal_to_str(self)
531    }
532}
533
534impl PartialOrd<String> for IdStr {
535    #[inline]
536    fn partial_cmp(&self, other: &String) -> Option<cmp::Ordering> {
537        self.as_gstr().partial_cmp(other)
538    }
539}
540
541impl PartialEq<String> for IdStr {
542    #[inline]
543    fn eq(&self, other: &String) -> bool {
544        self.is_equal_to_str(other)
545    }
546}
547
548impl PartialOrd<IdStr> for String {
549    #[inline]
550    fn partial_cmp(&self, other: &IdStr) -> Option<cmp::Ordering> {
551        self.partial_cmp(other.as_gstr())
552    }
553}
554
555impl PartialEq<IdStr> for String {
556    #[inline]
557    fn eq(&self, other: &IdStr) -> bool {
558        other.is_equal_to_str(self)
559    }
560}
561
562impl Hash for IdStr {
563    fn hash<H: Hasher>(&self, state: &mut H) {
564        self.as_gstr().hash(state)
565    }
566}
567
568unsafe impl Send for IdStr {}
569unsafe impl Sync for IdStr {}
570
571// Tests are mutualised between this implementation and the one in id_str_compat
572// See gstreamer/id_str/mod.rs