| 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 | |