1use glib_sys;
8use gobject_sys;
9use translate::{
10 from_glib, from_glib_none, FromGlib, FromGlibContainerAsVec, ToGlib, ToGlibContainerFromSlice,
11 ToGlibPtr, ToGlibPtrMut,
12};
13use value::{FromValue, FromValueOptional, SetValue, Value};
14
15use std::fmt;
16use std::mem;
17use std::ptr;
18
19#[derive(Clone, Copy, PartialEq, Eq)]
21pub enum Type {
22 Invalid,
24 Unit,
26 I8,
28 U8,
30 Bool,
32 I32,
34 U32,
36 ILong,
38 ULong,
40 I64,
42 U64,
44 F32,
46 F64,
48 String,
50 Pointer,
52 Variant,
54 BaseInterface,
56 BaseEnum,
58 BaseFlags,
60 BaseBoxed,
62 BaseParamSpec,
64 BaseObject,
66 Other(usize),
68}
69
70impl Type {
71 pub fn name(&self) -> String {
72 unsafe { from_glib_none(gobject_sys::g_type_name(self.to_glib())) }
73 }
74
75 pub fn qname(&self) -> ::Quark {
76 unsafe { from_glib(gobject_sys::g_type_qname(self.to_glib())) }
77 }
78
79 pub fn is_a(&self, other: &Type) -> bool {
80 unsafe { from_glib(gobject_sys::g_type_is_a(self.to_glib(), other.to_glib())) }
81 }
82
83 pub fn parent(&self) -> Option<Self> {
84 unsafe {
85 let parent = gobject_sys::g_type_parent(self.to_glib());
86 if parent == gobject_sys::G_TYPE_INVALID {
87 None
88 } else {
89 Some(from_glib(parent))
90 }
91 }
92 }
93
94 pub fn children(&self) -> Vec<Self> {
95 unsafe {
96 let mut n_children = 0u32;
97 let children = gobject_sys::g_type_children(self.to_glib(), &mut n_children);
98
99 FromGlibContainerAsVec::from_glib_full_num_as_vec(children, n_children as usize)
100 }
101 }
102
103 pub fn interfaces(&self) -> Vec<Self> {
104 unsafe {
105 let mut n_interfaces = 0u32;
106 let interfaces = gobject_sys::g_type_interfaces(self.to_glib(), &mut n_interfaces);
107
108 FromGlibContainerAsVec::from_glib_full_num_as_vec(interfaces, n_interfaces as usize)
109 }
110 }
111 pub fn interface_prerequisites(&self) -> Vec<Self> {
112 unsafe {
113 let mut n_prereqs = 0u32;
114 let prereqs =
115 gobject_sys::g_type_interface_prerequisites(self.to_glib(), &mut n_prereqs);
116
117 FromGlibContainerAsVec::from_glib_full_num_as_vec(prereqs, n_prereqs as usize)
118 }
119 }
120
121 pub fn from_name<'a, P: Into<&'a str>>(name: P) -> Option<Self> {
122 unsafe {
123 let type_ = gobject_sys::g_type_from_name(name.into().to_glib_none().0);
124 if type_ == gobject_sys::G_TYPE_INVALID {
125 None
126 } else {
127 Some(from_glib(type_))
128 }
129 }
130 }
131}
132
133impl fmt::Debug for Type {
134 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135 f.write_str(&self.name())
136 }
137}
138
139impl fmt::Display for Type {
140 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
141 f.write_str(&self.name())
142 }
143}
144
145pub trait StaticType {
147 fn static_type() -> Type;
149}
150
151impl StaticType for Type {
152 fn static_type() -> Type {
153 unsafe { from_glib(gobject_sys::g_gtype_get_type()) }
154 }
155}
156
157impl<'a> FromValueOptional<'a> for Type {
158 unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
159 Some(from_glib(gobject_sys::g_value_get_gtype(
160 value.to_glib_none().0,
161 )))
162 }
163}
164
165impl<'a> FromValue<'a> for Type {
166 unsafe fn from_value(value: &'a Value) -> Self {
167 from_glib(gobject_sys::g_value_get_gtype(value.to_glib_none().0))
168 }
169}
170
171impl SetValue for Type {
172 unsafe fn set_value(value: &mut Value, this: &Self) {
173 gobject_sys::g_value_set_gtype(value.to_glib_none_mut().0, this.to_glib())
174 }
175}
176
177impl<'a, T: ?Sized + StaticType> StaticType for &'a T {
178 fn static_type() -> Type {
179 T::static_type()
180 }
181}
182
183impl<'a, T: ?Sized + StaticType> StaticType for &'a mut T {
184 fn static_type() -> Type {
185 T::static_type()
186 }
187}
188
189macro_rules! builtin {
190 ($name:ident, $val:ident) => {
191 impl StaticType for $name {
192 fn static_type() -> Type {
193 Type::$val
194 }
195 }
196 };
197}
198
199builtin!(bool, Bool);
200builtin!(i8, I8);
201builtin!(u8, U8);
202builtin!(i32, I32);
203builtin!(u32, U32);
204builtin!(i64, I64);
205builtin!(u64, U64);
206builtin!(f32, F32);
207builtin!(f64, F64);
208builtin!(str, String);
209builtin!(String, String);
210
211impl<'a> StaticType for [&'a str] {
212 fn static_type() -> Type {
213 unsafe { from_glib(glib_sys::g_strv_get_type()) }
214 }
215}
216
217impl StaticType for Vec<String> {
218 fn static_type() -> Type {
219 unsafe { from_glib(glib_sys::g_strv_get_type()) }
220 }
221}
222
223#[inline]
224pub unsafe fn instance_of<C: StaticType>(ptr: glib_sys::gconstpointer) -> bool {
225 from_glib(gobject_sys::g_type_check_instance_is_a(
226 ptr as *mut _,
227 <C as StaticType>::static_type().to_glib(),
228 ))
229}
230
231impl FromGlib<glib_sys::GType> for Type {
232 #[inline]
233 fn from_glib(val: glib_sys::GType) -> Type {
234 use self::Type::*;
235 match val {
236 gobject_sys::G_TYPE_INVALID => Invalid,
237 gobject_sys::G_TYPE_NONE => Unit,
238 gobject_sys::G_TYPE_INTERFACE => BaseInterface,
239 gobject_sys::G_TYPE_CHAR => I8,
240 gobject_sys::G_TYPE_UCHAR => U8,
241 gobject_sys::G_TYPE_BOOLEAN => Bool,
242 gobject_sys::G_TYPE_INT => I32,
243 gobject_sys::G_TYPE_UINT => U32,
244 gobject_sys::G_TYPE_LONG => ILong,
245 gobject_sys::G_TYPE_ULONG => ULong,
246 gobject_sys::G_TYPE_INT64 => I64,
247 gobject_sys::G_TYPE_UINT64 => U64,
248 gobject_sys::G_TYPE_ENUM => BaseEnum,
249 gobject_sys::G_TYPE_FLAGS => BaseFlags,
250 gobject_sys::G_TYPE_FLOAT => F32,
251 gobject_sys::G_TYPE_DOUBLE => F64,
252 gobject_sys::G_TYPE_STRING => String,
253 gobject_sys::G_TYPE_POINTER => Pointer,
254 gobject_sys::G_TYPE_BOXED => BaseBoxed,
255 gobject_sys::G_TYPE_PARAM => BaseParamSpec,
256 gobject_sys::G_TYPE_OBJECT => BaseObject,
257 gobject_sys::G_TYPE_VARIANT => Variant,
258 x => Other(x as usize),
259 }
260 }
261}
262
263impl ToGlib for Type {
264 type GlibType = glib_sys::GType;
265
266 fn to_glib(&self) -> glib_sys::GType {
267 use self::Type::*;
268 match *self {
269 Invalid => gobject_sys::G_TYPE_INVALID,
270 Unit => gobject_sys::G_TYPE_NONE,
271 BaseInterface => gobject_sys::G_TYPE_INTERFACE,
272 I8 => gobject_sys::G_TYPE_CHAR,
273 U8 => gobject_sys::G_TYPE_UCHAR,
274 Bool => gobject_sys::G_TYPE_BOOLEAN,
275 I32 => gobject_sys::G_TYPE_INT,
276 U32 => gobject_sys::G_TYPE_UINT,
277 ILong => gobject_sys::G_TYPE_LONG,
278 ULong => gobject_sys::G_TYPE_ULONG,
279 I64 => gobject_sys::G_TYPE_INT64,
280 U64 => gobject_sys::G_TYPE_UINT64,
281 BaseEnum => gobject_sys::G_TYPE_ENUM,
282 BaseFlags => gobject_sys::G_TYPE_FLAGS,
283 F32 => gobject_sys::G_TYPE_FLOAT,
284 F64 => gobject_sys::G_TYPE_DOUBLE,
285 String => gobject_sys::G_TYPE_STRING,
286 Pointer => gobject_sys::G_TYPE_POINTER,
287 BaseBoxed => gobject_sys::G_TYPE_BOXED,
288 BaseParamSpec => gobject_sys::G_TYPE_PARAM,
289 BaseObject => gobject_sys::G_TYPE_OBJECT,
290 Variant => gobject_sys::G_TYPE_VARIANT,
291 Other(x) => x as glib_sys::GType,
292 }
293 }
294}
295
296impl<'a> ToGlibContainerFromSlice<'a, *mut glib_sys::GType> for Type {
297 type Storage = Option<Vec<glib_sys::GType>>;
298
299 fn to_glib_none_from_slice(t: &'a [Type]) -> (*mut glib_sys::GType, Self::Storage) {
300 let mut vec = t.iter().map(ToGlib::to_glib).collect::<Vec<_>>();
301
302 (vec.as_mut_ptr(), Some(vec))
303 }
304
305 fn to_glib_container_from_slice(t: &'a [Type]) -> (*mut glib_sys::GType, Self::Storage) {
306 (Self::to_glib_full_from_slice(t), None)
307 }
308
309 fn to_glib_full_from_slice(t: &[Type]) -> *mut glib_sys::GType {
310 if t.is_empty() {
311 return ptr::null_mut();
312 }
313
314 unsafe {
315 let res = glib_sys::g_malloc0(mem::size_of::<glib_sys::GType>() * (t.len() + 1))
316 as *mut glib_sys::GType;
317 for (i, v) in t.iter().enumerate() {
318 *res.add(i) = v.to_glib();
319 }
320 res
321 }
322 }
323}
324
325impl FromGlibContainerAsVec<Type, *const glib_sys::GType> for Type {
326 unsafe fn from_glib_none_num_as_vec(ptr: *const glib_sys::GType, num: usize) -> Vec<Self> {
327 if num == 0 || ptr.is_null() {
328 return Vec::new();
329 }
330
331 let mut res = Vec::with_capacity(num);
332 for i in 0..num {
333 res.push(from_glib(*ptr.add(i)));
334 }
335 res
336 }
337
338 unsafe fn from_glib_container_num_as_vec(_: *const glib_sys::GType, _: usize) -> Vec<Self> {
339 unimplemented!();
341 }
342
343 unsafe fn from_glib_full_num_as_vec(_: *const glib_sys::GType, _: usize) -> Vec<Self> {
344 unimplemented!();
346 }
347}
348
349impl FromGlibContainerAsVec<Type, *mut glib_sys::GType> for Type {
350 unsafe fn from_glib_none_num_as_vec(ptr: *mut glib_sys::GType, num: usize) -> Vec<Self> {
351 FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num)
352 }
353
354 unsafe fn from_glib_container_num_as_vec(ptr: *mut glib_sys::GType, num: usize) -> Vec<Self> {
355 let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
356 glib_sys::g_free(ptr as *mut _);
357 res
358 }
359
360 unsafe fn from_glib_full_num_as_vec(ptr: *mut glib_sys::GType, num: usize) -> Vec<Self> {
361 FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num)
362 }
363}