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