1 // This file was generated by gir (https://github.com/gtk-rs/gir)
2 // from gir-files (https://github.com/gtk-rs/gir-files)
3 // DO NOT EDIT
4 
5 use gobject_sys::*;
6 use std::env;
7 use std::error::Error;
8 use std::ffi::OsString;
9 use std::mem::{align_of, size_of};
10 use std::path::Path;
11 use std::process::Command;
12 use std::str;
13 use tempfile::Builder;
14 
15 static PACKAGES: &[&str] = &["gobject-2.0"];
16 
17 #[derive(Clone, Debug)]
18 struct Compiler {
19     pub args: Vec<String>,
20 }
21 
22 impl Compiler {
new() -> Result<Self, Box<dyn Error>>23     pub fn new() -> Result<Self, Box<dyn Error>> {
24         let mut args = get_var("CC", "cc")?;
25         args.push("-Wno-deprecated-declarations".to_owned());
26         // For _Generic
27         args.push("-std=c11".to_owned());
28         // For %z support in printf when using MinGW.
29         args.push("-D__USE_MINGW_ANSI_STDIO".to_owned());
30         args.extend(get_var("CFLAGS", "")?);
31         args.extend(get_var("CPPFLAGS", "")?);
32         args.extend(pkg_config_cflags(PACKAGES)?);
33         Ok(Self { args })
34     }
35 
compile(&self, src: &Path, out: &Path) -> Result<(), Box<dyn Error>>36     pub fn compile(&self, src: &Path, out: &Path) -> Result<(), Box<dyn Error>> {
37         let mut cmd = self.to_command();
38         cmd.arg(src);
39         cmd.arg("-o");
40         cmd.arg(out);
41         let status = cmd.spawn()?.wait()?;
42         if !status.success() {
43             return Err(format!("compilation command {:?} failed, {}", &cmd, status).into());
44         }
45         Ok(())
46     }
47 
to_command(&self) -> Command48     fn to_command(&self) -> Command {
49         let mut cmd = Command::new(&self.args[0]);
50         cmd.args(&self.args[1..]);
51         cmd
52     }
53 }
54 
get_var(name: &str, default: &str) -> Result<Vec<String>, Box<dyn Error>>55 fn get_var(name: &str, default: &str) -> Result<Vec<String>, Box<dyn Error>> {
56     match env::var(name) {
57         Ok(value) => Ok(shell_words::split(&value)?),
58         Err(env::VarError::NotPresent) => Ok(shell_words::split(default)?),
59         Err(err) => Err(format!("{} {}", name, err).into()),
60     }
61 }
62 
pkg_config_cflags(packages: &[&str]) -> Result<Vec<String>, Box<dyn Error>>63 fn pkg_config_cflags(packages: &[&str]) -> Result<Vec<String>, Box<dyn Error>> {
64     if packages.is_empty() {
65         return Ok(Vec::new());
66     }
67     let pkg_config = env::var_os("PKG_CONFIG").unwrap_or_else(|| OsString::from("pkg-config"));
68     let mut cmd = Command::new(pkg_config);
69     cmd.arg("--cflags");
70     cmd.args(packages);
71     let out = cmd.output()?;
72     if !out.status.success() {
73         return Err(format!("command {:?} returned {}", &cmd, out.status).into());
74     }
75     let stdout = str::from_utf8(&out.stdout)?;
76     Ok(shell_words::split(stdout.trim())?)
77 }
78 
79 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
80 struct Layout {
81     size: usize,
82     alignment: usize,
83 }
84 
85 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
86 struct Results {
87     /// Number of successfully completed tests.
88     passed: usize,
89     /// Total number of failed tests (including those that failed to compile).
90     failed: usize,
91 }
92 
93 impl Results {
record_passed(&mut self)94     fn record_passed(&mut self) {
95         self.passed += 1;
96     }
record_failed(&mut self)97     fn record_failed(&mut self) {
98         self.failed += 1;
99     }
summary(&self) -> String100     fn summary(&self) -> String {
101         format!("{} passed; {} failed", self.passed, self.failed)
102     }
expect_total_success(&self)103     fn expect_total_success(&self) {
104         if self.failed == 0 {
105             println!("OK: {}", self.summary());
106         } else {
107             panic!("FAILED: {}", self.summary());
108         };
109     }
110 }
111 
112 #[test]
cross_validate_constants_with_c()113 fn cross_validate_constants_with_c() {
114     let mut c_constants: Vec<(String, String)> = Vec::new();
115 
116     for l in get_c_output("constant").unwrap().lines() {
117         let mut words = l.trim().split(';');
118         let name = words.next().expect("Failed to parse name").to_owned();
119         let value = words
120             .next()
121             .and_then(|s| s.parse().ok())
122             .expect("Failed to parse value");
123         c_constants.push((name, value));
124     }
125 
126     let mut results = Results::default();
127 
128     for ((rust_name, rust_value), (c_name, c_value)) in
129         RUST_CONSTANTS.iter().zip(c_constants.iter())
130     {
131         if rust_name != c_name {
132             results.record_failed();
133             eprintln!("Name mismatch:\nRust: {:?}\nC:    {:?}", rust_name, c_name,);
134             continue;
135         }
136 
137         if rust_value != c_value {
138             results.record_failed();
139             eprintln!(
140                 "Constant value mismatch for {}\nRust: {:?}\nC:    {:?}",
141                 rust_name, rust_value, &c_value
142             );
143             continue;
144         }
145 
146         results.record_passed();
147     }
148 
149     results.expect_total_success();
150 }
151 
152 #[test]
cross_validate_layout_with_c()153 fn cross_validate_layout_with_c() {
154     let mut c_layouts = Vec::new();
155 
156     for l in get_c_output("layout").unwrap().lines() {
157         let mut words = l.trim().split(';');
158         let name = words.next().expect("Failed to parse name").to_owned();
159         let size = words
160             .next()
161             .and_then(|s| s.parse().ok())
162             .expect("Failed to parse size");
163         let alignment = words
164             .next()
165             .and_then(|s| s.parse().ok())
166             .expect("Failed to parse alignment");
167         c_layouts.push((name, Layout { size, alignment }));
168     }
169 
170     let mut results = Results::default();
171 
172     for ((rust_name, rust_layout), (c_name, c_layout)) in RUST_LAYOUTS.iter().zip(c_layouts.iter())
173     {
174         if rust_name != c_name {
175             results.record_failed();
176             eprintln!("Name mismatch:\nRust: {:?}\nC:    {:?}", rust_name, c_name,);
177             continue;
178         }
179 
180         if rust_layout != c_layout {
181             results.record_failed();
182             eprintln!(
183                 "Layout mismatch for {}\nRust: {:?}\nC:    {:?}",
184                 rust_name, rust_layout, &c_layout
185             );
186             continue;
187         }
188 
189         results.record_passed();
190     }
191 
192     results.expect_total_success();
193 }
194 
get_c_output(name: &str) -> Result<String, Box<dyn Error>>195 fn get_c_output(name: &str) -> Result<String, Box<dyn Error>> {
196     let tmpdir = Builder::new().prefix("abi").tempdir()?;
197     let exe = tmpdir.path().join(name);
198     let c_file = Path::new("tests").join(name).with_extension("c");
199 
200     let cc = Compiler::new().expect("configured compiler");
201     cc.compile(&c_file, &exe)?;
202 
203     let mut abi_cmd = Command::new(exe);
204     let output = abi_cmd.output()?;
205     if !output.status.success() {
206         return Err(format!("command {:?} failed, {:?}", &abi_cmd, &output).into());
207     }
208 
209     Ok(String::from_utf8(output.stdout)?)
210 }
211 
212 const RUST_LAYOUTS: &[(&str, Layout)] = &[
213     (
214         "GBindingFlags",
215         Layout {
216             size: size_of::<GBindingFlags>(),
217             alignment: align_of::<GBindingFlags>(),
218         },
219     ),
220     (
221         "GClosureNotifyData",
222         Layout {
223             size: size_of::<GClosureNotifyData>(),
224             alignment: align_of::<GClosureNotifyData>(),
225         },
226     ),
227     (
228         "GConnectFlags",
229         Layout {
230             size: size_of::<GConnectFlags>(),
231             alignment: align_of::<GConnectFlags>(),
232         },
233     ),
234     (
235         "GEnumClass",
236         Layout {
237             size: size_of::<GEnumClass>(),
238             alignment: align_of::<GEnumClass>(),
239         },
240     ),
241     (
242         "GEnumValue",
243         Layout {
244             size: size_of::<GEnumValue>(),
245             alignment: align_of::<GEnumValue>(),
246         },
247     ),
248     (
249         "GFlagsClass",
250         Layout {
251             size: size_of::<GFlagsClass>(),
252             alignment: align_of::<GFlagsClass>(),
253         },
254     ),
255     (
256         "GFlagsValue",
257         Layout {
258             size: size_of::<GFlagsValue>(),
259             alignment: align_of::<GFlagsValue>(),
260         },
261     ),
262     (
263         "GInitiallyUnowned",
264         Layout {
265             size: size_of::<GInitiallyUnowned>(),
266             alignment: align_of::<GInitiallyUnowned>(),
267         },
268     ),
269     (
270         "GInitiallyUnownedClass",
271         Layout {
272             size: size_of::<GInitiallyUnownedClass>(),
273             alignment: align_of::<GInitiallyUnownedClass>(),
274         },
275     ),
276     (
277         "GInterfaceInfo",
278         Layout {
279             size: size_of::<GInterfaceInfo>(),
280             alignment: align_of::<GInterfaceInfo>(),
281         },
282     ),
283     (
284         "GObject",
285         Layout {
286             size: size_of::<GObject>(),
287             alignment: align_of::<GObject>(),
288         },
289     ),
290     (
291         "GObjectClass",
292         Layout {
293             size: size_of::<GObjectClass>(),
294             alignment: align_of::<GObjectClass>(),
295         },
296     ),
297     (
298         "GObjectConstructParam",
299         Layout {
300             size: size_of::<GObjectConstructParam>(),
301             alignment: align_of::<GObjectConstructParam>(),
302         },
303     ),
304     (
305         "GParamFlags",
306         Layout {
307             size: size_of::<GParamFlags>(),
308             alignment: align_of::<GParamFlags>(),
309         },
310     ),
311     (
312         "GParamSpec",
313         Layout {
314             size: size_of::<GParamSpec>(),
315             alignment: align_of::<GParamSpec>(),
316         },
317     ),
318     (
319         "GParamSpecBoolean",
320         Layout {
321             size: size_of::<GParamSpecBoolean>(),
322             alignment: align_of::<GParamSpecBoolean>(),
323         },
324     ),
325     (
326         "GParamSpecBoxed",
327         Layout {
328             size: size_of::<GParamSpecBoxed>(),
329             alignment: align_of::<GParamSpecBoxed>(),
330         },
331     ),
332     (
333         "GParamSpecChar",
334         Layout {
335             size: size_of::<GParamSpecChar>(),
336             alignment: align_of::<GParamSpecChar>(),
337         },
338     ),
339     (
340         "GParamSpecClass",
341         Layout {
342             size: size_of::<GParamSpecClass>(),
343             alignment: align_of::<GParamSpecClass>(),
344         },
345     ),
346     (
347         "GParamSpecDouble",
348         Layout {
349             size: size_of::<GParamSpecDouble>(),
350             alignment: align_of::<GParamSpecDouble>(),
351         },
352     ),
353     (
354         "GParamSpecEnum",
355         Layout {
356             size: size_of::<GParamSpecEnum>(),
357             alignment: align_of::<GParamSpecEnum>(),
358         },
359     ),
360     (
361         "GParamSpecFlags",
362         Layout {
363             size: size_of::<GParamSpecFlags>(),
364             alignment: align_of::<GParamSpecFlags>(),
365         },
366     ),
367     (
368         "GParamSpecFloat",
369         Layout {
370             size: size_of::<GParamSpecFloat>(),
371             alignment: align_of::<GParamSpecFloat>(),
372         },
373     ),
374     (
375         "GParamSpecGType",
376         Layout {
377             size: size_of::<GParamSpecGType>(),
378             alignment: align_of::<GParamSpecGType>(),
379         },
380     ),
381     (
382         "GParamSpecInt",
383         Layout {
384             size: size_of::<GParamSpecInt>(),
385             alignment: align_of::<GParamSpecInt>(),
386         },
387     ),
388     (
389         "GParamSpecInt64",
390         Layout {
391             size: size_of::<GParamSpecInt64>(),
392             alignment: align_of::<GParamSpecInt64>(),
393         },
394     ),
395     (
396         "GParamSpecLong",
397         Layout {
398             size: size_of::<GParamSpecLong>(),
399             alignment: align_of::<GParamSpecLong>(),
400         },
401     ),
402     (
403         "GParamSpecObject",
404         Layout {
405             size: size_of::<GParamSpecObject>(),
406             alignment: align_of::<GParamSpecObject>(),
407         },
408     ),
409     (
410         "GParamSpecOverride",
411         Layout {
412             size: size_of::<GParamSpecOverride>(),
413             alignment: align_of::<GParamSpecOverride>(),
414         },
415     ),
416     (
417         "GParamSpecParam",
418         Layout {
419             size: size_of::<GParamSpecParam>(),
420             alignment: align_of::<GParamSpecParam>(),
421         },
422     ),
423     (
424         "GParamSpecPointer",
425         Layout {
426             size: size_of::<GParamSpecPointer>(),
427             alignment: align_of::<GParamSpecPointer>(),
428         },
429     ),
430     (
431         "GParamSpecTypeInfo",
432         Layout {
433             size: size_of::<GParamSpecTypeInfo>(),
434             alignment: align_of::<GParamSpecTypeInfo>(),
435         },
436     ),
437     (
438         "GParamSpecUChar",
439         Layout {
440             size: size_of::<GParamSpecUChar>(),
441             alignment: align_of::<GParamSpecUChar>(),
442         },
443     ),
444     (
445         "GParamSpecUInt",
446         Layout {
447             size: size_of::<GParamSpecUInt>(),
448             alignment: align_of::<GParamSpecUInt>(),
449         },
450     ),
451     (
452         "GParamSpecUInt64",
453         Layout {
454             size: size_of::<GParamSpecUInt64>(),
455             alignment: align_of::<GParamSpecUInt64>(),
456         },
457     ),
458     (
459         "GParamSpecULong",
460         Layout {
461             size: size_of::<GParamSpecULong>(),
462             alignment: align_of::<GParamSpecULong>(),
463         },
464     ),
465     (
466         "GParamSpecUnichar",
467         Layout {
468             size: size_of::<GParamSpecUnichar>(),
469             alignment: align_of::<GParamSpecUnichar>(),
470         },
471     ),
472     (
473         "GParamSpecValueArray",
474         Layout {
475             size: size_of::<GParamSpecValueArray>(),
476             alignment: align_of::<GParamSpecValueArray>(),
477         },
478     ),
479     (
480         "GParamSpecVariant",
481         Layout {
482             size: size_of::<GParamSpecVariant>(),
483             alignment: align_of::<GParamSpecVariant>(),
484         },
485     ),
486     (
487         "GParameter",
488         Layout {
489             size: size_of::<GParameter>(),
490             alignment: align_of::<GParameter>(),
491         },
492     ),
493     (
494         "GSignalCMarshaller",
495         Layout {
496             size: size_of::<GSignalCMarshaller>(),
497             alignment: align_of::<GSignalCMarshaller>(),
498         },
499     ),
500     (
501         "GSignalFlags",
502         Layout {
503             size: size_of::<GSignalFlags>(),
504             alignment: align_of::<GSignalFlags>(),
505         },
506     ),
507     (
508         "GSignalInvocationHint",
509         Layout {
510             size: size_of::<GSignalInvocationHint>(),
511             alignment: align_of::<GSignalInvocationHint>(),
512         },
513     ),
514     (
515         "GSignalMatchType",
516         Layout {
517             size: size_of::<GSignalMatchType>(),
518             alignment: align_of::<GSignalMatchType>(),
519         },
520     ),
521     (
522         "GSignalQuery",
523         Layout {
524             size: size_of::<GSignalQuery>(),
525             alignment: align_of::<GSignalQuery>(),
526         },
527     ),
528     (
529         "GTypeClass",
530         Layout {
531             size: size_of::<GTypeClass>(),
532             alignment: align_of::<GTypeClass>(),
533         },
534     ),
535     (
536         "GTypeDebugFlags",
537         Layout {
538             size: size_of::<GTypeDebugFlags>(),
539             alignment: align_of::<GTypeDebugFlags>(),
540         },
541     ),
542     (
543         "GTypeFlags",
544         Layout {
545             size: size_of::<GTypeFlags>(),
546             alignment: align_of::<GTypeFlags>(),
547         },
548     ),
549     (
550         "GTypeFundamentalFlags",
551         Layout {
552             size: size_of::<GTypeFundamentalFlags>(),
553             alignment: align_of::<GTypeFundamentalFlags>(),
554         },
555     ),
556     (
557         "GTypeFundamentalInfo",
558         Layout {
559             size: size_of::<GTypeFundamentalInfo>(),
560             alignment: align_of::<GTypeFundamentalInfo>(),
561         },
562     ),
563     (
564         "GTypeInfo",
565         Layout {
566             size: size_of::<GTypeInfo>(),
567             alignment: align_of::<GTypeInfo>(),
568         },
569     ),
570     (
571         "GTypeInstance",
572         Layout {
573             size: size_of::<GTypeInstance>(),
574             alignment: align_of::<GTypeInstance>(),
575         },
576     ),
577     (
578         "GTypeInterface",
579         Layout {
580             size: size_of::<GTypeInterface>(),
581             alignment: align_of::<GTypeInterface>(),
582         },
583     ),
584     (
585         "GTypeModule",
586         Layout {
587             size: size_of::<GTypeModule>(),
588             alignment: align_of::<GTypeModule>(),
589         },
590     ),
591     (
592         "GTypeModuleClass",
593         Layout {
594             size: size_of::<GTypeModuleClass>(),
595             alignment: align_of::<GTypeModuleClass>(),
596         },
597     ),
598     (
599         "GTypePluginClass",
600         Layout {
601             size: size_of::<GTypePluginClass>(),
602             alignment: align_of::<GTypePluginClass>(),
603         },
604     ),
605     (
606         "GTypeQuery",
607         Layout {
608             size: size_of::<GTypeQuery>(),
609             alignment: align_of::<GTypeQuery>(),
610         },
611     ),
612     (
613         "GTypeValueTable",
614         Layout {
615             size: size_of::<GTypeValueTable>(),
616             alignment: align_of::<GTypeValueTable>(),
617         },
618     ),
619     (
620         "GValue",
621         Layout {
622             size: size_of::<GValue>(),
623             alignment: align_of::<GValue>(),
624         },
625     ),
626     (
627         "GValueArray",
628         Layout {
629             size: size_of::<GValueArray>(),
630             alignment: align_of::<GValueArray>(),
631         },
632     ),
633     (
634         "GWeakRef",
635         Layout {
636             size: size_of::<GWeakRef>(),
637             alignment: align_of::<GWeakRef>(),
638         },
639     ),
640 ];
641 
642 const RUST_CONSTANTS: &[(&str, &str)] = &[
643     ("(guint) G_BINDING_BIDIRECTIONAL", "1"),
644     ("(guint) G_BINDING_DEFAULT", "0"),
645     ("(guint) G_BINDING_INVERT_BOOLEAN", "4"),
646     ("(guint) G_BINDING_SYNC_CREATE", "2"),
647     ("(guint) G_CONNECT_AFTER", "1"),
648     ("(guint) G_CONNECT_SWAPPED", "2"),
649     ("(guint) G_PARAM_CONSTRUCT", "4"),
650     ("(guint) G_PARAM_CONSTRUCT_ONLY", "8"),
651     ("(guint) G_PARAM_DEPRECATED", "2147483648"),
652     ("(guint) G_PARAM_EXPLICIT_NOTIFY", "1073741824"),
653     ("(guint) G_PARAM_LAX_VALIDATION", "16"),
654     ("G_PARAM_MASK", "255"),
655     ("(guint) G_PARAM_PRIVATE", "32"),
656     ("(guint) G_PARAM_READABLE", "1"),
657     ("(guint) G_PARAM_READWRITE", "3"),
658     ("(guint) G_PARAM_STATIC_BLURB", "128"),
659     ("(guint) G_PARAM_STATIC_NAME", "32"),
660     ("(guint) G_PARAM_STATIC_NICK", "64"),
661     ("G_PARAM_STATIC_STRINGS", "224"),
662     ("G_PARAM_USER_SHIFT", "8"),
663     ("(guint) G_PARAM_WRITABLE", "2"),
664     ("(guint) G_SIGNAL_ACTION", "32"),
665     ("(guint) G_SIGNAL_DEPRECATED", "256"),
666     ("(guint) G_SIGNAL_DETAILED", "16"),
667     ("G_SIGNAL_FLAGS_MASK", "511"),
668     ("(guint) G_SIGNAL_MATCH_CLOSURE", "4"),
669     ("(guint) G_SIGNAL_MATCH_DATA", "16"),
670     ("(guint) G_SIGNAL_MATCH_DETAIL", "2"),
671     ("(guint) G_SIGNAL_MATCH_FUNC", "8"),
672     ("(guint) G_SIGNAL_MATCH_ID", "1"),
673     ("G_SIGNAL_MATCH_MASK", "63"),
674     ("(guint) G_SIGNAL_MATCH_UNBLOCKED", "32"),
675     ("(guint) G_SIGNAL_MUST_COLLECT", "128"),
676     ("(guint) G_SIGNAL_NO_HOOKS", "64"),
677     ("(guint) G_SIGNAL_NO_RECURSE", "8"),
678     ("(guint) G_SIGNAL_RUN_CLEANUP", "4"),
679     ("(guint) G_SIGNAL_RUN_FIRST", "1"),
680     ("(guint) G_SIGNAL_RUN_LAST", "2"),
681     ("(guint) G_TYPE_DEBUG_INSTANCE_COUNT", "4"),
682     ("(guint) G_TYPE_DEBUG_MASK", "7"),
683     ("(guint) G_TYPE_DEBUG_NONE", "0"),
684     ("(guint) G_TYPE_DEBUG_OBJECTS", "1"),
685     ("(guint) G_TYPE_DEBUG_SIGNALS", "2"),
686     ("(guint) G_TYPE_FLAG_ABSTRACT", "16"),
687     ("(guint) G_TYPE_FLAG_CLASSED", "1"),
688     ("(guint) G_TYPE_FLAG_DEEP_DERIVABLE", "8"),
689     ("(guint) G_TYPE_FLAG_DERIVABLE", "4"),
690     ("(guint) G_TYPE_FLAG_INSTANTIATABLE", "2"),
691     ("G_TYPE_FLAG_RESERVED_ID_BIT", "1"),
692     ("(guint) G_TYPE_FLAG_VALUE_ABSTRACT", "32"),
693     ("G_TYPE_FUNDAMENTAL_MAX", "255"),
694     ("G_TYPE_FUNDAMENTAL_SHIFT", "2"),
695     ("G_TYPE_RESERVED_BSE_FIRST", "32"),
696     ("G_TYPE_RESERVED_BSE_LAST", "48"),
697     ("G_TYPE_RESERVED_GLIB_FIRST", "22"),
698     ("G_TYPE_RESERVED_GLIB_LAST", "31"),
699     ("G_TYPE_RESERVED_USER_FIRST", "49"),
700     ("G_VALUE_INTERNED_STRING", "268435456"),
701     ("G_VALUE_NOCOPY_CONTENTS", "134217728"),
702 ];
703