1 #define NOINLINE __attribute__((noinline))
2 #define NODISCARD [[nodiscard]]
3 
4 
5 #include <cstdarg>
6 #include <cstdint>
7 #include <cstdlib>
8 #include <new>
9 
10 enum class FillRule : uint8_t {
11   A,
12   B,
13 };
14 
15 /// This will have a destructor manually implemented via variant_body, and
16 /// similarly a Drop impl in Rust.
17 template<typename T>
18 struct OwnedSlice {
19   uintptr_t len;
20   T *ptr;
~OwnedSliceOwnedSlice21   ~OwnedSlice() {}
22 };
23 
24 template<typename LengthPercentage>
25 struct Polygon {
26   FillRule fill;
27   OwnedSlice<LengthPercentage> coordinates;
28 };
29 
30 template<typename T>
31 struct Foo {
32   enum class Tag : uint8_t {
33     Bar,
34     Polygon1,
35     Slice1,
36     Slice2,
37     Slice3,
38     Slice4,
39   };
40 
41   struct Polygon1_Body {
42     Polygon<T> _0;
43   };
44 
45   struct Slice1_Body {
46     OwnedSlice<T> _0;
47   };
48 
49   struct Slice2_Body {
50     OwnedSlice<int32_t> _0;
51   };
52 
53   struct Slice3_Body {
54     FillRule fill;
55     OwnedSlice<T> coords;
56   };
57 
58   struct Slice4_Body {
59     FillRule fill;
60     OwnedSlice<int32_t> coords;
61   };
62 
63   Tag tag;
64   union {
65     Polygon1_Body polygon1;
66     Slice1_Body slice1;
67     Slice2_Body slice2;
68     Slice3_Body slice3;
69     Slice4_Body slice4;
70   };
71 
BarFoo72   static Foo Bar() {
73     Foo result;
74     result.tag = Tag::Bar;
75     return result;
76   }
77 
IsBarFoo78   bool IsBar() const {
79     return tag == Tag::Bar;
80   }
81 
Polygon1Foo82   static Foo Polygon1(const Polygon<T> &a0) {
83     Foo result;
84     ::new (&result.polygon1._0) (Polygon<T>)(a0);
85     result.tag = Tag::Polygon1;
86     return result;
87   }
88 
IsPolygon1Foo89   bool IsPolygon1() const {
90     return tag == Tag::Polygon1;
91   }
92 
Slice1Foo93   static Foo Slice1(const OwnedSlice<T> &a0) {
94     Foo result;
95     ::new (&result.slice1._0) (OwnedSlice<T>)(a0);
96     result.tag = Tag::Slice1;
97     return result;
98   }
99 
IsSlice1Foo100   bool IsSlice1() const {
101     return tag == Tag::Slice1;
102   }
103 
Slice2Foo104   static Foo Slice2(const OwnedSlice<int32_t> &a0) {
105     Foo result;
106     ::new (&result.slice2._0) (OwnedSlice<int32_t>)(a0);
107     result.tag = Tag::Slice2;
108     return result;
109   }
110 
IsSlice2Foo111   bool IsSlice2() const {
112     return tag == Tag::Slice2;
113   }
114 
Slice3Foo115   static Foo Slice3(const FillRule &aFill,
116                     const OwnedSlice<T> &aCoords) {
117     Foo result;
118     ::new (&result.slice3.fill) (FillRule)(aFill);
119     ::new (&result.slice3.coords) (OwnedSlice<T>)(aCoords);
120     result.tag = Tag::Slice3;
121     return result;
122   }
123 
IsSlice3Foo124   bool IsSlice3() const {
125     return tag == Tag::Slice3;
126   }
127 
Slice4Foo128   static Foo Slice4(const FillRule &aFill,
129                     const OwnedSlice<int32_t> &aCoords) {
130     Foo result;
131     ::new (&result.slice4.fill) (FillRule)(aFill);
132     ::new (&result.slice4.coords) (OwnedSlice<int32_t>)(aCoords);
133     result.tag = Tag::Slice4;
134     return result;
135   }
136 
IsSlice4Foo137   bool IsSlice4() const {
138     return tag == Tag::Slice4;
139   }
140 
141   private:
FooFoo142   Foo() {
143 
144   }
145   public:
146 
147 
~FooFoo148   ~Foo() {
149     switch (tag) {
150       case Tag::Polygon1: polygon1.~Polygon1_Body(); break;
151       case Tag::Slice1: slice1.~Slice1_Body(); break;
152       case Tag::Slice2: slice2.~Slice2_Body(); break;
153       case Tag::Slice3: slice3.~Slice3_Body(); break;
154       case Tag::Slice4: slice4.~Slice4_Body(); break;
155       default: break;
156     }
157   }
158 
FooFoo159   Foo(const Foo& other)
160    : tag(other.tag) {
161     switch (tag) {
162       case Tag::Polygon1: ::new (&polygon1) (Polygon1_Body)(other.polygon1); break;
163       case Tag::Slice1: ::new (&slice1) (Slice1_Body)(other.slice1); break;
164       case Tag::Slice2: ::new (&slice2) (Slice2_Body)(other.slice2); break;
165       case Tag::Slice3: ::new (&slice3) (Slice3_Body)(other.slice3); break;
166       case Tag::Slice4: ::new (&slice4) (Slice4_Body)(other.slice4); break;
167       default: break;
168     }
169   }
operator =Foo170   Foo& operator=(const Foo& other) {
171     if (this != &other) {
172       this->~Foo();
173       new (this) Foo(other);
174     }
175     return *this;
176   }
177 };
178 
179 template<typename T>
180 union Baz {
181   enum class Tag : uint8_t {
182     Bar2,
183     Polygon21,
184     Slice21,
185     Slice22,
186     Slice23,
187     Slice24,
188   };
189 
190   struct Polygon21_Body {
191     Tag tag;
192     Polygon<T> _0;
193   };
194 
195   struct Slice21_Body {
196     Tag tag;
197     OwnedSlice<T> _0;
198   };
199 
200   struct Slice22_Body {
201     Tag tag;
202     OwnedSlice<int32_t> _0;
203   };
204 
205   struct Slice23_Body {
206     Tag tag;
207     FillRule fill;
208     OwnedSlice<T> coords;
209   };
210 
211   struct Slice24_Body {
212     Tag tag;
213     FillRule fill;
214     OwnedSlice<int32_t> coords;
215   };
216 
217   struct {
218     Tag tag;
219   };
220   Polygon21_Body polygon21;
221   Slice21_Body slice21;
222   Slice22_Body slice22;
223   Slice23_Body slice23;
224   Slice24_Body slice24;
225 
Bar2()226   static Baz Bar2() {
227     Baz result;
228     result.tag = Tag::Bar2;
229     return result;
230   }
231 
IsBar2() const232   bool IsBar2() const {
233     return tag == Tag::Bar2;
234   }
235 
Polygon21(const Polygon<T> & a0)236   static Baz Polygon21(const Polygon<T> &a0) {
237     Baz result;
238     ::new (&result.polygon21._0) (Polygon<T>)(a0);
239     result.tag = Tag::Polygon21;
240     return result;
241   }
242 
IsPolygon21() const243   bool IsPolygon21() const {
244     return tag == Tag::Polygon21;
245   }
246 
Slice21(const OwnedSlice<T> & a0)247   static Baz Slice21(const OwnedSlice<T> &a0) {
248     Baz result;
249     ::new (&result.slice21._0) (OwnedSlice<T>)(a0);
250     result.tag = Tag::Slice21;
251     return result;
252   }
253 
IsSlice21() const254   bool IsSlice21() const {
255     return tag == Tag::Slice21;
256   }
257 
Slice22(const OwnedSlice<int32_t> & a0)258   static Baz Slice22(const OwnedSlice<int32_t> &a0) {
259     Baz result;
260     ::new (&result.slice22._0) (OwnedSlice<int32_t>)(a0);
261     result.tag = Tag::Slice22;
262     return result;
263   }
264 
IsSlice22() const265   bool IsSlice22() const {
266     return tag == Tag::Slice22;
267   }
268 
Slice23(const FillRule & aFill,const OwnedSlice<T> & aCoords)269   static Baz Slice23(const FillRule &aFill,
270                      const OwnedSlice<T> &aCoords) {
271     Baz result;
272     ::new (&result.slice23.fill) (FillRule)(aFill);
273     ::new (&result.slice23.coords) (OwnedSlice<T>)(aCoords);
274     result.tag = Tag::Slice23;
275     return result;
276   }
277 
IsSlice23() const278   bool IsSlice23() const {
279     return tag == Tag::Slice23;
280   }
281 
Slice24(const FillRule & aFill,const OwnedSlice<int32_t> & aCoords)282   static Baz Slice24(const FillRule &aFill,
283                      const OwnedSlice<int32_t> &aCoords) {
284     Baz result;
285     ::new (&result.slice24.fill) (FillRule)(aFill);
286     ::new (&result.slice24.coords) (OwnedSlice<int32_t>)(aCoords);
287     result.tag = Tag::Slice24;
288     return result;
289   }
290 
IsSlice24() const291   bool IsSlice24() const {
292     return tag == Tag::Slice24;
293   }
294 
295   private:
Baz()296   Baz() {
297 
298   }
299   public:
300 
301 
~Baz()302   ~Baz() {
303     switch (tag) {
304       case Tag::Polygon21: polygon21.~Polygon21_Body(); break;
305       case Tag::Slice21: slice21.~Slice21_Body(); break;
306       case Tag::Slice22: slice22.~Slice22_Body(); break;
307       case Tag::Slice23: slice23.~Slice23_Body(); break;
308       case Tag::Slice24: slice24.~Slice24_Body(); break;
309       default: break;
310     }
311   }
312 
Baz(const Baz & other)313   Baz(const Baz& other)
314    : tag(other.tag) {
315     switch (tag) {
316       case Tag::Polygon21: ::new (&polygon21) (Polygon21_Body)(other.polygon21); break;
317       case Tag::Slice21: ::new (&slice21) (Slice21_Body)(other.slice21); break;
318       case Tag::Slice22: ::new (&slice22) (Slice22_Body)(other.slice22); break;
319       case Tag::Slice23: ::new (&slice23) (Slice23_Body)(other.slice23); break;
320       case Tag::Slice24: ::new (&slice24) (Slice24_Body)(other.slice24); break;
321       default: break;
322     }
323   }
operator =(const Baz & other)324   Baz& operator=(const Baz& other) {
325     if (this != &other) {
326       this->~Baz();
327       new (this) Baz(other);
328     }
329     return *this;
330   }
331 };
332 
333 union Taz {
334   enum class Tag : uint8_t {
335     Bar3,
336     Taz1,
337     Taz3,
338   };
339 
340   struct Taz1_Body {
341     Tag tag;
342     int32_t _0;
343   };
344 
345   struct Taz3_Body {
346     Tag tag;
347     OwnedSlice<int32_t> _0;
348   };
349 
350   struct {
351     Tag tag;
352   };
353   Taz1_Body taz1;
354   Taz3_Body taz3;
355 
Bar3()356   static Taz Bar3() {
357     Taz result;
358     result.tag = Tag::Bar3;
359     return result;
360   }
361 
IsBar3() const362   bool IsBar3() const {
363     return tag == Tag::Bar3;
364   }
365 
Taz1(const int32_t & a0)366   static Taz Taz1(const int32_t &a0) {
367     Taz result;
368     ::new (&result.taz1._0) (int32_t)(a0);
369     result.tag = Tag::Taz1;
370     return result;
371   }
372 
IsTaz1() const373   bool IsTaz1() const {
374     return tag == Tag::Taz1;
375   }
376 
Taz3(const OwnedSlice<int32_t> & a0)377   static Taz Taz3(const OwnedSlice<int32_t> &a0) {
378     Taz result;
379     ::new (&result.taz3._0) (OwnedSlice<int32_t>)(a0);
380     result.tag = Tag::Taz3;
381     return result;
382   }
383 
IsTaz3() const384   bool IsTaz3() const {
385     return tag == Tag::Taz3;
386   }
387 
388   private:
Taz()389   Taz() {
390 
391   }
392   public:
393 
394 
~Taz()395   ~Taz() {
396     switch (tag) {
397       case Tag::Taz1: taz1.~Taz1_Body(); break;
398       case Tag::Taz3: taz3.~Taz3_Body(); break;
399       default: break;
400     }
401   }
402 
Taz(const Taz & other)403   Taz(const Taz& other)
404    : tag(other.tag) {
405     switch (tag) {
406       case Tag::Taz1: ::new (&taz1) (Taz1_Body)(other.taz1); break;
407       case Tag::Taz3: ::new (&taz3) (Taz3_Body)(other.taz3); break;
408       default: break;
409     }
410   }
operator =(const Taz & other)411   Taz& operator=(const Taz& other) {
412     if (this != &other) {
413       this->~Taz();
414       new (this) Taz(other);
415     }
416     return *this;
417   }
418 };
419 
420 union Tazz {
421   enum class Tag : uint8_t {
422     Bar4,
423     Taz2,
424   };
425 
426   struct Taz2_Body {
427     Tag tag;
428     int32_t _0;
429   };
430 
431   struct {
432     Tag tag;
433   };
434   Taz2_Body taz2;
435 
Bar4()436   static Tazz Bar4() {
437     Tazz result;
438     result.tag = Tag::Bar4;
439     return result;
440   }
441 
IsBar4() const442   bool IsBar4() const {
443     return tag == Tag::Bar4;
444   }
445 
Taz2(const int32_t & a0)446   static Tazz Taz2(const int32_t &a0) {
447     Tazz result;
448     ::new (&result.taz2._0) (int32_t)(a0);
449     result.tag = Tag::Taz2;
450     return result;
451   }
452 
IsTaz2() const453   bool IsTaz2() const {
454     return tag == Tag::Taz2;
455   }
456 
457   private:
Tazz()458   Tazz() {
459 
460   }
461   public:
462 
463 };
464 
465 union Tazzz {
466   enum class Tag : uint8_t {
467     Bar5,
468     Taz5,
469   };
470 
471   struct Taz5_Body {
472     Tag tag;
473     int32_t _0;
474   };
475 
476   struct {
477     Tag tag;
478   };
479   Taz5_Body taz5;
480 
Bar5()481   static Tazzz Bar5() {
482     Tazzz result;
483     result.tag = Tag::Bar5;
484     return result;
485   }
486 
IsBar5() const487   bool IsBar5() const {
488     return tag == Tag::Bar5;
489   }
490 
Taz5(const int32_t & a0)491   static Tazzz Taz5(const int32_t &a0) {
492     Tazzz result;
493     ::new (&result.taz5._0) (int32_t)(a0);
494     result.tag = Tag::Taz5;
495     return result;
496   }
497 
IsTaz5() const498   bool IsTaz5() const {
499     return tag == Tag::Taz5;
500   }
501 
502   private:
Tazzz()503   Tazzz() {
504 
505   }
506   public:
507 
508 
~Tazzz()509   ~Tazzz() {
510     switch (tag) {
511       case Tag::Taz5: taz5.~Taz5_Body(); break;
512       default: break;
513     }
514   }
515 
Tazzz(const Tazzz & other)516   Tazzz(const Tazzz& other)
517    : tag(other.tag) {
518     switch (tag) {
519       case Tag::Taz5: ::new (&taz5) (Taz5_Body)(other.taz5); break;
520       default: break;
521     }
522   }
523 };
524 
525 union Tazzzz {
526   enum class Tag : uint8_t {
527     Taz6,
528     Taz7,
529   };
530 
531   struct Taz6_Body {
532     Tag tag;
533     int32_t _0;
534   };
535 
536   struct Taz7_Body {
537     Tag tag;
538     uint32_t _0;
539   };
540 
541   struct {
542     Tag tag;
543   };
544   Taz6_Body taz6;
545   Taz7_Body taz7;
546 
Taz6(const int32_t & a0)547   static Tazzzz Taz6(const int32_t &a0) {
548     Tazzzz result;
549     ::new (&result.taz6._0) (int32_t)(a0);
550     result.tag = Tag::Taz6;
551     return result;
552   }
553 
IsTaz6() const554   bool IsTaz6() const {
555     return tag == Tag::Taz6;
556   }
557 
Taz7(const uint32_t & a0)558   static Tazzzz Taz7(const uint32_t &a0) {
559     Tazzzz result;
560     ::new (&result.taz7._0) (uint32_t)(a0);
561     result.tag = Tag::Taz7;
562     return result;
563   }
564 
IsTaz7() const565   bool IsTaz7() const {
566     return tag == Tag::Taz7;
567   }
568 
569   private:
Tazzzz()570   Tazzzz() {
571 
572   }
573   public:
574 
575 
~Tazzzz()576   ~Tazzzz() {
577     switch (tag) {
578       case Tag::Taz6: taz6.~Taz6_Body(); break;
579       case Tag::Taz7: taz7.~Taz7_Body(); break;
580 
581     }
582   }
583 
Tazzzz(const Tazzzz & other)584   Tazzzz(const Tazzzz& other)
585    : tag(other.tag) {
586     switch (tag) {
587       case Tag::Taz6: ::new (&taz6) (Taz6_Body)(other.taz6); break;
588       case Tag::Taz7: ::new (&taz7) (Taz7_Body)(other.taz7); break;
589 
590     }
591   }
operator =(const Tazzzz & other)592   Tazzzz& operator=(const Tazzzz& other) {
593     if (this != &other) {
594       this->~Tazzzz();
595       new (this) Tazzzz(other);
596     }
597     return *this;
598   }
599 };
600 
601 union Qux {
602   enum class Tag : uint8_t {
603     Qux1,
604     Qux2,
605   };
606 
607   struct Qux1_Body {
608     Tag tag;
609     int32_t _0;
610 
operator ==Qux::Qux1_Body611     bool operator==(const Qux1_Body& other) const {
612       return _0 == other._0;
613     }
614   };
615 
616   struct Qux2_Body {
617     Tag tag;
618     uint32_t _0;
619 
operator ==Qux::Qux2_Body620     bool operator==(const Qux2_Body& other) const {
621       return _0 == other._0;
622     }
623   };
624 
625   struct {
626     Tag tag;
627   };
628   Qux1_Body qux1;
629   Qux2_Body qux2;
630 
Qux1(const int32_t & a0)631   static Qux Qux1(const int32_t &a0) {
632     Qux result;
633     ::new (&result.qux1._0) (int32_t)(a0);
634     result.tag = Tag::Qux1;
635     return result;
636   }
637 
IsQux1() const638   bool IsQux1() const {
639     return tag == Tag::Qux1;
640   }
641 
Qux2(const uint32_t & a0)642   static Qux Qux2(const uint32_t &a0) {
643     Qux result;
644     ::new (&result.qux2._0) (uint32_t)(a0);
645     result.tag = Tag::Qux2;
646     return result;
647   }
648 
IsQux2() const649   bool IsQux2() const {
650     return tag == Tag::Qux2;
651   }
652 
operator ==(const Qux & other) const653   NODISCARD bool operator==(const Qux& other) const {
654     if (tag != other.tag) {
655       return false;
656     }
657     switch (tag) {
658       case Tag::Qux1: return qux1 == other.qux1;
659       case Tag::Qux2: return qux2 == other.qux2;
660 
661     }
662     return true;
663   }
664 
operator !=(const Qux & other) const665   NODISCARD bool operator!=(const Qux& other) const {
666     return !(*this == other);
667   }
668 
669   private:
Qux()670   Qux() {
671 
672   }
673   public:
674 
675 
~Qux()676   NOINLINE ~Qux() {
677     switch (tag) {
678       case Tag::Qux1: qux1.~Qux1_Body(); break;
679       case Tag::Qux2: qux2.~Qux2_Body(); break;
680 
681     }
682   }
683 
Qux(const Qux & other)684   NOINLINE Qux(const Qux& other)
685    : tag(other.tag) {
686     switch (tag) {
687       case Tag::Qux1: ::new (&qux1) (Qux1_Body)(other.qux1); break;
688       case Tag::Qux2: ::new (&qux2) (Qux2_Body)(other.qux2); break;
689 
690     }
691   }
operator =(const Qux & other)692   NOINLINE Qux& operator=(const Qux& other) {
693     if (this != &other) {
694       this->~Qux();
695       new (this) Qux(other);
696     }
697     return *this;
698   }
699 };
700 
701 extern "C" {
702 
703 void root(const Foo<uint32_t> *a,
704           const Baz<int32_t> *b,
705           const Taz *c,
706           Tazz d,
707           const Tazzz *e,
708           const Tazzzz *f,
709           const Qux *g);
710 
711 } // extern "C"
712