1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2014, 2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use gobject as ffi;
use object::ObjectType;
use util::is_true;

use std::ffi::CStr;
use std::fmt;
use std::str;

pub mod raw {
    // Support macro g_type_register_box! by reexporting GType in this crate
    pub type GType = ::gtypes::GType;
}

#[derive(Copy, Clone, Eq, PartialEq)]
pub struct GType(raw::GType);

macro_rules! g_type_fundamental {
    ($num:expr) => (GType($num << 2));
}

pub const INVALID   : GType = g_type_fundamental!(0);
pub const NONE      : GType = g_type_fundamental!(1);
pub const INTERFACE : GType = g_type_fundamental!(2);
pub const CHAR      : GType = g_type_fundamental!(3);
pub const UCHAR     : GType = g_type_fundamental!(4);
pub const BOOLEAN   : GType = g_type_fundamental!(5);
pub const INT       : GType = g_type_fundamental!(6);
pub const UINT      : GType = g_type_fundamental!(7);
pub const LONG      : GType = g_type_fundamental!(8);
pub const ULONG     : GType = g_type_fundamental!(9);
pub const INT64     : GType = g_type_fundamental!(10);
pub const UINT64    : GType = g_type_fundamental!(11);
pub const ENUM      : GType = g_type_fundamental!(12);
pub const FLAGS     : GType = g_type_fundamental!(13);
pub const FLOAT     : GType = g_type_fundamental!(14);
pub const DOUBLE    : GType = g_type_fundamental!(15);
pub const STRING    : GType = g_type_fundamental!(16);
pub const POINTER   : GType = g_type_fundamental!(17);
pub const BOXED     : GType = g_type_fundamental!(18);
pub const PARAM     : GType = g_type_fundamental!(19);
pub const OBJECT    : GType = g_type_fundamental!(20);
pub const VARIANT   : GType = g_type_fundamental!(21);

impl GType {

    #[inline]
    pub unsafe fn from_raw(type_id: raw::GType) -> GType {
        GType(type_id)
    }

    #[inline]
    pub fn to_raw(&self) -> raw::GType {
        let GType(type_id) = *self;
        type_id
    }

    pub fn name(&self) -> &str {
        unsafe {
            let name = CStr::from_ptr(ffi::g_type_name(self.to_raw()));
            // A valid GType name is restricted to ASCII characters
            str::from_utf8_unchecked(name.to_bytes())
        }
    }
}

impl fmt::Debug for GType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "GType {{ id: {}, name: \"{}\" }}", self.to_raw(), self.name())
    }
}

pub fn check_instance_is_a<T>(inst: &T, type_id: GType) -> bool
    where T: ObjectType
{
    let raw_inst = inst as *const T;
    let raw_type = type_id.to_raw();
    is_true(unsafe {
        ffi::g_type_check_instance_is_a(raw_inst as *mut ffi::GTypeInstance,
                                        raw_type)
    })
}