@@ -12,30 +12,10 @@ use std::ptr;
12
12
13
13
/// A newly registered `glib::Type` that is currently still being initialized.
14
14
///
15
- /// This allows running additional type-setup functions, e.g. for implementing
16
- /// interfaces on the type.
15
+ /// This allows running additional type-setup functions.
17
16
#[ derive( Debug , PartialEq , Eq ) ]
18
17
pub struct InitializingType < T > ( pub ( crate ) Type , pub ( crate ) marker:: PhantomData < * const T > ) ;
19
18
20
- impl < T : ObjectSubclass > InitializingType < T > {
21
- /// Adds an interface implementation for `I` to the type.
22
- #[ doc( alias = "g_type_add_interface_static" ) ]
23
- pub fn add_interface < I : IsImplementable < T > > ( & mut self ) {
24
- unsafe {
25
- let iface_info = gobject_ffi:: GInterfaceInfo {
26
- interface_init : Some ( I :: interface_init) ,
27
- interface_finalize : None ,
28
- interface_data : ptr:: null_mut ( ) ,
29
- } ;
30
- gobject_ffi:: g_type_add_interface_static (
31
- self . 0 . to_glib ( ) ,
32
- I :: static_type ( ) . to_glib ( ) ,
33
- & iface_info,
34
- ) ;
35
- }
36
- }
37
- }
38
-
39
19
impl < T > ToGlib for InitializingType < T > {
40
20
type GlibType = ffi:: GType ;
41
21
@@ -128,6 +108,103 @@ pub unsafe trait IsImplementable<T: ObjectSubclass>: StaticType {
128
108
unsafe extern "C" fn interface_init ( iface : ffi:: gpointer , _iface_data : ffi:: gpointer ) ;
129
109
}
130
110
111
+ /// Trait for a type list of interfaces.
112
+ pub trait InterfaceList < T > {
113
+ /// Returns the list of types and corresponding interface infos for this list.
114
+ fn iface_infos ( ) -> Vec < ( ffi:: GType , gobject_ffi:: GInterfaceInfo ) > ;
115
+ }
116
+
117
+ impl < T : ObjectSubclass > InterfaceList < T > for ( ) {
118
+ fn iface_infos ( ) -> Vec < ( ffi:: GType , gobject_ffi:: GInterfaceInfo ) > {
119
+ vec ! [ ]
120
+ }
121
+ }
122
+
123
+ impl < T : ObjectSubclass , A : IsImplementable < T > > InterfaceList < T > for ( A , ) {
124
+ fn iface_infos ( ) -> Vec < ( ffi:: GType , gobject_ffi:: GInterfaceInfo ) > {
125
+ vec ! [ (
126
+ A :: static_type( ) . to_glib( ) ,
127
+ gobject_ffi:: GInterfaceInfo {
128
+ interface_init: Some ( A :: interface_init) ,
129
+ interface_finalize: None ,
130
+ interface_data: ptr:: null_mut( ) ,
131
+ } ,
132
+ ) ]
133
+ }
134
+ }
135
+
136
+ // Generates all the InterfaceList impls for interface_lists of arbitrary sizes based on a list of type
137
+ // parameters like A B C. It would generate the impl then for (A, B) and (A, B, C).
138
+ macro_rules! interface_list_trait(
139
+ ( $name1: ident, $name2: ident, $( $name: ident) ,* ) => (
140
+ interface_list_trait!( __impl $name1, $name2; $( $name) ,* ) ;
141
+ ) ;
142
+ ( __impl $( $name: ident) ,+; $name1: ident, $( $name2: ident) ,* ) => (
143
+ interface_list_trait_impl!( $( $name) ,+) ;
144
+ interface_list_trait!( __impl $( $name) ,+ , $name1; $( $name2) ,* ) ;
145
+ ) ;
146
+ ( __impl $( $name: ident) ,+; $name1: ident) => (
147
+ interface_list_trait_impl!( $( $name) ,+) ;
148
+ interface_list_trait_impl!( $( $name) ,+, $name1) ;
149
+ ) ;
150
+ ) ;
151
+
152
+ // Generates the impl block for InterfaceList on interface_lists or arbitrary sizes based on its
153
+ // arguments. Takes a list of type parameters as parameters, e.g. A B C
154
+ // and then implements the trait on (A, B, C).
155
+ macro_rules! interface_list_trait_impl(
156
+ ( $( $name: ident) ,+) => (
157
+ impl <T : ObjectSubclass , $( $name: IsImplementable <T >) ,+> InterfaceList <T > for ( $( $name) ,+ ) {
158
+ fn iface_infos( ) -> Vec <( ffi:: GType , gobject_ffi:: GInterfaceInfo ) > {
159
+ let mut types = Vec :: new( ) ;
160
+ interface_list_trait_inner!( types, $( $name) +)
161
+ }
162
+ }
163
+ ) ;
164
+ ) ;
165
+
166
+ // Generates the inner part of the InterfaceList::types() implementation, which will
167
+ // basically look as follows:
168
+ //
169
+ // let mut types = Vec::new();
170
+ //
171
+ // types.push((A::static_type().to_glib(), ...));
172
+ // types.push((B::static_type().to_glib(), ...));
173
+ // [...]
174
+ // types.push((Z::static_type().to_glib(), ...));
175
+ //
176
+ // types
177
+ macro_rules! interface_list_trait_inner(
178
+ ( $types: ident, $head: ident $( $id: ident) +) => ( {
179
+ $types. push(
180
+ (
181
+ $head:: static_type( ) . to_glib( ) ,
182
+ gobject_ffi:: GInterfaceInfo {
183
+ interface_init: Some ( $head:: interface_init) ,
184
+ interface_finalize: None ,
185
+ interface_data: ptr:: null_mut( ) ,
186
+ } ,
187
+ )
188
+ ) ;
189
+ interface_list_trait_inner!( $types, $( $id) +)
190
+ } ) ;
191
+ ( $types: ident, $head: ident) => ( {
192
+ $types. push(
193
+ (
194
+ $head:: static_type( ) . to_glib( ) ,
195
+ gobject_ffi:: GInterfaceInfo {
196
+ interface_init: Some ( $head:: interface_init) ,
197
+ interface_finalize: None ,
198
+ interface_data: ptr:: null_mut( ) ,
199
+ } ,
200
+ )
201
+ ) ;
202
+ $types
203
+ } ) ;
204
+ ) ;
205
+
206
+ interface_list_trait ! ( A , B , C , D , E , F , G , H , I , J , K , L , M , N , O , P , Q , R , S ) ;
207
+
131
208
/// Type-specific data that is filled in during type creation.
132
209
pub struct TypeData {
133
210
#[ doc( hidden) ]
@@ -257,6 +334,9 @@ pub trait ObjectSubclass: Sized + 'static {
257
334
+ FromGlibPtrBorrow < * mut <Self :: ParentType as ObjectType >:: GlibType >
258
335
+ FromGlibPtrNone < * mut <Self :: ParentType as ObjectType >:: GlibType > ;
259
336
337
+ /// List of interfaces implemented by this type.
338
+ type Interfaces : InterfaceList < Self > ;
339
+
260
340
/// The C instance struct.
261
341
///
262
342
/// See [`simple::InstanceStruct`] for an basic instance struct that should be
@@ -529,6 +609,11 @@ where
529
609
} ;
530
610
( * data. as_mut ( ) ) . private_offset = private_offset as isize ;
531
611
612
+ let iface_types = T :: Interfaces :: iface_infos ( ) ;
613
+ for ( iface_type, iface_info) in iface_types {
614
+ gobject_ffi:: g_type_add_interface_static ( type_. to_glib ( ) , iface_type, & iface_info) ;
615
+ }
616
+
532
617
T :: type_init ( & mut InitializingType :: < T > ( type_, marker:: PhantomData ) ) ;
533
618
534
619
type_
0 commit comments