1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | // rustdoc-stripper-ignore-next |
4 | //! Runtime type information. |
5 | |
6 | use std::{ |
7 | fmt, |
8 | marker::PhantomData, |
9 | mem, |
10 | num::{NonZeroI32, NonZeroI64, NonZeroI8, NonZeroU32, NonZeroU64, NonZeroU8}, |
11 | path::{Path, PathBuf}, |
12 | ptr, |
13 | }; |
14 | |
15 | use crate::{translate::*, IntoGStr, Slice}; |
16 | |
17 | // rustdoc-stripper-ignore-next |
18 | /// A GLib or GLib-based library type |
19 | #[derive (Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
20 | #[doc (alias = "GType" )] |
21 | #[repr (transparent)] |
22 | pub struct Type(ffi::GType); |
23 | |
24 | unsafe impl TransparentType for Type { |
25 | type GlibType = ffi::GType; |
26 | } |
27 | |
28 | impl Type { |
29 | // rustdoc-stripper-ignore-next |
30 | /// An invalid `Type` used as error return value in some functions |
31 | #[doc (alias = "G_TYPE_INVALID" )] |
32 | pub const INVALID: Self = Self(gobject_ffi::G_TYPE_INVALID); |
33 | |
34 | // rustdoc-stripper-ignore-next |
35 | /// The fundamental type corresponding to the unit type `()` |
36 | #[doc (alias = "G_TYPE_NONE" )] |
37 | pub const UNIT: Self = Self(gobject_ffi::G_TYPE_NONE); |
38 | |
39 | // rustdoc-stripper-ignore-next |
40 | /// The fundamental type corresponding to `i8` |
41 | #[doc (alias = "G_TYPE_CHAR" )] |
42 | pub const I8: Self = Self(gobject_ffi::G_TYPE_CHAR); |
43 | |
44 | // rustdoc-stripper-ignore-next |
45 | /// The fundamental type corresponding to `u8` |
46 | #[doc (alias = "G_TYPE_UCHAR" )] |
47 | pub const U8: Self = Self(gobject_ffi::G_TYPE_UCHAR); |
48 | |
49 | // rustdoc-stripper-ignore-next |
50 | /// The fundamental type corresponding to `bool` |
51 | #[doc (alias = "G_TYPE_BOOLEAN" )] |
52 | pub const BOOL: Self = Self(gobject_ffi::G_TYPE_BOOLEAN); |
53 | |
54 | // rustdoc-stripper-ignore-next |
55 | /// The fundamental type corresponding to `i32` |
56 | #[doc (alias = "G_TYPE_INT" )] |
57 | pub const I32: Self = Self(gobject_ffi::G_TYPE_INT); |
58 | |
59 | // rustdoc-stripper-ignore-next |
60 | /// The fundamental type corresponding to `u32` |
61 | #[doc (alias = "G_TYPE_UINT" )] |
62 | pub const U32: Self = Self(gobject_ffi::G_TYPE_UINT); |
63 | |
64 | // rustdoc-stripper-ignore-next |
65 | /// The fundamental type corresponding to C `long` |
66 | #[doc (alias = "G_TYPE_LONG" )] |
67 | pub const I_LONG: Self = Self(gobject_ffi::G_TYPE_LONG); |
68 | |
69 | // rustdoc-stripper-ignore-next |
70 | /// The fundamental type corresponding to C `unsigned long` |
71 | #[doc (alias = "G_TYPE_ULONG" )] |
72 | pub const U_LONG: Self = Self(gobject_ffi::G_TYPE_ULONG); |
73 | |
74 | // rustdoc-stripper-ignore-next |
75 | /// The fundamental type corresponding to `i64` |
76 | #[doc (alias = "G_TYPE_INT64" )] |
77 | pub const I64: Self = Self(gobject_ffi::G_TYPE_INT64); |
78 | |
79 | // rustdoc-stripper-ignore-next |
80 | /// The fundamental type corresponding to `u64` |
81 | #[doc (alias = "G_TYPE_UINT64" )] |
82 | pub const U64: Self = Self(gobject_ffi::G_TYPE_UINT64); |
83 | |
84 | // rustdoc-stripper-ignore-next |
85 | /// The fundamental type corresponding to `f32` |
86 | #[doc (alias = "G_TYPE_FLOAT" )] |
87 | pub const F32: Self = Self(gobject_ffi::G_TYPE_FLOAT); |
88 | |
89 | // rustdoc-stripper-ignore-next |
90 | /// The fundamental type corresponding to `f64` |
91 | #[doc (alias = "G_TYPE_DOUBLE" )] |
92 | pub const F64: Self = Self(gobject_ffi::G_TYPE_DOUBLE); |
93 | |
94 | // rustdoc-stripper-ignore-next |
95 | /// The fundamental type corresponding to `String` |
96 | #[doc (alias = "G_TYPE_STRING" )] |
97 | pub const STRING: Self = Self(gobject_ffi::G_TYPE_STRING); |
98 | |
99 | // rustdoc-stripper-ignore-next |
100 | /// The fundamental type corresponding to a pointer |
101 | #[doc (alias = "G_TYPE_POINTER" )] |
102 | pub const POINTER: Self = Self(gobject_ffi::G_TYPE_POINTER); |
103 | |
104 | // rustdoc-stripper-ignore-next |
105 | /// The fundamental type of GVariant |
106 | #[doc (alias = "G_TYPE_VARIANT" )] |
107 | pub const VARIANT: Self = Self(gobject_ffi::G_TYPE_VARIANT); |
108 | |
109 | // rustdoc-stripper-ignore-next |
110 | /// The fundamental type from which all interfaces are derived |
111 | #[doc (alias = "G_TYPE_INTERFACE" )] |
112 | pub const INTERFACE: Self = Self(gobject_ffi::G_TYPE_INTERFACE); |
113 | |
114 | // rustdoc-stripper-ignore-next |
115 | /// The fundamental type from which all enumeration types are derived |
116 | #[doc (alias = "G_TYPE_ENUM" )] |
117 | pub const ENUM: Self = Self(gobject_ffi::G_TYPE_ENUM); |
118 | |
119 | // rustdoc-stripper-ignore-next |
120 | /// The fundamental type from which all flags types are derived |
121 | #[doc (alias = "G_TYPE_FLAGS" )] |
122 | pub const FLAGS: Self = Self(gobject_ffi::G_TYPE_FLAGS); |
123 | |
124 | // rustdoc-stripper-ignore-next |
125 | /// The fundamental type from which all boxed types are derived |
126 | #[doc (alias = "G_TYPE_BOXED" )] |
127 | pub const BOXED: Self = Self(gobject_ffi::G_TYPE_BOXED); |
128 | |
129 | // rustdoc-stripper-ignore-next |
130 | /// The fundamental type from which all `GParamSpec` types are derived |
131 | #[doc (alias = "G_TYPE_PARAM" )] |
132 | pub const PARAM_SPEC: Self = Self(gobject_ffi::G_TYPE_PARAM); |
133 | |
134 | // rustdoc-stripper-ignore-next |
135 | /// The fundamental type from which all objects are derived |
136 | #[doc (alias = "G_TYPE_OBJECT" )] |
137 | pub const OBJECT: Self = Self(gobject_ffi::G_TYPE_OBJECT); |
138 | |
139 | #[doc (alias = "g_type_name" )] |
140 | pub fn name<'a>(self) -> &'a str { |
141 | match self.into_glib() { |
142 | gobject_ffi::G_TYPE_INVALID => "<invalid>" , |
143 | x => unsafe { |
144 | let ptr = gobject_ffi::g_type_name(x); |
145 | std::ffi::CStr::from_ptr(ptr).to_str().unwrap() |
146 | }, |
147 | } |
148 | } |
149 | |
150 | #[doc (alias = "g_type_qname" )] |
151 | pub fn qname(self) -> crate::Quark { |
152 | match self.into_glib() { |
153 | gobject_ffi::G_TYPE_INVALID => crate::Quark::from_str("<invalid>" ), |
154 | x => unsafe { from_glib(gobject_ffi::g_type_qname(x)) }, |
155 | } |
156 | } |
157 | |
158 | #[doc (alias = "g_type_is_a" )] |
159 | #[inline ] |
160 | pub fn is_a(self, other: Self) -> bool { |
161 | unsafe { |
162 | from_glib(gobject_ffi::g_type_is_a( |
163 | self.into_glib(), |
164 | other.into_glib(), |
165 | )) |
166 | } |
167 | } |
168 | |
169 | #[doc (alias = "g_type_parent" )] |
170 | pub fn parent(self) -> Option<Self> { |
171 | unsafe { |
172 | let parent: Self = from_glib(gobject_ffi::g_type_parent(self.into_glib())); |
173 | Some(parent).filter(|t| t.is_valid()) |
174 | } |
175 | } |
176 | |
177 | #[doc (alias = "g_type_children" )] |
178 | pub fn children(self) -> Slice<Self> { |
179 | unsafe { |
180 | let mut n_children = 0u32; |
181 | let children = gobject_ffi::g_type_children(self.into_glib(), &mut n_children); |
182 | |
183 | Slice::from_glib_full_num(children, n_children as usize) |
184 | } |
185 | } |
186 | |
187 | #[doc (alias = "g_type_interfaces" )] |
188 | pub fn interfaces(self) -> Slice<Self> { |
189 | unsafe { |
190 | let mut n_interfaces = 0u32; |
191 | let interfaces = gobject_ffi::g_type_interfaces(self.into_glib(), &mut n_interfaces); |
192 | |
193 | Slice::from_glib_full_num(interfaces, n_interfaces as usize) |
194 | } |
195 | } |
196 | |
197 | #[doc (alias = "g_type_interface_prerequisites" )] |
198 | pub fn interface_prerequisites(self) -> Slice<Self> { |
199 | unsafe { |
200 | match self { |
201 | t if !t.is_a(Self::INTERFACE) => Slice::from_glib_full_num(ptr::null_mut(), 0), |
202 | _ => { |
203 | let mut n_prereqs = 0u32; |
204 | let prereqs = gobject_ffi::g_type_interface_prerequisites( |
205 | self.into_glib(), |
206 | &mut n_prereqs, |
207 | ); |
208 | |
209 | Slice::from_glib_full_num(prereqs, n_prereqs as usize) |
210 | } |
211 | } |
212 | } |
213 | } |
214 | |
215 | #[doc (alias = "g_type_from_name" )] |
216 | pub fn from_name(name: impl IntoGStr) -> Option<Self> { |
217 | unsafe { |
218 | let type_ = name.run_with_gstr(|name| { |
219 | Self::from_glib(gobject_ffi::g_type_from_name(name.as_ptr())) |
220 | }); |
221 | |
222 | Some(type_).filter(|t| t.is_valid()) |
223 | } |
224 | } |
225 | |
226 | // rustdoc-stripper-ignore-next |
227 | /// Checks that the type is not [`INVALID`](Self::INVALID) |
228 | #[inline ] |
229 | pub fn is_valid(self) -> bool { |
230 | self != Self::INVALID |
231 | } |
232 | } |
233 | |
234 | impl fmt::Debug for Type { |
235 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
236 | f.write_str(self.name()) |
237 | } |
238 | } |
239 | |
240 | impl fmt::Display for Type { |
241 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
242 | f.write_str(self.name()) |
243 | } |
244 | } |
245 | |
246 | // rustdoc-stripper-ignore-next |
247 | /// Types that are supported by GLib dynamic typing. |
248 | pub trait StaticType { |
249 | // rustdoc-stripper-ignore-next |
250 | /// Returns the type identifier of `Self`. |
251 | fn static_type() -> Type; |
252 | } |
253 | |
254 | impl StaticType for Type { |
255 | #[doc (alias = "g_gtype_get_type" )] |
256 | #[inline ] |
257 | fn static_type() -> Type { |
258 | unsafe { from_glib(val:gobject_ffi::g_gtype_get_type()) } |
259 | } |
260 | } |
261 | |
262 | pub trait StaticTypeExt { |
263 | // rustdoc-stripper-ignore-next |
264 | /// Ensures that the type has been registered with the type system. |
265 | #[doc (alias = "g_type_ensure" )] |
266 | fn ensure_type(); |
267 | } |
268 | |
269 | impl<T: StaticType> StaticTypeExt for T { |
270 | #[inline ] |
271 | fn ensure_type() { |
272 | T::static_type(); |
273 | } |
274 | } |
275 | |
276 | #[doc (hidden)] |
277 | impl crate::value::ValueType for Type { |
278 | type Type = Type; |
279 | } |
280 | |
281 | #[doc (hidden)] |
282 | unsafe impl<'a> crate::value::FromValue<'a> for Type { |
283 | type Checker = crate::value::GenericValueTypeChecker<Self>; |
284 | |
285 | #[inline ] |
286 | unsafe fn from_value(value: &'a crate::Value) -> Self { |
287 | from_glib(val:gobject_ffi::g_value_get_gtype(value.to_glib_none().0)) |
288 | } |
289 | } |
290 | |
291 | #[doc (hidden)] |
292 | impl crate::value::ToValue for Type { |
293 | #[inline ] |
294 | fn to_value(&self) -> crate::Value { |
295 | unsafe { |
296 | let mut value: Value = crate::Value::from_type_unchecked(type_:Type::static_type()); |
297 | gobject_ffi::g_value_set_gtype(value:value.to_glib_none_mut().0, self.into_glib()); |
298 | value |
299 | } |
300 | } |
301 | |
302 | #[inline ] |
303 | fn value_type(&self) -> crate::Type { |
304 | Type::static_type() |
305 | } |
306 | } |
307 | |
308 | #[doc (hidden)] |
309 | impl From<Type> for crate::Value { |
310 | #[inline ] |
311 | fn from(t: Type) -> Self { |
312 | crate::value::ToValue::to_value(&t) |
313 | } |
314 | } |
315 | |
316 | impl<'a, T: ?Sized + StaticType> StaticType for &'a T { |
317 | #[inline ] |
318 | fn static_type() -> Type { |
319 | T::static_type() |
320 | } |
321 | } |
322 | |
323 | impl<'a, T: ?Sized + StaticType> StaticType for &'a mut T { |
324 | #[inline ] |
325 | fn static_type() -> Type { |
326 | T::static_type() |
327 | } |
328 | } |
329 | |
330 | macro_rules! builtin { |
331 | ($name:ty, $val:ident) => { |
332 | impl StaticType for $name { |
333 | #[inline] |
334 | fn static_type() -> Type { |
335 | Type::$val |
336 | } |
337 | } |
338 | }; |
339 | } |
340 | |
341 | // rustdoc-stripper-ignore-next |
342 | /// A GLib pointer |
343 | /// |
344 | /// A raw untyped pointer equivalent to [`*mut Pointee`](Pointee). |
345 | pub type Pointer = ffi::gpointer; |
346 | |
347 | // rustdoc-stripper-ignore-next |
348 | /// The target of a [Pointer] |
349 | /// |
350 | /// # Examples |
351 | /// |
352 | /// ``` |
353 | /// use glib::prelude::*; |
354 | /// use glib::types::{Pointee, Pointer}; |
355 | /// use std::ptr::NonNull; |
356 | /// |
357 | /// let pointer = NonNull::<Pointee>::dangling(); |
358 | /// let value = pointer.to_value(); |
359 | /// assert!(value.is::<Pointer>()); |
360 | /// assert_eq!(value.get(), Ok(pointer.as_ptr())); |
361 | /// ``` |
362 | pub type Pointee = libc::c_void; |
363 | |
364 | impl StaticType for ptr::NonNull<Pointee> { |
365 | #[inline ] |
366 | fn static_type() -> Type { |
367 | Pointer::static_type() |
368 | } |
369 | } |
370 | |
371 | #[derive (Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] |
372 | pub struct ILong(pub libc::c_long); |
373 | |
374 | impl std::ops::Deref for ILong { |
375 | type Target = libc::c_long; |
376 | |
377 | #[inline ] |
378 | fn deref(&self) -> &Self::Target { |
379 | &self.0 |
380 | } |
381 | } |
382 | |
383 | impl std::ops::DerefMut for ILong { |
384 | #[inline ] |
385 | fn deref_mut(&mut self) -> &mut Self::Target { |
386 | &mut self.0 |
387 | } |
388 | } |
389 | |
390 | impl From<libc::c_long> for ILong { |
391 | #[inline ] |
392 | fn from(v: libc::c_long) -> ILong { |
393 | ILong(v) |
394 | } |
395 | } |
396 | |
397 | impl From<ILong> for libc::c_long { |
398 | #[inline ] |
399 | fn from(v: ILong) -> libc::c_long { |
400 | v.0 |
401 | } |
402 | } |
403 | |
404 | impl PartialEq<libc::c_long> for ILong { |
405 | #[inline ] |
406 | fn eq(&self, other: &libc::c_long) -> bool { |
407 | &self.0 == other |
408 | } |
409 | } |
410 | |
411 | impl PartialEq<ILong> for libc::c_long { |
412 | #[inline ] |
413 | fn eq(&self, other: &ILong) -> bool { |
414 | self == &other.0 |
415 | } |
416 | } |
417 | |
418 | impl PartialOrd<libc::c_long> for ILong { |
419 | #[inline ] |
420 | fn partial_cmp(&self, other: &libc::c_long) -> Option<std::cmp::Ordering> { |
421 | self.0.partial_cmp(other) |
422 | } |
423 | } |
424 | |
425 | impl PartialOrd<ILong> for libc::c_long { |
426 | #[inline ] |
427 | fn partial_cmp(&self, other: &ILong) -> Option<std::cmp::Ordering> { |
428 | self.partial_cmp(&other.0) |
429 | } |
430 | } |
431 | |
432 | #[derive (Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] |
433 | pub struct ULong(pub libc::c_ulong); |
434 | |
435 | impl std::ops::Deref for ULong { |
436 | type Target = libc::c_ulong; |
437 | |
438 | #[inline ] |
439 | fn deref(&self) -> &Self::Target { |
440 | &self.0 |
441 | } |
442 | } |
443 | |
444 | impl std::ops::DerefMut for ULong { |
445 | #[inline ] |
446 | fn deref_mut(&mut self) -> &mut Self::Target { |
447 | &mut self.0 |
448 | } |
449 | } |
450 | |
451 | impl From<libc::c_ulong> for ULong { |
452 | #[inline ] |
453 | fn from(v: libc::c_ulong) -> ULong { |
454 | ULong(v) |
455 | } |
456 | } |
457 | |
458 | impl From<ULong> for libc::c_ulong { |
459 | #[inline ] |
460 | fn from(v: ULong) -> libc::c_ulong { |
461 | v.0 |
462 | } |
463 | } |
464 | |
465 | impl PartialEq<libc::c_ulong> for ULong { |
466 | #[inline ] |
467 | fn eq(&self, other: &libc::c_ulong) -> bool { |
468 | &self.0 == other |
469 | } |
470 | } |
471 | |
472 | impl PartialEq<ULong> for libc::c_ulong { |
473 | #[inline ] |
474 | fn eq(&self, other: &ULong) -> bool { |
475 | self == &other.0 |
476 | } |
477 | } |
478 | |
479 | impl PartialOrd<libc::c_ulong> for ULong { |
480 | #[inline ] |
481 | fn partial_cmp(&self, other: &libc::c_ulong) -> Option<std::cmp::Ordering> { |
482 | self.0.partial_cmp(other) |
483 | } |
484 | } |
485 | |
486 | impl PartialOrd<ULong> for libc::c_ulong { |
487 | #[inline ] |
488 | fn partial_cmp(&self, other: &ULong) -> Option<std::cmp::Ordering> { |
489 | self.partial_cmp(&other.0) |
490 | } |
491 | } |
492 | |
493 | builtin!(bool, BOOL); |
494 | builtin!(i8, I8); |
495 | builtin!(NonZeroI8, I8); |
496 | builtin!(u8, U8); |
497 | builtin!(NonZeroU8, U8); |
498 | builtin!(i32, I32); |
499 | builtin!(NonZeroI32, I32); |
500 | builtin!(u32, U32); |
501 | builtin!(NonZeroU32, U32); |
502 | builtin!(i64, I64); |
503 | builtin!(NonZeroI64, I64); |
504 | builtin!(u64, U64); |
505 | builtin!(NonZeroU64, U64); |
506 | builtin!(ILong, I_LONG); |
507 | builtin!(ULong, U_LONG); |
508 | builtin!(f32, F32); |
509 | builtin!(f64, F64); |
510 | builtin!(str, STRING); |
511 | builtin!(String, STRING); |
512 | builtin!(PathBuf, STRING); |
513 | builtin!(Path, STRING); |
514 | builtin!(Pointer, POINTER); |
515 | |
516 | impl<'a> StaticType for [&'a str] { |
517 | #[inline ] |
518 | fn static_type() -> Type { |
519 | unsafe { from_glib(val:ffi::g_strv_get_type()) } |
520 | } |
521 | } |
522 | |
523 | impl StaticType for Vec<String> { |
524 | #[inline ] |
525 | fn static_type() -> Type { |
526 | unsafe { from_glib(val:ffi::g_strv_get_type()) } |
527 | } |
528 | } |
529 | |
530 | impl StaticType for () { |
531 | #[inline ] |
532 | fn static_type() -> Type { |
533 | Type::UNIT |
534 | } |
535 | } |
536 | |
537 | #[inline ] |
538 | pub unsafe fn instance_of<C: StaticType>(ptr: ffi::gconstpointer) -> bool { |
539 | from_glib(val:gobject_ffi::g_type_check_instance_is_a( |
540 | instance:ptr as *mut _, |
541 | <C as StaticType>::static_type().into_glib(), |
542 | )) |
543 | } |
544 | |
545 | impl FromGlib<ffi::GType> for Type { |
546 | #[inline ] |
547 | unsafe fn from_glib(val: ffi::GType) -> Self { |
548 | Self(val) |
549 | } |
550 | } |
551 | |
552 | impl IntoGlib for Type { |
553 | type GlibType = ffi::GType; |
554 | |
555 | #[inline ] |
556 | fn into_glib(self) -> ffi::GType { |
557 | self.0 |
558 | } |
559 | } |
560 | |
561 | impl<'a> ToGlibContainerFromSlice<'a, *mut ffi::GType> for Type { |
562 | type Storage = PhantomData<&'a [Type]>; |
563 | |
564 | #[inline ] |
565 | fn to_glib_none_from_slice(t: &'a [Type]) -> (*mut ffi::GType, Self::Storage) { |
566 | (t.as_ptr() as *mut ffi::GType, PhantomData) |
567 | } |
568 | |
569 | #[inline ] |
570 | fn to_glib_container_from_slice(t: &'a [Type]) -> (*mut ffi::GType, Self::Storage) { |
571 | (Self::to_glib_full_from_slice(t), PhantomData) |
572 | } |
573 | |
574 | fn to_glib_full_from_slice(t: &[Type]) -> *mut ffi::GType { |
575 | if t.is_empty() { |
576 | return ptr::null_mut(); |
577 | } |
578 | |
579 | unsafe { |
580 | let res = |
581 | ffi::g_malloc(mem::size_of::<ffi::GType>() * (t.len() + 1)) as *mut ffi::GType; |
582 | std::ptr::copy_nonoverlapping(t.as_ptr() as *const ffi::GType, res, t.len()); |
583 | *res.add(t.len()) = 0; |
584 | res |
585 | } |
586 | } |
587 | } |
588 | |
589 | impl FromGlibContainerAsVec<Type, *const ffi::GType> for Type { |
590 | unsafe fn from_glib_none_num_as_vec(ptr: *const ffi::GType, num: usize) -> Vec<Self> { |
591 | if num == 0 || ptr.is_null() { |
592 | return Vec::new(); |
593 | } |
594 | |
595 | let mut res: Vec = Vec::<Self>::with_capacity(num); |
596 | let res_ptr: *mut usize = res.as_mut_ptr() as *mut ffi::GType; |
597 | std::ptr::copy_nonoverlapping(src:ptr, dst:res_ptr, count:num); |
598 | res.set_len(new_len:num); |
599 | res |
600 | } |
601 | |
602 | unsafe fn from_glib_container_num_as_vec(_: *const ffi::GType, _: usize) -> Vec<Self> { |
603 | // Can't really free a *const |
604 | unimplemented!(); |
605 | } |
606 | |
607 | unsafe fn from_glib_full_num_as_vec(_: *const ffi::GType, _: usize) -> Vec<Self> { |
608 | // Can't really free a *const |
609 | unimplemented!(); |
610 | } |
611 | } |
612 | |
613 | impl FromGlibContainerAsVec<Type, *mut ffi::GType> for Type { |
614 | unsafe fn from_glib_none_num_as_vec(ptr: *mut ffi::GType, num: usize) -> Vec<Self> { |
615 | FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num) |
616 | } |
617 | |
618 | unsafe fn from_glib_container_num_as_vec(ptr: *mut ffi::GType, num: usize) -> Vec<Self> { |
619 | let res: Vec = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num); |
620 | ffi::g_free(mem:ptr as *mut _); |
621 | res |
622 | } |
623 | |
624 | unsafe fn from_glib_full_num_as_vec(ptr: *mut ffi::GType, num: usize) -> Vec<Self> { |
625 | FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num) |
626 | } |
627 | } |
628 | |
629 | #[cfg (test)] |
630 | mod tests { |
631 | use std::collections::{BTreeSet, HashSet}; |
632 | |
633 | use super::*; |
634 | use crate::InitiallyUnowned; |
635 | |
636 | #[test ] |
637 | fn invalid() { |
638 | let invalid = Type::INVALID; |
639 | |
640 | assert_eq!(invalid.name(), "<invalid>" ); |
641 | assert_eq!(invalid.qname(), crate::Quark::from_str("<invalid>" )); |
642 | assert!(invalid.is_a(Type::INVALID)); |
643 | assert!(!invalid.is_a(Type::STRING)); |
644 | assert_eq!(invalid.parent(), None); |
645 | assert!(invalid.children().is_empty()); |
646 | assert!(invalid.interfaces().is_empty()); |
647 | assert!(invalid.interface_prerequisites().is_empty()); |
648 | assert!(!invalid.is_valid()); |
649 | dbg!(&invalid); |
650 | } |
651 | |
652 | #[test ] |
653 | fn hash() { |
654 | // Get this first so the type is registered |
655 | let iu_type = InitiallyUnowned::static_type(); |
656 | |
657 | let set = Type::OBJECT |
658 | .children() |
659 | .iter() |
660 | .copied() |
661 | .collect::<HashSet<_>>(); |
662 | assert!(set.contains(&iu_type)); |
663 | } |
664 | |
665 | #[test ] |
666 | fn ord() { |
667 | // Get this first so the type is registered |
668 | let iu_type = InitiallyUnowned::static_type(); |
669 | assert!(Type::OBJECT < iu_type); |
670 | |
671 | let set = Type::OBJECT |
672 | .children() |
673 | .iter() |
674 | .copied() |
675 | .collect::<BTreeSet<_>>(); |
676 | assert!(set.contains(&iu_type)); |
677 | } |
678 | } |
679 | |