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::{ffi, gobject_ffi, prelude::*, translate::*, Slice, TypeFlags, TypePlugin}; |
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 | #[doc (alias = "g_type_get_plugin" )] |
227 | pub fn plugin(self) -> Option<TypePlugin> { |
228 | unsafe { |
229 | let plugin_ptr = gobject_ffi::g_type_get_plugin(self.into_glib()); |
230 | if plugin_ptr.is_null() { |
231 | None |
232 | } else { |
233 | Some(TypePlugin::from_glib_none(plugin_ptr)) |
234 | } |
235 | } |
236 | } |
237 | |
238 | #[doc (alias = "g_type_register_dynamic" )] |
239 | pub fn register_dynamic( |
240 | parent_type: Self, |
241 | name: impl IntoGStr, |
242 | plugin: &TypePlugin, |
243 | flags: TypeFlags, |
244 | ) -> Self { |
245 | unsafe { |
246 | name.run_with_gstr(|name| { |
247 | Self::from_glib(gobject_ffi::g_type_register_dynamic( |
248 | parent_type.into_glib(), |
249 | name.as_ptr(), |
250 | plugin.as_ptr(), |
251 | flags.into_glib(), |
252 | )) |
253 | }) |
254 | } |
255 | } |
256 | |
257 | #[doc (alias = "g_type_add_interface_dynamic" )] |
258 | pub fn add_interface_dynamic(self, interface_type: Self, plugin: &TypePlugin) { |
259 | unsafe { |
260 | gobject_ffi::g_type_add_interface_dynamic( |
261 | self.into_glib(), |
262 | interface_type.into_glib(), |
263 | plugin.as_ptr(), |
264 | ); |
265 | } |
266 | } |
267 | |
268 | // rustdoc-stripper-ignore-next |
269 | /// Checks that the type is not [`INVALID`](Self::INVALID) |
270 | #[inline ] |
271 | pub fn is_valid(self) -> bool { |
272 | self != Self::INVALID |
273 | } |
274 | } |
275 | |
276 | impl fmt::Debug for Type { |
277 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
278 | f.write_str(self.name()) |
279 | } |
280 | } |
281 | |
282 | impl fmt::Display for Type { |
283 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
284 | f.write_str(self.name()) |
285 | } |
286 | } |
287 | |
288 | // rustdoc-stripper-ignore-next |
289 | /// Types that are supported by GLib dynamic typing. |
290 | pub trait StaticType { |
291 | // rustdoc-stripper-ignore-next |
292 | /// Returns the type identifier of `Self`. |
293 | fn static_type() -> Type; |
294 | } |
295 | |
296 | impl StaticType for Type { |
297 | #[doc (alias = "g_gtype_get_type" )] |
298 | #[inline ] |
299 | fn static_type() -> Type { |
300 | unsafe { from_glib(val:gobject_ffi::g_gtype_get_type()) } |
301 | } |
302 | } |
303 | |
304 | pub trait StaticTypeExt { |
305 | // rustdoc-stripper-ignore-next |
306 | /// Ensures that the type has been registered with the type system. |
307 | #[doc (alias = "g_type_ensure" )] |
308 | fn ensure_type(); |
309 | } |
310 | |
311 | impl<T: StaticType> StaticTypeExt for T { |
312 | #[inline ] |
313 | fn ensure_type() { |
314 | T::static_type(); |
315 | } |
316 | } |
317 | |
318 | #[doc (hidden)] |
319 | impl crate::value::ValueType for Type { |
320 | type Type = Type; |
321 | } |
322 | |
323 | #[doc (hidden)] |
324 | unsafe impl<'a> crate::value::FromValue<'a> for Type { |
325 | type Checker = crate::value::GenericValueTypeChecker<Self>; |
326 | |
327 | #[inline ] |
328 | unsafe fn from_value(value: &'a crate::Value) -> Self { |
329 | from_glib(val:gobject_ffi::g_value_get_gtype(value.to_glib_none().0)) |
330 | } |
331 | } |
332 | |
333 | #[doc (hidden)] |
334 | impl crate::value::ToValue for Type { |
335 | #[inline ] |
336 | fn to_value(&self) -> crate::Value { |
337 | unsafe { |
338 | let mut value: Value = crate::Value::from_type_unchecked(type_:Type::static_type()); |
339 | gobject_ffi::g_value_set_gtype(value.to_glib_none_mut().0, self.into_glib()); |
340 | value |
341 | } |
342 | } |
343 | |
344 | #[inline ] |
345 | fn value_type(&self) -> crate::Type { |
346 | Type::static_type() |
347 | } |
348 | } |
349 | |
350 | #[doc (hidden)] |
351 | impl From<Type> for crate::Value { |
352 | #[inline ] |
353 | fn from(t: Type) -> Self { |
354 | crate::value::ToValue::to_value(&t) |
355 | } |
356 | } |
357 | |
358 | impl<T: ?Sized + StaticType> StaticType for &'_ T { |
359 | #[inline ] |
360 | fn static_type() -> Type { |
361 | T::static_type() |
362 | } |
363 | } |
364 | |
365 | impl<T: ?Sized + StaticType> StaticType for &'_ mut T { |
366 | #[inline ] |
367 | fn static_type() -> Type { |
368 | T::static_type() |
369 | } |
370 | } |
371 | |
372 | macro_rules! builtin { |
373 | ($name:ty, $val:ident) => { |
374 | impl StaticType for $name { |
375 | #[inline] |
376 | fn static_type() -> Type { |
377 | Type::$val |
378 | } |
379 | } |
380 | }; |
381 | } |
382 | |
383 | // rustdoc-stripper-ignore-next |
384 | /// A GLib pointer |
385 | /// |
386 | /// A raw untyped pointer equivalent to [`*mut Pointee`](Pointee). |
387 | pub type Pointer = ffi::gpointer; |
388 | |
389 | // rustdoc-stripper-ignore-next |
390 | /// The target of a [Pointer] |
391 | /// |
392 | /// # Examples |
393 | /// |
394 | /// ``` |
395 | /// use glib::prelude::*; |
396 | /// use glib::types::{Pointee, Pointer}; |
397 | /// use std::ptr::NonNull; |
398 | /// |
399 | /// let pointer = NonNull::<Pointee>::dangling(); |
400 | /// let value = pointer.to_value(); |
401 | /// assert!(value.is::<Pointer>()); |
402 | /// assert_eq!(value.get(), Ok(pointer.as_ptr())); |
403 | /// ``` |
404 | pub type Pointee = libc::c_void; |
405 | |
406 | impl StaticType for ptr::NonNull<Pointee> { |
407 | #[inline ] |
408 | fn static_type() -> Type { |
409 | Pointer::static_type() |
410 | } |
411 | } |
412 | |
413 | #[derive (Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] |
414 | pub struct ILong(pub libc::c_long); |
415 | |
416 | impl std::ops::Deref for ILong { |
417 | type Target = libc::c_long; |
418 | |
419 | #[inline ] |
420 | fn deref(&self) -> &Self::Target { |
421 | &self.0 |
422 | } |
423 | } |
424 | |
425 | impl std::ops::DerefMut for ILong { |
426 | #[inline ] |
427 | fn deref_mut(&mut self) -> &mut Self::Target { |
428 | &mut self.0 |
429 | } |
430 | } |
431 | |
432 | impl From<libc::c_long> for ILong { |
433 | #[inline ] |
434 | fn from(v: libc::c_long) -> ILong { |
435 | ILong(v) |
436 | } |
437 | } |
438 | |
439 | impl From<ILong> for libc::c_long { |
440 | #[inline ] |
441 | fn from(v: ILong) -> libc::c_long { |
442 | v.0 |
443 | } |
444 | } |
445 | |
446 | impl PartialEq<libc::c_long> for ILong { |
447 | #[inline ] |
448 | fn eq(&self, other: &libc::c_long) -> bool { |
449 | &self.0 == other |
450 | } |
451 | } |
452 | |
453 | impl PartialEq<ILong> for libc::c_long { |
454 | #[inline ] |
455 | fn eq(&self, other: &ILong) -> bool { |
456 | self == &other.0 |
457 | } |
458 | } |
459 | |
460 | impl PartialOrd<libc::c_long> for ILong { |
461 | #[inline ] |
462 | fn partial_cmp(&self, other: &libc::c_long) -> Option<std::cmp::Ordering> { |
463 | self.0.partial_cmp(other) |
464 | } |
465 | } |
466 | |
467 | impl PartialOrd<ILong> for libc::c_long { |
468 | #[inline ] |
469 | fn partial_cmp(&self, other: &ILong) -> Option<std::cmp::Ordering> { |
470 | self.partial_cmp(&other.0) |
471 | } |
472 | } |
473 | |
474 | #[derive (Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] |
475 | pub struct ULong(pub libc::c_ulong); |
476 | |
477 | impl std::ops::Deref for ULong { |
478 | type Target = libc::c_ulong; |
479 | |
480 | #[inline ] |
481 | fn deref(&self) -> &Self::Target { |
482 | &self.0 |
483 | } |
484 | } |
485 | |
486 | impl std::ops::DerefMut for ULong { |
487 | #[inline ] |
488 | fn deref_mut(&mut self) -> &mut Self::Target { |
489 | &mut self.0 |
490 | } |
491 | } |
492 | |
493 | impl From<libc::c_ulong> for ULong { |
494 | #[inline ] |
495 | fn from(v: libc::c_ulong) -> ULong { |
496 | ULong(v) |
497 | } |
498 | } |
499 | |
500 | impl From<ULong> for libc::c_ulong { |
501 | #[inline ] |
502 | fn from(v: ULong) -> libc::c_ulong { |
503 | v.0 |
504 | } |
505 | } |
506 | |
507 | impl PartialEq<libc::c_ulong> for ULong { |
508 | #[inline ] |
509 | fn eq(&self, other: &libc::c_ulong) -> bool { |
510 | &self.0 == other |
511 | } |
512 | } |
513 | |
514 | impl PartialEq<ULong> for libc::c_ulong { |
515 | #[inline ] |
516 | fn eq(&self, other: &ULong) -> bool { |
517 | self == &other.0 |
518 | } |
519 | } |
520 | |
521 | impl PartialOrd<libc::c_ulong> for ULong { |
522 | #[inline ] |
523 | fn partial_cmp(&self, other: &libc::c_ulong) -> Option<std::cmp::Ordering> { |
524 | self.0.partial_cmp(other) |
525 | } |
526 | } |
527 | |
528 | impl PartialOrd<ULong> for libc::c_ulong { |
529 | #[inline ] |
530 | fn partial_cmp(&self, other: &ULong) -> Option<std::cmp::Ordering> { |
531 | self.partial_cmp(&other.0) |
532 | } |
533 | } |
534 | |
535 | builtin!(bool, BOOL); |
536 | builtin!(i8, I8); |
537 | builtin!(NonZeroI8, I8); |
538 | builtin!(u8, U8); |
539 | builtin!(NonZeroU8, U8); |
540 | builtin!(i32, I32); |
541 | builtin!(NonZeroI32, I32); |
542 | builtin!(u32, U32); |
543 | builtin!(NonZeroU32, U32); |
544 | builtin!(i64, I64); |
545 | builtin!(NonZeroI64, I64); |
546 | builtin!(u64, U64); |
547 | builtin!(NonZeroU64, U64); |
548 | builtin!(ILong, I_LONG); |
549 | builtin!(ULong, U_LONG); |
550 | builtin!(f32, F32); |
551 | builtin!(f64, F64); |
552 | builtin!(str, STRING); |
553 | builtin!(String, STRING); |
554 | builtin!(PathBuf, STRING); |
555 | builtin!(Path, STRING); |
556 | builtin!(Pointer, POINTER); |
557 | |
558 | impl StaticType for [&'_ str] { |
559 | #[inline ] |
560 | fn static_type() -> Type { |
561 | unsafe { from_glib(val:ffi::g_strv_get_type()) } |
562 | } |
563 | } |
564 | |
565 | impl StaticType for Vec<String> { |
566 | #[inline ] |
567 | fn static_type() -> Type { |
568 | unsafe { from_glib(val:ffi::g_strv_get_type()) } |
569 | } |
570 | } |
571 | |
572 | impl StaticType for () { |
573 | #[inline ] |
574 | fn static_type() -> Type { |
575 | Type::UNIT |
576 | } |
577 | } |
578 | |
579 | #[inline ] |
580 | pub unsafe fn instance_of<C: StaticType>(ptr: ffi::gconstpointer) -> bool { |
581 | from_glib(val:gobject_ffi::g_type_check_instance_is_a( |
582 | instance:ptr as *mut _, |
583 | <C as StaticType>::static_type().into_glib(), |
584 | )) |
585 | } |
586 | |
587 | impl FromGlib<ffi::GType> for Type { |
588 | #[inline ] |
589 | unsafe fn from_glib(val: ffi::GType) -> Self { |
590 | Self(val) |
591 | } |
592 | } |
593 | |
594 | impl IntoGlib for Type { |
595 | type GlibType = ffi::GType; |
596 | |
597 | #[inline ] |
598 | fn into_glib(self) -> ffi::GType { |
599 | self.0 |
600 | } |
601 | } |
602 | |
603 | impl<'a> ToGlibContainerFromSlice<'a, *mut ffi::GType> for Type { |
604 | type Storage = PhantomData<&'a [Type]>; |
605 | |
606 | #[inline ] |
607 | fn to_glib_none_from_slice(t: &'a [Type]) -> (*mut ffi::GType, Self::Storage) { |
608 | (t.as_ptr() as *mut ffi::GType, PhantomData) |
609 | } |
610 | |
611 | #[inline ] |
612 | fn to_glib_container_from_slice(t: &'a [Type]) -> (*mut ffi::GType, Self::Storage) { |
613 | (Self::to_glib_full_from_slice(t), PhantomData) |
614 | } |
615 | |
616 | fn to_glib_full_from_slice(t: &[Type]) -> *mut ffi::GType { |
617 | if t.is_empty() { |
618 | return ptr::null_mut(); |
619 | } |
620 | |
621 | unsafe { |
622 | let res = |
623 | ffi::g_malloc(mem::size_of::<ffi::GType>() * (t.len() + 1)) as *mut ffi::GType; |
624 | std::ptr::copy_nonoverlapping(t.as_ptr() as *const ffi::GType, res, t.len()); |
625 | *res.add(t.len()) = 0; |
626 | res |
627 | } |
628 | } |
629 | } |
630 | |
631 | impl FromGlibContainerAsVec<Type, *const ffi::GType> for Type { |
632 | unsafe fn from_glib_none_num_as_vec(ptr: *const ffi::GType, num: usize) -> Vec<Self> { |
633 | if num == 0 || ptr.is_null() { |
634 | return Vec::new(); |
635 | } |
636 | |
637 | let mut res: Vec = Vec::<Self>::with_capacity(num); |
638 | let res_ptr: *mut usize = res.as_mut_ptr() as *mut ffi::GType; |
639 | std::ptr::copy_nonoverlapping(src:ptr, dst:res_ptr, count:num); |
640 | res.set_len(new_len:num); |
641 | res |
642 | } |
643 | |
644 | unsafe fn from_glib_container_num_as_vec(_: *const ffi::GType, _: usize) -> Vec<Self> { |
645 | // Can't really free a *const |
646 | unimplemented!(); |
647 | } |
648 | |
649 | unsafe fn from_glib_full_num_as_vec(_: *const ffi::GType, _: usize) -> Vec<Self> { |
650 | // Can't really free a *const |
651 | unimplemented!(); |
652 | } |
653 | } |
654 | |
655 | impl FromGlibContainerAsVec<Type, *mut ffi::GType> for Type { |
656 | unsafe fn from_glib_none_num_as_vec(ptr: *mut ffi::GType, num: usize) -> Vec<Self> { |
657 | FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num) |
658 | } |
659 | |
660 | unsafe fn from_glib_container_num_as_vec(ptr: *mut ffi::GType, num: usize) -> Vec<Self> { |
661 | let res: Vec = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num); |
662 | ffi::g_free(mem:ptr as *mut _); |
663 | res |
664 | } |
665 | |
666 | unsafe fn from_glib_full_num_as_vec(ptr: *mut ffi::GType, num: usize) -> Vec<Self> { |
667 | FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num) |
668 | } |
669 | } |
670 | |
671 | #[cfg (test)] |
672 | mod tests { |
673 | use std::collections::{BTreeSet, HashSet}; |
674 | |
675 | use super::*; |
676 | use crate::InitiallyUnowned; |
677 | |
678 | #[test ] |
679 | fn invalid() { |
680 | let invalid = Type::INVALID; |
681 | |
682 | assert_eq!(invalid.name(), "<invalid>" ); |
683 | assert_eq!(invalid.qname(), crate::Quark::from_str("<invalid>" )); |
684 | assert!(invalid.is_a(Type::INVALID)); |
685 | assert!(!invalid.is_a(Type::STRING)); |
686 | assert_eq!(invalid.parent(), None); |
687 | assert!(invalid.children().is_empty()); |
688 | assert!(invalid.interfaces().is_empty()); |
689 | assert!(invalid.interface_prerequisites().is_empty()); |
690 | assert!(!invalid.is_valid()); |
691 | dbg!(&invalid); |
692 | } |
693 | |
694 | #[test ] |
695 | fn hash() { |
696 | // Get this first so the type is registered |
697 | let iu_type = InitiallyUnowned::static_type(); |
698 | |
699 | let set = Type::OBJECT |
700 | .children() |
701 | .iter() |
702 | .copied() |
703 | .collect::<HashSet<_>>(); |
704 | assert!(set.contains(&iu_type)); |
705 | } |
706 | |
707 | #[test ] |
708 | fn ord() { |
709 | // Get this first so the type is registered |
710 | let iu_type = InitiallyUnowned::static_type(); |
711 | assert!(Type::OBJECT < iu_type); |
712 | |
713 | let set = Type::OBJECT |
714 | .children() |
715 | .iter() |
716 | .copied() |
717 | .collect::<BTreeSet<_>>(); |
718 | assert!(set.contains(&iu_type)); |
719 | } |
720 | } |
721 | |